[PowerPC] Clean up generation of ha16() / lo16() markers

When targeting the Darwin assembler, we need to generate markers ha16() and
lo16() to designate the high and low parts of a (symbolic) immediate.  This
is necessary not just for plain symbols, but also for certain symbolic
expression, typically along the lines of ha16(A - B).  The latter doesn't
work when simply using VariantKind flags on the symbol reference.
This is why the current back-end uses hacks (explicitly called out as such
via multiple FIXMEs) in the symbolLo/symbolHi print methods.

This patch uses target-defined MCExpr codes to represent the Darwin
ha16/lo16 constructs, following along the lines of the equivalent solution
used by the ARM back end to handle their :upper16: / :lower16: markers.
This allows us to get rid of special handling both in the symbolLo/symbolHi
print method and in the common code MCExpr::print routine.  Instead, the
ha16 / lo16 markers are printed simply in a custom print routine for the
target MCExpr types.  (As a result, the symbolLo/symbolHi print methods
can now replaced by a single printS16ImmOperand routine that also handles
symbolic operands.)

The patch also provides a EvaluateAsRelocatableImpl routine to handle
ha16/lo16 constructs.  This is not actually used at the moment by any
in-tree code, but is provided as it makes merging into David Fang's
out-of-tree Mach-O object writer simpler.

Since there is no longer any need to treat VK_PPC_GAS_HA16 and
VK_PPC_DARWIN_HA16 differently, they are merged into a single
VK_PPC_ADDR16_HA (and likewise for the _LO16 types).



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182616 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ulrich Weigand
2013-05-23 22:26:41 +00:00
parent 8c18a6fe37
commit edaa58ee66
12 changed files with 259 additions and 112 deletions

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "PPC.h"
#include "MCTargetDesc/PPCMCExpr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
@ -110,32 +111,32 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;
switch (access) {
case PPCII::MO_HA16: RefKind = isDarwin ?
MCSymbolRefExpr::VK_PPC_DARWIN_HA16 :
MCSymbolRefExpr::VK_PPC_GAS_HA16;
break;
case PPCII::MO_LO16: RefKind = isDarwin ?
MCSymbolRefExpr::VK_PPC_DARWIN_LO16 :
MCSymbolRefExpr::VK_PPC_GAS_LO16;
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;
}
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;
}
}
// FIXME: This isn't right, but we don't have a good way to express this in
// the MC Level, see below.
if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG)
RefKind = MCSymbolRefExpr::VK_None;
const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);
if (!MO.isJTI() && MO.getOffset())
@ -149,10 +150,20 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
const MCExpr *PB = MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), Ctx);
Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx);
// FIXME: We have no way to make the result be VK_PPC_LO16/VK_PPC_HA16,
// since it is not a symbol!
}
// 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;
}
}
return MCOperand::CreateExpr(Expr);
}