From: Joerg Sonnenberger Date: Fri, 21 Nov 2014 22:39:34 +0000 (+0000) Subject: Fix transformation of add with pc argument to adr for non-immediate X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0b1407b5cfde0117d0e96e970d2032380dfa601c;p=oota-llvm.git Fix transformation of add with pc argument to adr for non-immediate arguments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222587 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 9cc89bd6142..0e474c0e153 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -318,7 +318,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); @@ -6434,7 +6434,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: @@ -6475,12 +6476,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; @@ -8320,7 +8340,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 diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s index e5e96170a77..df5ecbb131c 100644 --- a/test/MC/ARM/basic-arm-instructions.s +++ b/test/MC/ARM/basic-arm-instructions.s @@ -191,7 +191,9 @@ Lforward: add r0, #-4 add r4, r5, #-21 - add r0, pc, #0xc0000000 + add r0, pc, #0xc0000000 + + add r0, pc, #(Lback - .) @ CHECK: add r4, r5, #61440 @ encoding: [0x0f,0x4a,0x85,0xe2] @ CHECK: add r4, r5, r6 @ encoding: [0x06,0x40,0x85,0xe0] @@ -222,7 +224,11 @@ Lforward: @ CHECK: sub r0, r0, #4 @ encoding: [0x04,0x00,0x40,0xe2] @ CHECK: sub r4, r5, #21 @ encoding: [0x15,0x40,0x45,0xe2] -@ CHECK: adr r0, #-1073741824 @ encoding: [0x03,0x01,0x8f,0xe2] +@ CHECK: adr r0, #-1073741824 @ encoding: [0x03,0x01,0x8f,0xe2] +@ CHECK: Ltmp0: +@ CHECK-NEXT: Ltmp1: +@ CHECK-NEXT: adr r0, (Ltmp1+8)+(Lback-Ltmp0) @ encoding: [A,A,0x0f'A',0xe2'A'] +@ CHECK-NEXT: @ fixup A - offset: 0, value: (Ltmp1+8)+(Lback-Ltmp0), kind: fixup_arm_adr_pcrel_12 @ Test right shift by 32, which is encoded as 0 add r3, r1, r2, lsr #32