Pull in r198681 from upstream llvm trunk (by Venkatraman Govindaraju): [Sparc] Add support for parsing sparc asm modifiers such as %hi, %lo etc., Also, correct the offsets for FixupsKindInfo. Introduced here: http://svnweb.freebsd.org/changeset/base/262261 Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -27,11 +27,11 @@ static unsigned adjustFixupValue(unsigned Kind, ui case FK_Data_8: return Value; case Sparc::fixup_sparc_call30: - return Value & 0x3fffffff; + return (Value >> 2) & 0x3fffffff; case Sparc::fixup_sparc_br22: - return Value & 0x3fffff; + return (Value >> 2) & 0x3fffff; case Sparc::fixup_sparc_br19: - return Value & 0x1ffff; + return (Value >> 2) & 0x1ffff; case Sparc::fixup_sparc_hi22: return (Value >> 10) & 0x3fffff; case Sparc::fixup_sparc_lo10: @@ -45,7 +45,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui case Sparc::fixup_sparc_hh: return (Value >> 42) & 0x3fffff; case Sparc::fixup_sparc_hm: - return (Value >>32) & 0x3ff; + return (Value >> 32) & 0x3ff; } } @@ -62,16 +62,16 @@ namespace { const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = { // name offset bits flags - { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_sparc_hi22", 0, 22, 0 }, - { "fixup_sparc_lo10", 0, 10, 0 }, - { "fixup_sparc_h44", 0, 22, 0 }, - { "fixup_sparc_m44", 0, 10, 0 }, - { "fixup_sparc_l44", 0, 12, 0 }, - { "fixup_sparc_hh", 0, 21, 0 }, - { "fixup_sparc_hm", 0, 10, 0 }, + { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_hi22", 10, 22, 0 }, + { "fixup_sparc_lo10", 22, 10, 0 }, + { "fixup_sparc_h44", 10, 22, 0 }, + { "fixup_sparc_m44", 22, 10, 0 }, + { "fixup_sparc_l44", 20, 12, 0 }, + { "fixup_sparc_hh", 10, 22, 0 }, + { "fixup_sparc_hm", 22, 10, 0 }, }; if (Kind < FirstTargetFixupKind) Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -67,6 +67,37 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const OS << ')'; } +SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) +{ + return StringSwitch(name) + .Case("lo", VK_Sparc_LO) + .Case("hi", VK_Sparc_HI) + .Case("h44", VK_Sparc_H44) + .Case("m44", VK_Sparc_M44) + .Case("l44", VK_Sparc_L44) + .Case("hh", VK_Sparc_HH) + .Case("hm", VK_Sparc_HM) + .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) + .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) + .Case("tgd_add", VK_Sparc_TLS_GD_ADD) + .Case("tgd_call", VK_Sparc_TLS_GD_CALL) + .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22) + .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10) + .Case("tldm_add", VK_Sparc_TLS_LDM_ADD) + .Case("tldm_call", VK_Sparc_TLS_LDM_CALL) + .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22) + .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10) + .Case("tldo_add", VK_Sparc_TLS_LDO_ADD) + .Case("tie_hi22", VK_Sparc_TLS_IE_HI22) + .Case("tie_lo10", VK_Sparc_TLS_IE_LO10) + .Case("tie_ld", VK_Sparc_TLS_IE_LD) + .Case("tie_ldx", VK_Sparc_TLS_IE_LDX) + .Case("tie_add", VK_Sparc_TLS_IE_ADD) + .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22) + .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10) + .Default(VK_Sparc_None); +} + bool SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const { Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h @@ -19,6 +19,7 @@ namespace llvm { +class StringRef; class SparcMCExpr : public MCTargetExpr { public: enum VariantKind { @@ -90,6 +91,7 @@ class SparcMCExpr : public MCTargetExpr { static bool classof(const SparcMCExpr *) { return true; } + static VariantKind parseVariantKind(StringRef name); }; Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/SparcMCTargetDesc.h" +#include "MCTargetDesc/SparcMCExpr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" @@ -68,6 +69,7 @@ class SparcAsmParser : public MCTargetAsmParser { // returns true if Tok is matched to a register and returns register in RegNo. bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP, bool isQFP); + bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc); public: SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, @@ -536,15 +538,19 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand unsigned RegNo; if (matchRegisterName(Parser.getTok(), RegNo, false, false)) { Parser.Lex(); // Eat the identifier token. + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E); break; } - // FIXME: Handle modifiers like %hi, %lo etc., + if (matchSparcAsmModifiers(EVal, E)) { + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Op = SparcOperand::CreateImm(EVal, S, E); + } break; case AsmToken::Minus: case AsmToken::Integer: - if (!getParser().parseExpression(EVal)) + if (!getParser().parseExpression(EVal, E)) Op = SparcOperand::CreateImm(EVal, S, E); break; @@ -551,13 +557,11 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand case AsmToken::Identifier: { StringRef Identifier; if (!getParser().parseIdentifier(Identifier)) { - SMLoc E = SMLoc::getFromPointer(Parser.getTok(). - getLoc().getPointer() - 1); + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); - Op = SparcOperand::CreateImm(Res, S, E); } break; @@ -675,7 +679,33 @@ bool SparcAsmParser::matchRegisterName(const AsmTo } +bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, + SMLoc &EndLoc) +{ + AsmToken Tok = Parser.getTok(); + if (!Tok.is(AsmToken::Identifier)) + return false; + StringRef name = Tok.getString(); + + SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name); + + if (VK == SparcMCExpr::VK_Sparc_None) + return false; + + Parser.Lex(); // Eat the identifier. + if (Parser.getTok().getKind() != AsmToken::LParen) + return false; + + Parser.Lex(); // Eat the LParen token. + const MCExpr *subExpr; + if (Parser.parseParenExpression(subExpr, EndLoc)) + return false; + EVal = SparcMCExpr::Create(VK, subExpr, getContext()); + return true; +} + + extern "C" void LLVMInitializeSparcAsmParser() { RegisterMCAsmParser A(TheSparcTarget); RegisterMCAsmParser B(TheSparcV9Target); Index: test/MC/Sparc/sparc-relocations.s =================================================================== --- test/MC/Sparc/sparc-relocations.s +++ test/MC/Sparc/sparc-relocations.s @@ -0,0 +1,33 @@ +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s + + ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A] + ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30 + call foo + + ! CHECK: or %g1, %lo(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A] + ! CHECK-NEXT ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 + or %g1, %lo(sym), %g3 + + ! CHECK: sethi %hi(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: %hi(sym), kind: fixup_sparc_hi22 + sethi %hi(sym), %l0 + + ! CHECK: sethi %h44(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: %h44(sym), kind: fixup_sparc_h44 + sethi %h44(sym), %l0 + + ! CHECK: or %g1, %m44(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A] + ! CHECK-NEXT ! fixup A - offset: 0, value: %m44(sym), kind: fixup_sparc_m44 + or %g1, %m44(sym), %g3 + + ! CHECK: or %g1, %l44(sym), %g3 ! encoding: [0x86,0x10,0b0110AAAA,A] + ! CHECK-NEXT ! fixup A - offset: 0, value: %l44(sym), kind: fixup_sparc_l44 + or %g1, %l44(sym), %g3 + + ! CHECK: sethi %hh(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: %hh(sym), kind: fixup_sparc_hh + sethi %hh(sym), %l0 + + ! CHECK: or %g1, %hm(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A] + ! CHECK-NEXT ! fixup A - offset: 0, value: %hm(sym), kind: fixup_sparc_hm + or %g1, %hm(sym), %g3 Index: test/MC/Sparc/sparc-ctrl-instructions.s =================================================================== --- test/MC/Sparc/sparc-ctrl-instructions.s +++ test/MC/Sparc/sparc-ctrl-instructions.s @@ -1,23 +1,33 @@ ! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s ! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s - ! CHECK: call foo + ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A] + ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30 call foo - ! CHECK: call %g1+%i2 + ! CHECK: call %g1+%i2 ! encoding: [0x9f,0xc0,0x40,0x1a] call %g1 + %i2 - ! CHECK: call %o1+8 + ! CHECK: call %o1+8 ! encoding: [0x9f,0xc2,0x60,0x08] call %o1 + 8 - ! CHECK: call %g1 + ! CHECK: call %g1 ! encoding: [0x9f,0xc0,0x60,0x00] call %g1 - ! CHECK: jmp %g1+%i2 + ! CHECK: call %g1+%lo(sym) ! encoding: [0x9f,0xc0,0b011000AA,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 + call %g1+%lo(sym) + + ! CHECK: jmp %g1+%i2 ! encoding: [0x81,0xc0,0x40,0x1a] jmp %g1 + %i2 - ! CHECK: jmp %o1+8 + ! CHECK: jmp %o1+8 ! encoding: [0x81,0xc2,0x60,0x08] jmp %o1 + 8 - ! CHECK: jmp %g1 + ! CHECK: jmp %g1 ! encoding: [0x81,0xc0,0x60,0x00] jmp %g1 + + ! CHECK: jmp %g1+%lo(sym) ! encoding: [0x81,0xc0,0b011000AA,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10 + jmp %g1+%lo(sym) +