Fix transformation of add with pc argument to adr for non-immediate

arguments.

llvm-svn: 222587
This commit is contained in:
Joerg Sonnenberger 2014-11-21 22:39:34 +00:00
parent 60ef25bd54
commit 02b13a8d9b
2 changed files with 33 additions and 7 deletions

View File

@ -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

View File

@ -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