ARM IAS: properly handle expression operands

Operands which involved label arithemetic would previously fail to parse.  This
corrects that by adding the additional case for the shift operand validation.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198735 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Saleem Abdulrasool 2014-01-08 03:28:14 +00:00
parent bc41190a74
commit cb914a32d6
3 changed files with 81 additions and 16 deletions

View File

@ -8775,12 +8775,24 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp,
// If the kind is a token for a literal immediate, check if our asm
// operand matches. This is for InstAliases which have a fixed-value
// immediate in the syntax.
if (Kind == MCK__35_0 && Op->isImm()) {
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
if (!CE)
return Match_InvalidOperand;
if (CE->getValue() == 0)
return Match_Success;
switch (Kind) {
default: break;
case MCK__35_0:
if (Op->isImm())
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm()))
if (CE->getValue() == 0)
return Match_Success;
break;
case MCK_ARMSOImm:
if (Op->isImm()) {
const MCExpr *SOExpr = Op->getImm();
int64_t Value;
if (!SOExpr->EvaluateAsAbsolute(Value))
return Match_Success;
assert((Value >= INT32_MIN && Value <= INT32_MAX) &&
"expression value must be representiable in 32 bits");
}
break;
}
return Match_InvalidOperand;
}

View File

@ -307,17 +307,30 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
<< markup(">");
} else {
assert(Op.isExpr() && "unknown operand kind in printOperand");
// If a symbolic branch target was added as a constant expression then print
// that address in hex. And only print 32 unsigned bits for the address.
const MCConstantExpr *BranchTarget = dyn_cast<MCConstantExpr>(Op.getExpr());
int64_t Address;
if (BranchTarget && BranchTarget->EvaluateAsAbsolute(Address)) {
O << "0x";
O.write_hex((uint32_t)Address);
const MCExpr *Expr = Op.getExpr();
switch (Expr->getKind()) {
case MCExpr::Binary:
O << '#' << *Expr;
break;
case MCExpr::Constant: {
// If a symbolic branch target was added as a constant expression then
// print that address in hex. And only print 32 unsigned bits for the
// address.
const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);
int64_t TargetAddress;
if (!Constant->EvaluateAsAbsolute(TargetAddress)) {
O << '#' << *Expr;
} else {
O << "0x";
O.write_hex(static_cast<uint32_t>(TargetAddress));
}
break;
}
else {
// Otherwise, just print the expression.
O << *Op.getExpr();
default:
// FIXME: Should we always treat this as if it is a constant literal and
// prefix it with '#'?
O << *Expr;
break;
}
}
}

View File

@ -0,0 +1,40 @@
@ RUN: llvm-mc -triple armv7-eabi -filetype asm -o - %s | FileCheck %s
.syntax unified
.data
.type .L_table_begin,%object
.L_table_begin:
.rep 2
.long 0xd15ab1ed
.long 0x0ff1c1a1
.endr
.L_table_end:
.text
.type return,%function
return:
bx lr
.global arm_function
.type arm_function,%function
arm_function:
mov r0, #(.L_table_end - .L_table_begin) >> 2
blx return
@ CHECK-LABEL: arm_function
@ CHECK: movw r0, #(.L_table_end-.L_table_begin)>>2
@ CHECK: blx return
.global thumb_function
.type thumb_function,%function
thumb_function:
mov r0, #(.L_table_end - .L_table_begin) >> 2
blx return
@ CHECK-LABEL: thumb_function
@ CHECK: movw r0, #(.L_table_end-.L_table_begin)>>2
@ CHECK: blx return