mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 06:30:39 +00:00
[Powerpc darwin] AsmParser Base implementation.
This is a base implementation of the powerpc-apple-darwin asm parser dialect. * Enables infrastructure (essentially isDarwin()) and fixes up the parsing of asm directives to separate out ELF and MachO/Darwin additions. * Enables parsing of {r,f,v}XX as register identifiers. * Enables parsing of lo16() hi16() and ha16() as modifiers. The changes to the test case are from David Fang (fangism). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197324 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
da48260ed4
commit
771005ce98
@ -177,6 +177,7 @@ class PPCAsmParser : public MCTargetAsmParser {
|
||||
MCAsmParser &Parser;
|
||||
const MCInstrInfo &MII;
|
||||
bool IsPPC64;
|
||||
bool IsDarwin;
|
||||
|
||||
MCAsmParser &getParser() const { return Parser; }
|
||||
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
|
||||
@ -185,6 +186,7 @@ class PPCAsmParser : public MCTargetAsmParser {
|
||||
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
|
||||
|
||||
bool isPPC64() const { return IsPPC64; }
|
||||
bool isDarwin() const { return IsDarwin; }
|
||||
|
||||
bool MatchRegisterName(const AsmToken &Tok,
|
||||
unsigned &RegNo, int64_t &IntVal);
|
||||
@ -195,12 +197,14 @@ class PPCAsmParser : public MCTargetAsmParser {
|
||||
PPCMCExpr::VariantKind &Variant);
|
||||
const MCExpr *FixupVariantKind(const MCExpr *E);
|
||||
bool ParseExpression(const MCExpr *&EVal);
|
||||
bool ParseDarwinExpression(const MCExpr *&EVal);
|
||||
|
||||
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
|
||||
bool ParseDirectiveWord(unsigned Size, SMLoc L);
|
||||
bool ParseDirectiveTC(unsigned Size, SMLoc L);
|
||||
bool ParseDirectiveMachine(SMLoc L);
|
||||
bool ParseDarwinDirectiveMachine(SMLoc L);
|
||||
|
||||
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
@ -227,6 +231,7 @@ public:
|
||||
Triple TheTriple(STI.getTargetTriple());
|
||||
IsPPC64 = (TheTriple.getArch() == Triple::ppc64 ||
|
||||
TheTriple.getArch() == Triple::ppc64le);
|
||||
IsDarwin = TheTriple.isMacOSX();
|
||||
// Initialize the set of available features.
|
||||
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
|
||||
}
|
||||
@ -1081,10 +1086,16 @@ FixupVariantKind(const MCExpr *E) {
|
||||
llvm_unreachable("Invalid expression kind!");
|
||||
}
|
||||
|
||||
/// Parse an expression. This differs from the default "parseExpression"
|
||||
/// in that it handles complex \code @l/@ha \endcode modifiers.
|
||||
/// ParseExpression. This differs from the default "parseExpression" in that
|
||||
/// it handles modifiers.
|
||||
bool PPCAsmParser::
|
||||
ParseExpression(const MCExpr *&EVal) {
|
||||
|
||||
if (isDarwin())
|
||||
return ParseDarwinExpression(EVal);
|
||||
|
||||
// (ELF Platforms)
|
||||
// Handle \code @l/@ha \endcode
|
||||
if (getParser().parseExpression(EVal))
|
||||
return true;
|
||||
|
||||
@ -1098,6 +1109,55 @@ ParseExpression(const MCExpr *&EVal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDarwinExpression. (MachO Platforms)
|
||||
/// This differs from the default "parseExpression" in that it handles detection
|
||||
/// of the \code hi16(), ha16() and lo16() \endcode modifiers. At present,
|
||||
/// parseExpression() doesn't recognise the modifiers when in the Darwin/MachO
|
||||
/// syntax form so it is done here. TODO: Determine if there is merit in arranging
|
||||
/// for this to be done at a higher level.
|
||||
bool PPCAsmParser::
|
||||
ParseDarwinExpression(const MCExpr *&EVal) {
|
||||
PPCMCExpr::VariantKind Variant = PPCMCExpr::VK_PPC_None;
|
||||
switch (getLexer().getKind()) {
|
||||
default:
|
||||
break;
|
||||
case AsmToken::Identifier:
|
||||
// Compiler-generated Darwin identifiers begin with L,l,_ or "; thus
|
||||
// something starting with any other char should be part of the
|
||||
// asm syntax. If handwritten asm includes an identifier like lo16,
|
||||
// then all bets are off - but no-one would do that, right?
|
||||
StringRef poss = Parser.getTok().getString();
|
||||
if (poss.equals_lower("lo16")) {
|
||||
Variant = PPCMCExpr::VK_PPC_LO;
|
||||
} else if (poss.equals_lower("hi16")) {
|
||||
Variant = PPCMCExpr::VK_PPC_HI;
|
||||
} else if (poss.equals_lower("ha16")) {
|
||||
Variant = PPCMCExpr::VK_PPC_HA;
|
||||
}
|
||||
if (Variant != PPCMCExpr::VK_PPC_None) {
|
||||
Parser.Lex(); // Eat the xx16
|
||||
if (getLexer().isNot(AsmToken::LParen))
|
||||
return Error(Parser.getTok().getLoc(), "expected '('");
|
||||
Parser.Lex(); // Eat the '('
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (getParser().parseExpression(EVal))
|
||||
return true;
|
||||
|
||||
if (Variant != PPCMCExpr::VK_PPC_None) {
|
||||
if (getLexer().isNot(AsmToken::RParen))
|
||||
return Error(Parser.getTok().getLoc(), "expected ')'");
|
||||
Parser.Lex(); // Eat the ')'
|
||||
EVal = PPCMCExpr::Create(Variant, EVal, false, getParser().getContext());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseOperand
|
||||
/// This handles registers in the form 'NN', '%rNN' for ELF platforms and
|
||||
/// rNN for MachO.
|
||||
bool PPCAsmParser::
|
||||
ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
SMLoc S = Parser.getTok().getLoc();
|
||||
@ -1121,12 +1181,27 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
}
|
||||
return Error(S, "invalid register name");
|
||||
|
||||
case AsmToken::Identifier:
|
||||
// Note that non-register-name identifiers from the compiler will begin
|
||||
// with '_', 'L'/'l' or '"'. Of course, handwritten asm could include
|
||||
// identifiers like r31foo - so we fall through in the event that parsing
|
||||
// a register name fails.
|
||||
if (isDarwin()) {
|
||||
unsigned RegNo;
|
||||
int64_t IntVal;
|
||||
if (!MatchRegisterName(Parser.getTok(), RegNo, IntVal)) {
|
||||
Parser.Lex(); // Eat the identifier token.
|
||||
Op = PPCOperand::CreateImm(IntVal, S, E, isPPC64());
|
||||
Operands.push_back(Op);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Fall-through to process non-register-name identifiers as expression.
|
||||
// All other expressions
|
||||
case AsmToken::LParen:
|
||||
case AsmToken::Plus:
|
||||
case AsmToken::Minus:
|
||||
case AsmToken::Integer:
|
||||
case AsmToken::Identifier:
|
||||
case AsmToken::Dot:
|
||||
case AsmToken::Dollar:
|
||||
if (!ParseExpression(EVal))
|
||||
@ -1177,11 +1252,25 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
break;
|
||||
|
||||
case AsmToken::Integer:
|
||||
if (getParser().parseAbsoluteExpression(IntVal) ||
|
||||
if (!isDarwin()) {
|
||||
if (getParser().parseAbsoluteExpression(IntVal) ||
|
||||
IntVal < 0 || IntVal > 31)
|
||||
return Error(S, "invalid register number");
|
||||
} else {
|
||||
return Error(S, "unexpected integer value");
|
||||
}
|
||||
break;
|
||||
|
||||
case AsmToken::Identifier:
|
||||
if (isDarwin()) {
|
||||
unsigned RegNo;
|
||||
if (!MatchRegisterName(Parser.getTok(), RegNo, IntVal)) {
|
||||
Parser.Lex(); // Eat the identifier token.
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Fall-through..
|
||||
|
||||
default:
|
||||
return Error(S, "invalid memory operand");
|
||||
}
|
||||
@ -1261,14 +1350,19 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
||||
/// ParseDirective parses the PPC specific directives
|
||||
bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
StringRef IDVal = DirectiveID.getIdentifier();
|
||||
if (IDVal == ".word")
|
||||
return ParseDirectiveWord(2, DirectiveID.getLoc());
|
||||
if (IDVal == ".llong")
|
||||
return ParseDirectiveWord(8, DirectiveID.getLoc());
|
||||
if (IDVal == ".tc")
|
||||
return ParseDirectiveTC(isPPC64()? 8 : 4, DirectiveID.getLoc());
|
||||
if (IDVal == ".machine")
|
||||
return ParseDirectiveMachine(DirectiveID.getLoc());
|
||||
if (!isDarwin()) {
|
||||
if (IDVal == ".word")
|
||||
return ParseDirectiveWord(2, DirectiveID.getLoc());
|
||||
if (IDVal == ".llong")
|
||||
return ParseDirectiveWord(8, DirectiveID.getLoc());
|
||||
if (IDVal == ".tc")
|
||||
return ParseDirectiveTC(isPPC64()? 8 : 4, DirectiveID.getLoc());
|
||||
if (IDVal == ".machine")
|
||||
return ParseDirectiveMachine(DirectiveID.getLoc());
|
||||
} else {
|
||||
if (IDVal == ".machine")
|
||||
return ParseDarwinDirectiveMachine(DirectiveID.getLoc());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1314,7 +1408,7 @@ bool PPCAsmParser::ParseDirectiveTC(unsigned Size, SMLoc L) {
|
||||
return ParseDirectiveWord(Size, L);
|
||||
}
|
||||
|
||||
/// ParseDirectiveMachine
|
||||
/// ParseDirectiveMachine (ELF platforms)
|
||||
/// ::= .machine [ cpu | "push" | "pop" ]
|
||||
bool PPCAsmParser::ParseDirectiveMachine(SMLoc L) {
|
||||
if (getLexer().isNot(AsmToken::Identifier) &&
|
||||
@ -1338,6 +1432,33 @@ bool PPCAsmParser::ParseDirectiveMachine(SMLoc L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDarwinDirectiveMachine (Mach-o platforms)
|
||||
/// ::= .machine cpu-identifier
|
||||
bool PPCAsmParser::ParseDarwinDirectiveMachine(SMLoc L) {
|
||||
if (getLexer().isNot(AsmToken::Identifier) &&
|
||||
getLexer().isNot(AsmToken::String))
|
||||
return Error(L, "unexpected token in directive");
|
||||
|
||||
StringRef CPU = Parser.getTok().getIdentifier();
|
||||
Parser.Lex();
|
||||
|
||||
// FIXME: this is only the 'default' set of cpu variants.
|
||||
// However we don't act on this information at present, this is simply
|
||||
// allowing parsing to proceed with minimal sanity checking.
|
||||
if (CPU != "ppc7400" && CPU != "ppc" && CPU != "ppc64")
|
||||
return Error(L, "unrecognized cpu type");
|
||||
|
||||
if (isPPC64() && (CPU == "ppc7400" || CPU == "ppc"))
|
||||
return Error(L, "wrong cpu type specified for 64bit");
|
||||
if (!isPPC64() && CPU == "ppc64")
|
||||
return Error(L, "wrong cpu type specified for 32bit");
|
||||
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return Error(L, "unexpected token in directive");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Force static initialization.
|
||||
extern "C" void LLVMInitializePowerPCAsmParser() {
|
||||
RegisterMCAsmParser<PPCAsmParser> A(ThePPC32Target);
|
||||
|
@ -1,14 +1,10 @@
|
||||
; This tests for the basic implementation of PPCMachObjectWriter.cpp,
|
||||
; which is responsible for writing mach-o relocation entries for (PIC)
|
||||
; PowerPC objects.
|
||||
; NOTE: Darwin PPC asm syntax is not yet supported by PPCAsmParser,
|
||||
; so this test case uses ELF PPC asm syntax to produce a mach-o object.
|
||||
; Once PPCAsmParser supports darwin asm syntax, this test case should
|
||||
; be updated accordingly.
|
||||
|
||||
; RUN: llvm-mc -filetype=obj -relocation-model=pic -mcpu=g4 -triple=powerpc-apple-darwin8 %s -o - | llvm-readobj -relocations | FileCheck -check-prefix=DARWIN-G4-DUMP %s
|
||||
|
||||
; .machine ppc7400
|
||||
.machine ppc7400
|
||||
.section __TEXT,__textcoal_nt,coalesced,pure_instructions
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.section __TEXT,__text,regular,pure_instructions
|
||||
@ -16,40 +12,40 @@
|
||||
.align 4
|
||||
_main: ; @main
|
||||
; BB#0: ; %entry
|
||||
mflr 0
|
||||
stw 31, -4(1)
|
||||
stw 0, 8(1)
|
||||
stwu 1, -80(1)
|
||||
mflr r0
|
||||
stw r31, -4(r1)
|
||||
stw r0, 8(r1)
|
||||
stwu r1, -80(r1)
|
||||
bl L0$pb
|
||||
L0$pb:
|
||||
mr 31, 1
|
||||
li 5, 0
|
||||
mr r31, r1
|
||||
li r5, 0
|
||||
mflr 2
|
||||
stw 3, 68(31)
|
||||
stw 5, 72(31)
|
||||
stw 4, 64(31)
|
||||
addis 2, 2, (L_.str-L0$pb)@ha
|
||||
la 3, (L_.str-L0$pb)@l(2)
|
||||
stw r3, 68(r31)
|
||||
stw r5, 72(r31)
|
||||
stw r4, 64(r31)
|
||||
addis r2, r2, ha16(L_.str-L0$pb)
|
||||
la r3, lo16(L_.str-L0$pb)(r2)
|
||||
bl L_puts$stub
|
||||
li 3, 0
|
||||
addi 1, 1, 80
|
||||
lwz 0, 8(1)
|
||||
lwz 31, -4(1)
|
||||
mtlr 0
|
||||
li r3, 0
|
||||
addi r1, r1, 80
|
||||
lwz r0, 8(r1)
|
||||
lwz r31, -4(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align 4
|
||||
L_puts$stub:
|
||||
.indirect_symbol _puts
|
||||
mflr 0
|
||||
mflr r0
|
||||
bcl 20, 31, L_puts$stub$tmp
|
||||
L_puts$stub$tmp:
|
||||
mflr 11
|
||||
addis 11, 11, (L_puts$lazy_ptr-L_puts$stub$tmp)@ha
|
||||
mtlr 0
|
||||
lwzu 12, (L_puts$lazy_ptr-L_puts$stub$tmp)@l(11)
|
||||
mtctr 12
|
||||
mflr r11
|
||||
addis r11, r11, ha16(L_puts$lazy_ptr-L_puts$stub$tmp)
|
||||
mtlr r0
|
||||
lwzu r12, lo16(L_puts$lazy_ptr-L_puts$stub$tmp)(r11)
|
||||
mtctr r12
|
||||
bctr
|
||||
.section __DATA,__la_symbol_ptr,lazy_symbol_pointers
|
||||
L_puts$lazy_ptr:
|
||||
|
Loading…
Reference in New Issue
Block a user