Fix #13241, a bug around shift immediate operand for ARM instruction ADR.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161159 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jiangning Liu 2012-08-02 08:13:13 +00:00
parent ac89c0ddfd
commit 1fb27eccf5
10 changed files with 82 additions and 7 deletions

View File

@ -416,8 +416,11 @@ def pclabel : Operand<i32> {
}
// ADR instruction labels.
def AdrLabelAsmOperand : AsmOperandClass { let Name = "AdrLabel"; }
def adrlabel : Operand<i32> {
let EncoderMethod = "getAdrLabelOpValue";
let ParserMatchClass = AdrLabelAsmOperand;
let PrintMethod = "printAdrLabelOperand";
}
def neon_vcvt_imm32 : Operand<i32> {

View File

@ -172,6 +172,7 @@ def t2ldr_pcrel_imm12 : Operand<i32> {
// ADR instruction labels.
def t2adrlabel : Operand<i32> {
let EncoderMethod = "getT2AdrLabelOpValue";
let PrintMethod = "printAdrLabelOperand";
}

View File

@ -796,6 +796,13 @@ public:
int64_t Value = CE->getValue();
return Value > 0 && Value <= 32;
}
bool isAdrLabel() const {
// If we have an immediate that's not a constant, treat it as a label
// reference needing a fixup. If it is a constant, but it can't fit
// into shift immediate encoding, we reject it.
if (isImm() && !isa<MCConstantExpr>(getImm())) return true;
else return (isARMSOImm() || isARMSOImmNeg());
}
bool isARMSOImm() const {
if (!isImm()) return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
@ -1644,6 +1651,22 @@ public:
Inst.addOperand(MCOperand::CreateImm(Imm));
}
void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
assert(isImm() && "Not an immediate!");
// If we have an immediate that's not a constant, treat it as a label
// reference needing a fixup.
if (!isa<MCConstantExpr>(getImm())) {
Inst.addOperand(MCOperand::CreateExpr(getImm()));
return;
}
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
int Val = CE->getValue();
Inst.addOperand(MCOperand::CreateImm(Val));
}
void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));

View File

@ -792,6 +792,25 @@ void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
}
void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
if (MO.isExpr()) {
O << *MO.getExpr();
return;
}
int32_t OffImm = (int32_t)MO.getImm();
if (OffImm == INT32_MIN)
O << "#-0";
else if (OffImm < 0)
O << "#-" << -OffImm;
else
O << "#" << OffImm;
}
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
O << "#" << MI->getOperand(OpNum).getImm() * 4;

View File

@ -73,6 +73,7 @@ public:
void printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printPKHASRShiftImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbSRImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O);

View File

@ -641,8 +641,8 @@ getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
return Val;
}
/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
/// target.
/// getAdrLabelOpValue - Return encoding info for 12-bit shifted-immediate
/// ADR label target.
uint32_t ARMMCCodeEmitter::
getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
@ -652,15 +652,23 @@ getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
Fixups);
int32_t offset = MO.getImm();
uint32_t Val = 0x2000;
if (offset < 0) {
if (offset == INT32_MIN) {
Val = 0x1000;
offset = 0;
} else if (offset < 0) {
Val = 0x1000;
offset *= -1;
}
Val |= offset;
int SoImmVal = ARM_AM::getSOImmVal(offset);
assert(SoImmVal != -1 && "Not a valid so_imm value!");
Val |= SoImmVal;
return Val;
}
/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
/// getT2AdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
/// target.
uint32_t ARMMCCodeEmitter::
getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
@ -670,14 +678,16 @@ getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12,
Fixups);
int32_t Val = MO.getImm();
if (Val < 0) {
if (Val == INT32_MIN)
Val = 0x1000;
else if (Val < 0) {
Val *= -1;
Val |= 0x1000;
}
return Val;
}
/// getAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
/// target.
uint32_t ARMMCCodeEmitter::
getThumbAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,

View File

@ -141,6 +141,14 @@ Lforward:
@ CHECK: adr r2, #3 @ encoding: [0x03,0x20,0x8f,0xe2]
@ CHECK: adr r2, #-3 @ encoding: [0x03,0x20,0x4f,0xe2]
adr r1, #-0x0
adr r1, #-0x12000000
adr r1, #0x12000000
@ CHECK: adr r1, #-0 @ encoding: [0x00,0x10,0x4f,0xe2]
@ CHECK: adr r1, #-301989888 @ encoding: [0x12,0x14,0x4f,0xe2]
@ CHECK: adr r1, #301989888 @ encoding: [0x12,0x14,0x8f,0xe2]
@------------------------------------------------------------------------------
@ ADD

View File

@ -135,9 +135,11 @@ _func:
subw r11, pc, #3270
adr.w r11, #-826
adr.w r1, #-0x0
@ CHECK: subw r11, pc, #3270 @ encoding: [0xaf,0xf6,0xc6,0x4b]
@ CHECK: adr.w r11, #-826 @ encoding: [0xaf,0xf2,0x3a,0x3b]
@ CHECK: adr.w r1, #-0 @ encoding: [0xaf,0xf2,0x00,0x01]
@------------------------------------------------------------------------------
@ AND (immediate)

View File

@ -169,9 +169,15 @@
#------------------------------------------------------------------------------
# CHECK: add r2, pc, #3
# CHECK: sub r2, pc, #3
# CHECK: sub r1, pc, #0
# CHECK: sub r1, pc, #301989888
# CHECK: add r1, pc, #301989888
0x03 0x20 0x8f 0xe2
0x03 0x20 0x4f 0xe2
0x00 0x10 0x4f 0xe2
0x12 0x14 0x4f 0xe2
0x12 0x14 0x8f 0xe2
#------------------------------------------------------------------------------
# AND

View File

@ -92,9 +92,11 @@
#------------------------------------------------------------------------------
# CHECK: subw r11, pc, #3270
# CHECK: subw r11, pc, #826
# CHECK: subw r1, pc, #0
0xaf 0xf6 0xc6 0x4b
0xaf 0xf2 0x3a 0x3b
0xaf 0xf2 0x00 0x01
#------------------------------------------------------------------------------
# AND (immediate)