summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2013-06-20 16:23:52 +0000
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2013-06-20 16:23:52 +0000
commit027e94479c9e69eb3c3c5536fa9990d0b96e9510 (patch)
treee0ff894ae7806fba4e5872840cba830ff5daa4eb /lib
parent0db5379fe643cbe738b4831e337251819cc5dc5d (diff)
downloadllvm-027e94479c9e69eb3c3c5536fa9990d0b96e9510.tar.gz
llvm-027e94479c9e69eb3c3c5536fa9990d0b96e9510.tar.bz2
llvm-027e94479c9e69eb3c3c5536fa9990d0b96e9510.tar.xz
[PowerPC] Optimize @ha/@l constructs
This patch adds support for having the assembler optimize fixups to constructs like "symbol@ha" or "symbol@l" if "symbol" can be resolved at assembler time. This optimization is already present in the PPCMCExpr.cpp code for handling PPC_HA16/PPC_LO16 target expressions. However, those target expression were used only on Darwin targets. This patch changes target expression code so that they are usable also with the GNU assembler (using the @ha / @l syntax instead of the ha16() / lo16() syntax), and changes the MCInst lowering code to generate those target expressions where appropriate. It also changes the asm parser to generate HA16/LO16 target expressions when parsing assembler source that uses the @ha / @l modifiers. The effect is that now the above- mentioned optimization automatically becomes available for those situations too. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184436 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-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);