summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/ARM
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2015-01-02 14:55:02 +0000
committerdim <dim@FreeBSD.org>2015-01-02 14:55:02 +0000
commitad057890048fdd957ffc50de442f15f365059e1b (patch)
treecc7623f761930438ec32e49a0cea5707db154127 /contrib/llvm/lib/Target/ARM
parent110917eb46c5ac715474ac8ab0a6f2566827d416 (diff)
downloadFreeBSD-src-ad057890048fdd957ffc50de442f15f365059e1b.zip
FreeBSD-src-ad057890048fdd957ffc50de442f15f365059e1b.tar.gz
Pull in r222587 from upstream llvm trunk (by Jörg Sonnenberger):
Fix transformation of add with pc argument to adr for non-immediate arguments. This fixes an "Unimplemented" error when assembling certain ARM add instructions with pc-relative arguments. Reported by: sbruno PR: 196412, 196423
Diffstat (limited to 'contrib/llvm/lib/Target/ARM')
-rw-r--r--contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp30
1 files changed, 25 insertions, 5 deletions
diff --git a/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index be3b9d4..faff9a7 100644
--- a/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -314,7 +314,7 @@ class ARMAsmParser : public MCTargetAsmParser {
void cvtThumbBranches(MCInst &Inst, const OperandVector &);
bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
- bool processInstruction(MCInst &Inst, const OperandVector &Ops);
+ bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out);
bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands);
bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands);
@@ -6175,7 +6175,8 @@ static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
}
bool ARMAsmParser::processInstruction(MCInst &Inst,
- const OperandVector &Operands) {
+ const OperandVector &Operands,
+ MCStreamer &Out) {
switch (Inst.getOpcode()) {
// Alias for alternate form of 'ldr{,b}t Rt, [Rn], #imm' instruction.
case ARM::LDRT_POST:
@@ -6216,12 +6217,31 @@ bool ARMAsmParser::processInstruction(MCInst &Inst,
// Alias for alternate form of 'ADR Rd, #imm' instruction.
case ARM::ADDri: {
if (Inst.getOperand(1).getReg() != ARM::PC ||
- Inst.getOperand(5).getReg() != 0)
+ Inst.getOperand(5).getReg() != 0 ||
+ !(Inst.getOperand(2).isExpr() || Inst.getOperand(2).isImm()))
return false;
MCInst TmpInst;
TmpInst.setOpcode(ARM::ADR);
TmpInst.addOperand(Inst.getOperand(0));
- TmpInst.addOperand(Inst.getOperand(2));
+ if (Inst.getOperand(2).isImm()) {
+ TmpInst.addOperand(Inst.getOperand(2));
+ } else {
+ // Turn PC-relative expression into absolute expression.
+ // Reading PC provides the start of the current instruction + 8 and
+ // the transform to adr is biased by that.
+ MCSymbol *Dot = getContext().CreateTempSymbol();
+ Out.EmitLabel(Dot);
+ const MCExpr *OpExpr = Inst.getOperand(2).getExpr();
+ const MCExpr *InstPC = MCSymbolRefExpr::Create(Dot,
+ MCSymbolRefExpr::VK_None,
+ getContext());
+ const MCExpr *Const8 = MCConstantExpr::Create(8, getContext());
+ const MCExpr *ReadPC = MCBinaryExpr::CreateAdd(InstPC, Const8,
+ getContext());
+ const MCExpr *FixupAddr = MCBinaryExpr::CreateAdd(ReadPC, OpExpr,
+ getContext());
+ TmpInst.addOperand(MCOperand::CreateExpr(FixupAddr));
+ }
TmpInst.addOperand(Inst.getOperand(3));
TmpInst.addOperand(Inst.getOperand(4));
Inst = TmpInst;
@@ -8061,7 +8081,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
// encoding is selected. Loop on it while changes happen so the
// individual transformations can chain off each other. E.g.,
// tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
- while (processInstruction(Inst, Operands))
+ while (processInstruction(Inst, Operands, Out))
;
// Only after the instruction is fully processed, we can validate it
OpenPOWER on IntegriCloud