diff options
author | Iain Sandoe <iain@codesourcery.com> | 2013-12-14 13:34:02 +0000 |
---|---|---|
committer | Iain Sandoe <iain@codesourcery.com> | 2013-12-14 13:34:02 +0000 |
commit | 771005ce98f82b458accb0a6ca83fc683818c629 (patch) | |
tree | c7e5133d6ba5299a7fe5ca905a2bbae261c97a53 /lib/Target/PowerPC/AsmParser | |
parent | da48260ed46b61865639932c1013b417123b5028 (diff) | |
download | llvm-771005ce98f82b458accb0a6ca83fc683818c629.tar.gz llvm-771005ce98f82b458accb0a6ca83fc683818c629.tar.bz2 llvm-771005ce98f82b458accb0a6ca83fc683818c629.tar.xz |
[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
Diffstat (limited to 'lib/Target/PowerPC/AsmParser')
-rw-r--r-- | lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 147 |
1 files changed, 134 insertions, 13 deletions
diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index fe83fe1438..b297cd89cb 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -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); |