aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMMCInstLower.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMMCInstLower.cpp')
-rw-r--r--lib/Target/ARM/ARMMCInstLower.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp
index 88e654d281..1bd2a93a8b 100644
--- a/lib/Target/ARM/ARMMCInstLower.cpp
+++ b/lib/Target/ARM/ARMMCInstLower.cpp
@@ -123,3 +123,57 @@ void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
OutMI.addOperand(MCOp);
}
}
+
+// @LOCALMOD-BEGIN
+// Unlike LowerARMMachineInstrToMCInst, the opcode has already been set.
+// Otherwise, this is like LowerARMMachineInstrToMCInst, but with special
+// handling where the "immediate" is PC Relative
+// (used for MOVi16PIC / MOVTi16PIC, etc. -- see .td file)
+void llvm::LowerARMMachineInstrToMCInstPCRel(const MachineInstr *MI,
+ MCInst &OutMI,
+ ARMAsmPrinter &AP,
+ unsigned ImmIndex,
+ unsigned PCIndex,
+ MCSymbol *PCLabel,
+ unsigned PCAdjustment) {
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ if (i == ImmIndex) {
+ MCContext &Ctx = AP.OutContext;
+ const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, Ctx);
+ if (PCAdjustment) {
+ const MCExpr *AdjExpr = MCConstantExpr::Create(PCAdjustment, Ctx);
+ PCRelExpr = MCBinaryExpr::CreateAdd(PCRelExpr, AdjExpr, Ctx);
+ }
+
+ // Get the usual symbol operand, then subtract the PCRelExpr.
+ const MachineOperand &MOImm = MI->getOperand(ImmIndex);
+ MCOperand SymOp;
+ bool DidLower = AP.lowerOperand(MOImm, SymOp);
+ assert (DidLower && "Immediate-like operand should have been lowered");
+
+ const MCExpr *Expr = SymOp.getExpr();
+ ARMMCExpr::VariantKind TargetKind = ARMMCExpr::VK_ARM_None;
+ /* Unwrap and rewrap the ARMMCExpr */
+ if (Expr->getKind() == MCExpr::Target) {
+ const ARMMCExpr *TargetExpr = cast<ARMMCExpr>(Expr);
+ TargetKind = TargetExpr->getKind();
+ Expr = TargetExpr->getSubExpr();
+ }
+ Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, Ctx);
+ if (TargetKind != ARMMCExpr::VK_ARM_None) {
+ Expr = ARMMCExpr::Create(TargetKind, Expr, Ctx);
+ }
+ MCOperand MCOp = MCOperand::CreateExpr(Expr);
+ OutMI.addOperand(MCOp);
+ } else if (i == PCIndex) { // dummy index already handled as PCLabel
+ continue;
+ } else {
+ MCOperand MCOp;
+ if (AP.lowerOperand(MI->getOperand(i), MCOp)) {
+ OutMI.addOperand(MCOp);
+ }
+ }
+ }
+}
+// @LOCALMOD-END