diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -7950,7 +7950,10 @@ break; case ARM::t2B: { int op = (Operands[2]->isImm()) ? 2 : 3; - if (!static_cast(*Operands[op]).isSignedOffset<24, 1>()) + ARMOperand &Operand = static_cast(*Operands[op]); + // Delay the checks of symbolic expressions until they are resolved. + if (!isa(Operand.getImm()) && + !Operand.isSignedOffset<24, 1>()) return Error(Operands[op]->getStartLoc(), "branch target out of range"); break; } diff --git a/llvm/test/MC/ARM/thumb2-b.w-target.s b/llvm/test/MC/ARM/thumb2-b.w-target.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/thumb2-b.w-target.s @@ -0,0 +1,12 @@ +// RUN: llvm-mc -triple=thumbv7 -filetype=obj %s | llvm-objdump --triple=thumbv7 -d - | FileCheck %s + +.syntax unified + +// CHECK-LABEL: start +// CHECK-NEXT: b.w #16777208 +// CHECK-NEXT: b.w #2 +start: + b.w start - 1f + 0x1000000 +1: + b.w . + (2f - 1b + 2) +2: diff --git a/llvm/test/MC/ARM/thumb2-branch-ranges.s b/llvm/test/MC/ARM/thumb2-branch-ranges.s --- a/llvm/test/MC/ARM/thumb2-branch-ranges.s +++ b/llvm/test/MC/ARM/thumb2-branch-ranges.s @@ -94,3 +94,9 @@ // CHECK: [[@LINE+2]]:{{[0-9]}}: error: Relocation out of range // CHECK-LABEL: beq.w start6 beq.w start6 + +start7: +// branch to thumb function resolved at assembly time +// CHECK: [[#@LINE+1]]:{{[0-9]}}: error: Relocation out of range + b.w start8 - start7 + 0x1000000 +start8: