diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index fe83fe1438ce..b297cd89cb90 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/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 &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 &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 &Operands) { SMLoc S = Parser.getTok().getLoc(); @@ -1121,12 +1181,27 @@ ParseOperand(SmallVectorImpl &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 &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 A(ThePPC32Target); diff --git a/llvm/test/CodeGen/PowerPC/hello-reloc.s b/llvm/test/CodeGen/PowerPC/hello-reloc.s index 9bbfb3817890..1e3fb8fb0e71 100644 --- a/llvm/test/CodeGen/PowerPC/hello-reloc.s +++ b/llvm/test/CodeGen/PowerPC/hello-reloc.s @@ -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: