Skip to content

Commit 0e1accd

Browse files
committed
[AArch64] Support expression results as immediate values in mov
Summary: This patch adds support of using the result of an expression as an immediate value. For example, 0: .skip 4 1: mov x0, 1b - 0b is assembled to mov x0, #4 Currently it does not support expressions requiring relocation unless explicitly specified. This fixes PR#45781. Reviewers: peter.smith, ostannard, efriedma Reviewed By: efriedma Subscribers: nickdesaulniers, llozano, manojgupta, efriedma, ostannard, kristof.beyls, hiraditya, danielkiss, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D80028
1 parent 6a31a9a commit 0e1accd

7 files changed

+94
-31
lines changed

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -970,11 +970,15 @@ class AArch64Operand : public MCParsedAsmOperand {
970970
bool isMOVZMovAlias() const {
971971
if (!isImm()) return false;
972972

973-
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
974-
if (!CE) return false;
975-
uint64_t Value = CE->getValue();
973+
const MCExpr *E = getImm();
974+
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(E)) {
975+
uint64_t Value = CE->getValue();
976976

977-
return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
977+
return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
978+
}
979+
// Only supports the case of Shift being 0 if an expression is used as an
980+
// operand
981+
return !Shift && E;
978982
}
979983

980984
template<int RegWidth, int Shift>
@@ -1774,9 +1778,13 @@ class AArch64Operand : public MCParsedAsmOperand {
17741778
void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
17751779
assert(N == 1 && "Invalid number of operands!");
17761780

1777-
const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1778-
uint64_t Value = CE->getValue();
1779-
Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
1781+
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1782+
if (CE) {
1783+
uint64_t Value = CE->getValue();
1784+
Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
1785+
} else {
1786+
addExpr(Inst, getImm());
1787+
}
17801788
}
17811789

17821790
template<int Shift>

llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,22 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
243243
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
244244
if (AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_ABS &&
245245
AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_SABS) {
246-
// VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
247-
// ever be resolved in the assembler.
248-
Ctx.reportError(Fixup.getLoc(),
249-
"relocation for a thread-local variable points to an "
250-
"absolute symbol");
246+
if (!RefKind) {
247+
// The fixup is an expression
248+
if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
249+
Ctx.reportError(Fixup.getLoc(),
250+
"fixup value out of range [-0xFFFF, 0xFFFF]");
251+
252+
// Invert the negative immediate because it will feed into a MOVN.
253+
if (SignedValue < 0)
254+
SignedValue = ~SignedValue;
255+
Value = static_cast<uint64_t>(SignedValue);
256+
} else
257+
// VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
258+
// ever be resolved in the assembler.
259+
Ctx.reportError(Fixup.getLoc(),
260+
"relocation for a thread-local variable points to an "
261+
"absolute symbol");
251262
return Value;
252263
}
253264

@@ -440,8 +451,9 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
440451
// FIXME: getFixupKindInfo() and getFixupKindNumBytes() could be fixed to
441452
// handle this more cleanly. This may affect the output of -show-mc-encoding.
442453
AArch64MCExpr::VariantKind RefKind =
443-
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
444-
if (AArch64MCExpr::getSymbolLoc(RefKind) == AArch64MCExpr::VK_SABS) {
454+
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
455+
if (AArch64MCExpr::getSymbolLoc(RefKind) == AArch64MCExpr::VK_SABS ||
456+
(!RefKind && Fixup.getTargetKind() == AArch64::fixup_aarch64_movw)) {
445457
// If the immediate is negative, generate MOVN else MOVZ.
446458
// (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
447459
if (SignedValue < 0)

llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -569,23 +569,24 @@ unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
569569
if (UImm16MO.isImm())
570570
return EncodedValue;
571571

572-
const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr());
573-
switch (A64E->getKind()) {
574-
case AArch64MCExpr::VK_DTPREL_G2:
575-
case AArch64MCExpr::VK_DTPREL_G1:
576-
case AArch64MCExpr::VK_DTPREL_G0:
577-
case AArch64MCExpr::VK_GOTTPREL_G1:
578-
case AArch64MCExpr::VK_TPREL_G2:
579-
case AArch64MCExpr::VK_TPREL_G1:
580-
case AArch64MCExpr::VK_TPREL_G0:
581-
return EncodedValue & ~(1u << 30);
582-
default:
583-
// Nothing to do for an unsigned fixup.
584-
return EncodedValue;
572+
const MCExpr *E = UImm16MO.getExpr();
573+
if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(E)) {
574+
switch (A64E->getKind()) {
575+
case AArch64MCExpr::VK_DTPREL_G2:
576+
case AArch64MCExpr::VK_DTPREL_G1:
577+
case AArch64MCExpr::VK_DTPREL_G0:
578+
case AArch64MCExpr::VK_GOTTPREL_G1:
579+
case AArch64MCExpr::VK_TPREL_G2:
580+
case AArch64MCExpr::VK_TPREL_G1:
581+
case AArch64MCExpr::VK_TPREL_G0:
582+
return EncodedValue & ~(1u << 30);
583+
default:
584+
// Nothing to do for an unsigned fixup.
585+
return EncodedValue;
586+
}
585587
}
586588

587-
588-
return EncodedValue & ~(1u << 30);
589+
return EncodedValue;
589590
}
590591

591592
void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,

llvm/test/MC/AArch64/basic-a64-diagnostics.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@
167167
// MOV alias should not accept any fiddling
168168
mov x2, xsp, #123
169169
mov wsp, w27, #0xfff, lsl #12
170-
// CHECK-ERROR: error: expected compatible register or logical immediate
170+
// CHECK-ERROR: error: invalid operand for instruction
171171
// CHECK-ERROR-NEXT: mov x2, xsp, #123
172-
// CHECK-ERROR-NEXT: ^
172+
// CHECK-ERROR-NEXT: ^
173173
// CHECK-ERROR-NEXT: error: invalid operand for instruction
174174
// CHECK-ERROR-NEXT: mov wsp, w27, #0xfff, lsl #12
175175
// CHECK-ERROR-NEXT: ^
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o %t | llvm-objdump --triple aarch64-none-linux-gnu -Dr %t | FileCheck %s
2+
3+
0:
4+
.skip 4
5+
1:
6+
mov x0, 1b - 0b
7+
// CHECK: mov x0, #4
8+
mov x0, 0b - 1b
9+
// CHECK: mov x0, #-4
10+
mov x0, 0b - 0b
11+
// CHECK: mov x0, #0
12+
mov x0, 1b - 2 - 0b + 6
13+
// CHECK: mov x0, #8
14+
mov x0, #:abs_g0_s:1b
15+
// CHECK: mov x0, #0
16+
// CHECK-NEXT: R_AARCH64_MOVW_SABS_G0 .text+0x4
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o %t | llvm-objdump -d %t | FileCheck %s
2+
3+
0:
4+
.skip 4
5+
1:
6+
mov x0, 1b - 0b
7+
// CHECK: mov x0, #4
8+
mov x0, 0b - 1b
9+
// CHECK: mov x0, #-4
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: not llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o /dev/null 2>&1 | FileCheck %s
2+
3+
0:
4+
.skip 0x10000
5+
1:
6+
mov x0, 1b - 0b
7+
// CHECK: error: fixup value out of range
8+
// CHECK: mov x0, 1b - 0b
9+
// CHECK: ^
10+
mov x0, 0b - 1b
11+
// CHECK: error: fixup value out of range
12+
// CHECK: mov x0, 0b - 1b
13+
// CHECK: ^
14+
mov x0, 1b
15+
// CHECK: error: invalid fixup for movz/movk instruction
16+
// CHECK: mov x0, 1b
17+
// CHECK: ^

0 commit comments

Comments
 (0)