summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp92
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp30
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h10
-rw-r--r--lib/Target/PowerPC/PPCMCInstLower.cpp58
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);