diff options
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 92 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp | 30 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h | 10 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCMCInstLower.cpp | 58 |
4 files changed, 144 insertions, 46 deletions
diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 9cf16f08ae..59a5ef9a53 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/PPCMCTargetDesc.h" +#include "MCTargetDesc/PPCMCExpr.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" @@ -126,6 +127,10 @@ class PPCAsmParser : public MCTargetAsmParser { virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); + const MCExpr *ExtractModifierFromExpr(const MCExpr *E, + PPCMCExpr::VariantKind &Variant); + bool ParseExpression(const MCExpr *&EVal); + bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); bool ParseDirectiveWord(unsigned Size, SMLoc L); @@ -540,6 +545,91 @@ ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { return Error(StartLoc, "invalid register name"); } +/// Extract @l/@ha modifier from expression. Recursively scan +/// the expression and check for VK_PPC_ADDR16_HA/VK_PPC_ADDR16_LO +/// symbol variants. If all symbols with modifier use the same +/// variant, return the corresponding PPCMCExpr::VariantKind, +/// and a modified expression using the default symbol variant. +/// Otherwise, return NULL. +const MCExpr *PPCAsmParser:: +ExtractModifierFromExpr(const MCExpr *E, + PPCMCExpr::VariantKind &Variant) { + MCContext &Context = getParser().getContext(); + Variant = PPCMCExpr::VK_PPC_None; + + switch (E->getKind()) { + case MCExpr::Target: + case MCExpr::Constant: + return 0; + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); + + switch (SRE->getKind()) { + case MCSymbolRefExpr::VK_PPC_ADDR16_HA: + Variant = PPCMCExpr::VK_PPC_HA16; + break; + case MCSymbolRefExpr::VK_PPC_ADDR16_LO: + Variant = PPCMCExpr::VK_PPC_LO16; + break; + default: + return 0; + } + + return MCSymbolRefExpr::Create(&SRE->getSymbol(), Context); + } + + case MCExpr::Unary: { + const MCUnaryExpr *UE = cast<MCUnaryExpr>(E); + const MCExpr *Sub = ExtractModifierFromExpr(UE->getSubExpr(), Variant); + if (!Sub) + return 0; + return MCUnaryExpr::Create(UE->getOpcode(), Sub, Context); + } + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); + PPCMCExpr::VariantKind LHSVariant, RHSVariant; + const MCExpr *LHS = ExtractModifierFromExpr(BE->getLHS(), LHSVariant); + const MCExpr *RHS = ExtractModifierFromExpr(BE->getRHS(), RHSVariant); + + if (!LHS && !RHS) + return 0; + + if (!LHS) LHS = BE->getLHS(); + if (!RHS) RHS = BE->getRHS(); + + if (LHSVariant == PPCMCExpr::VK_PPC_None) + Variant = RHSVariant; + else if (RHSVariant == PPCMCExpr::VK_PPC_None) + Variant = LHSVariant; + else if (LHSVariant == RHSVariant) + Variant = LHSVariant; + else + return 0; + + return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, Context); + } + } + + llvm_unreachable("Invalid expression kind!"); +} + +/// Parse an expression. This differs from the default "parseExpression" +/// in that it handles complex @l/@ha modifiers. +bool PPCAsmParser:: +ParseExpression(const MCExpr *&EVal) { + if (getParser().parseExpression(EVal)) + return true; + + PPCMCExpr::VariantKind Variant; + const MCExpr *E = ExtractModifierFromExpr(EVal, Variant); + if (E) + EVal = PPCMCExpr::Create(Variant, E, getParser().getContext()); + + return false; +} + bool PPCAsmParser:: ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { SMLoc S = Parser.getTok().getLoc(); @@ -571,7 +661,7 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { case AsmToken::Identifier: case AsmToken::Dot: case AsmToken::Dollar: - if (!getParser().parseExpression(EVal)) + if (!ParseExpression(EVal)) break; /* fall through */ default: diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp index f0613ff632..3b794fe862 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp @@ -11,25 +11,37 @@ #include "PPCMCExpr.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" using namespace llvm; const PPCMCExpr* PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx) { - return new (Ctx) PPCMCExpr(Kind, Expr); + int AssemblerDialect = Ctx.getAsmInfo()->getAssemblerDialect(); + return new (Ctx) PPCMCExpr(Kind, Expr, AssemblerDialect); } void PPCMCExpr::PrintImpl(raw_ostream &OS) const { - switch (Kind) { - default: llvm_unreachable("Invalid kind!"); - case VK_PPC_HA16: OS << "ha16"; break; - case VK_PPC_LO16: OS << "lo16"; break; - } + if (isDarwinSyntax()) { + switch (Kind) { + default: llvm_unreachable("Invalid kind!"); + case VK_PPC_HA16: OS << "ha16"; break; + case VK_PPC_LO16: OS << "lo16"; break; + } + + OS << '('; + getSubExpr()->print(OS); + OS << ')'; + } else { + getSubExpr()->print(OS); - OS << '('; - getSubExpr()->print(OS); - OS << ')'; + switch (Kind) { + default: llvm_unreachable("Invalid kind!"); + case VK_PPC_HA16: OS << "@ha"; break; + case VK_PPC_LO16: OS << "@l"; break; + } + } } bool diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h index a0805374a4..1b57687996 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h @@ -27,9 +27,11 @@ public: private: const VariantKind Kind; const MCExpr *Expr; + const int AssemblerDialect; - explicit PPCMCExpr(VariantKind _Kind, const MCExpr *_Expr) - : Kind(_Kind), Expr(_Expr) {} + explicit PPCMCExpr(VariantKind _Kind, const MCExpr *_Expr, + int _AssemblerDialect) + : Kind(_Kind), Expr(_Expr), AssemblerDialect(_AssemblerDialect) {} public: /// @name Construction @@ -56,6 +58,10 @@ public: /// getSubExpr - Get the child of this expression. const MCExpr *getSubExpr() const { return Expr; } + /// isDarwinSyntax - True if expression is to be printed using Darwin syntax. + bool isDarwinSyntax() const { return AssemblerDialect == 1; } + + /// @} void PrintImpl(raw_ostream &OS) const; diff --git a/lib/Target/PowerPC/PPCMCInstLower.cpp b/lib/Target/PowerPC/PPCMCInstLower.cpp index ba7efc1880..7cecf2506a 100644 --- a/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -111,30 +111,22 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK; - if (!isDarwin) { - switch (access) { - case PPCII::MO_HA16: - RefKind = MCSymbolRefExpr::VK_PPC_ADDR16_HA; - break; - case PPCII::MO_LO16: - RefKind = MCSymbolRefExpr::VK_PPC_ADDR16_LO; - break; - case PPCII::MO_TPREL16_HA: - RefKind = MCSymbolRefExpr::VK_PPC_TPREL16_HA; - break; - case PPCII::MO_TPREL16_LO: - RefKind = MCSymbolRefExpr::VK_PPC_TPREL16_LO; - break; - case PPCII::MO_DTPREL16_LO: - RefKind = MCSymbolRefExpr::VK_PPC_DTPREL16_LO; - break; - case PPCII::MO_TLSLD16_LO: - RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO; - break; - case PPCII::MO_TOC16_LO: - RefKind = MCSymbolRefExpr::VK_PPC_TOC16_LO; - break; - } + switch (access) { + case PPCII::MO_TPREL16_HA: + RefKind = MCSymbolRefExpr::VK_PPC_TPREL16_HA; + break; + case PPCII::MO_TPREL16_LO: + RefKind = MCSymbolRefExpr::VK_PPC_TPREL16_LO; + break; + case PPCII::MO_DTPREL16_LO: + RefKind = MCSymbolRefExpr::VK_PPC_DTPREL16_LO; + break; + case PPCII::MO_TLSLD16_LO: + RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD16_LO; + break; + case PPCII::MO_TOC16_LO: + RefKind = MCSymbolRefExpr::VK_PPC_TOC16_LO; + break; } const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx); @@ -152,16 +144,14 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx); } - // Add Darwin ha16() / lo16() markers if required. - if (isDarwin) { - switch (access) { - case PPCII::MO_HA16: - Expr = PPCMCExpr::CreateHa16(Expr, Ctx); - break; - case PPCII::MO_LO16: - Expr = PPCMCExpr::CreateLo16(Expr, Ctx); - break; - } + // Add ha16() / lo16() markers if required. + switch (access) { + case PPCII::MO_HA16: + Expr = PPCMCExpr::CreateHa16(Expr, Ctx); + break; + case PPCII::MO_LO16: + Expr = PPCMCExpr::CreateLo16(Expr, Ctx); + break; } return MCOperand::CreateExpr(Expr); |