Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -318,7 +318,7 @@ 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 @@ } 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 @@ // 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. + // Special care is needed to compensate for the implicit addition + // of 8 Bytes for fixup_arm_adr_pcrel_12. + MCSymbol *Sym = getContext().CreateTempSymbol(); + Out.EmitLabel(Sym); + const MCExpr *OpExpr = Inst.getOperand(2).getExpr(); + const MCExpr *PCRel = MCSymbolRefExpr::Create(Sym, + MCSymbolRefExpr::VK_None, + getContext()); + const MCExpr *Const8 = MCConstantExpr::Create(8, getContext()); + const MCExpr *Addr = MCBinaryExpr::CreateAdd(PCRel, OpExpr, + getContext()); + const MCExpr *FixupAddr = MCBinaryExpr::CreateAdd(Const8, Addr, + getContext()); + TmpInst.addOperand(MCOperand::CreateExpr(FixupAddr)); + } TmpInst.addOperand(Inst.getOperand(3)); TmpInst.addOperand(Inst.getOperand(4)); Inst = TmpInst; @@ -8320,7 +8340,7 @@ // 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 Index: test/MC/ARM/basic-arm-instructions.s =================================================================== --- test/MC/ARM/basic-arm-instructions.s +++ test/MC/ARM/basic-arm-instructions.s @@ -191,7 +191,9 @@ 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 @@ @ 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, 8+(Ltmp1+(Lback-Ltmp0)) @ encoding: [A,A,0x0f'A',0xe2'A'] +@ CHECK-NEXT: @ fixup A - offset: 0, value: 8+(Ltmp1+(Lback-Ltmp0)), kind: fixup_arm_adr_pcrel_12 @ Test right shift by 32, which is encoded as 0 add r3, r1, r2, lsr #32