diff options
author | dim <dim@FreeBSD.org> | 2015-01-02 14:55:02 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-01-02 14:55:02 +0000 |
commit | ad057890048fdd957ffc50de442f15f365059e1b (patch) | |
tree | cc7623f761930438ec32e49a0cea5707db154127 /contrib/llvm/lib/Target/ARM | |
parent | 110917eb46c5ac715474ac8ab0a6f2566827d416 (diff) | |
download | FreeBSD-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.cpp | 30 |
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 |