const MCExpr *SOExpr = Op->getImm();
int64_t Value;
if (!SOExpr->EvaluateAsAbsolute(Value))
- return Match_InvalidOperand;
+ return Match_Success;
assert((Value >= INT32_MIN && Value <= INT32_MAX) &&
"expression value must be representiable in 32 bits");
}
unsigned getSOImmOpValue(const MCInst &MI, unsigned Op,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
- unsigned SoImm = MI.getOperand(Op).getImm();
+
+ const MCOperand &MO = MI.getOperand(Op);
+
+ // We expect MO to be an immediate or an expression,
+ // if it is an immediate - that's fine, just encode the value.
+ // Otherwise - create a Fixup.
+ if (MO.isExpr()) {
+ const MCExpr *Expr = MO.getExpr();
+ // In instruction code this value always encoded as lowest 12 bits,
+ // so we don't have to perform any specific adjustments.
+ // Due to requirements of relocatable records we have to use FK_Data_4.
+ // See ARMELFObjectWriter::ExplicitRelSym and
+ // ARMELFObjectWriter::GetRelocTypeInner for more details.
+ MCFixupKind Kind = MCFixupKind(FK_Data_4);
+ Fixups.push_back(MCFixup::Create(0, Expr, Kind, MI.getLoc()));
+ return 0;
+ }
+
+ unsigned SoImm = MO.getImm();
int SoImmVal = ARM_AM::getSOImmVal(SoImm);
assert(SoImmVal != -1 && "Not a valid so_imm value!");
--- /dev/null
+@ RUN: not llvm-mc -triple=arm-linux-gnueabi -filetype=obj < %s 2>&1 | FileCheck %s
+
+.text
+ cmp r0, #(l1 - unknownLabel + 4) >> 2
+@ CHECK: error: expected relocatable expression
+
+l1:
--- /dev/null
+@ RUN: not llvm-mc -triple=arm-linux-gnueabi -filetype=obj < %s 2>&1 | FileCheck %s
+
+.text
+ cmp r0, #(l1 - unknownLabel)
+@ CHECK: error: symbol 'unknownLabel' can not be undefined in a subtraction expression
+
+l1:
--- /dev/null
+@ PR18931
+@ RUN: llvm-mc < %s -triple=arm-linux-gnueabi -filetype=obj -o - \
+@ RUN: | llvm-objdump --disassemble -arch=arm - | FileCheck %s
+
+ .text
+@ CHECK: cmp r2, #1
+ cmp r2, #(l2 - l1 + 4) >> 2
+l1:
+l2:
+++ /dev/null
-@ RUN: not llvm-mc -triple=armv7-linux-gnuabi -filetype=obj < %s 2>&1 | FileCheck %s
-
-.text
- cmp r2, #(l2 - l1) >> 6
-@ CHECK: error: invalid operand for instruction
-
-l1:
-l2: