mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[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
This commit is contained in:
parent
ea1b197077
commit
688a507b32
@ -970,12 +970,16 @@ public:
|
|||||||
bool isMOVZMovAlias() const {
|
bool isMOVZMovAlias() const {
|
||||||
if (!isImm()) return false;
|
if (!isImm()) return false;
|
||||||
|
|
||||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
const MCExpr *E = getImm();
|
||||||
if (!CE) return false;
|
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(E)) {
|
||||||
uint64_t Value = CE->getValue();
|
uint64_t Value = CE->getValue();
|
||||||
|
|
||||||
return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
|
return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
|
||||||
}
|
}
|
||||||
|
// Only supports the case of Shift being 0 if an expression is used as an
|
||||||
|
// operand
|
||||||
|
return !Shift && E;
|
||||||
|
}
|
||||||
|
|
||||||
template<int RegWidth, int Shift>
|
template<int RegWidth, int Shift>
|
||||||
bool isMOVNMovAlias() const {
|
bool isMOVNMovAlias() const {
|
||||||
@ -1774,9 +1778,13 @@ public:
|
|||||||
void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
|
void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
|
||||||
const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
if (CE) {
|
||||||
uint64_t Value = CE->getValue();
|
uint64_t Value = CE->getValue();
|
||||||
Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
|
Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
|
||||||
|
} else {
|
||||||
|
addExpr(Inst, getImm());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Shift>
|
template<int Shift>
|
||||||
|
@ -243,6 +243,17 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
|
|||||||
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
|
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
|
||||||
if (AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_ABS &&
|
if (AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_ABS &&
|
||||||
AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_SABS) {
|
AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_SABS) {
|
||||||
|
if (!RefKind) {
|
||||||
|
// The fixup is an expression
|
||||||
|
if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
|
||||||
|
Ctx.reportError(Fixup.getLoc(),
|
||||||
|
"fixup value out of range [-0xFFFF, 0xFFFF]");
|
||||||
|
|
||||||
|
// Invert the negative immediate because it will feed into a MOVN.
|
||||||
|
if (SignedValue < 0)
|
||||||
|
SignedValue = ~SignedValue;
|
||||||
|
Value = static_cast<uint64_t>(SignedValue);
|
||||||
|
} else
|
||||||
// VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
|
// VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
|
||||||
// ever be resolved in the assembler.
|
// ever be resolved in the assembler.
|
||||||
Ctx.reportError(Fixup.getLoc(),
|
Ctx.reportError(Fixup.getLoc(),
|
||||||
@ -441,7 +452,8 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
|
|||||||
// handle this more cleanly. This may affect the output of -show-mc-encoding.
|
// handle this more cleanly. This may affect the output of -show-mc-encoding.
|
||||||
AArch64MCExpr::VariantKind RefKind =
|
AArch64MCExpr::VariantKind RefKind =
|
||||||
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
|
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
|
||||||
if (AArch64MCExpr::getSymbolLoc(RefKind) == AArch64MCExpr::VK_SABS) {
|
if (AArch64MCExpr::getSymbolLoc(RefKind) == AArch64MCExpr::VK_SABS ||
|
||||||
|
(!RefKind && Fixup.getTargetKind() == AArch64::fixup_aarch64_movw)) {
|
||||||
// If the immediate is negative, generate MOVN else MOVZ.
|
// If the immediate is negative, generate MOVN else MOVZ.
|
||||||
// (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
|
// (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
|
||||||
if (SignedValue < 0)
|
if (SignedValue < 0)
|
||||||
|
@ -569,7 +569,8 @@ unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
|
|||||||
if (UImm16MO.isImm())
|
if (UImm16MO.isImm())
|
||||||
return EncodedValue;
|
return EncodedValue;
|
||||||
|
|
||||||
const AArch64MCExpr *A64E = cast<AArch64MCExpr>(UImm16MO.getExpr());
|
const MCExpr *E = UImm16MO.getExpr();
|
||||||
|
if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(E)) {
|
||||||
switch (A64E->getKind()) {
|
switch (A64E->getKind()) {
|
||||||
case AArch64MCExpr::VK_DTPREL_G2:
|
case AArch64MCExpr::VK_DTPREL_G2:
|
||||||
case AArch64MCExpr::VK_DTPREL_G1:
|
case AArch64MCExpr::VK_DTPREL_G1:
|
||||||
@ -583,9 +584,9 @@ unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue,
|
|||||||
// Nothing to do for an unsigned fixup.
|
// Nothing to do for an unsigned fixup.
|
||||||
return EncodedValue;
|
return EncodedValue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EncodedValue;
|
||||||
return EncodedValue & ~(1u << 30);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||||
|
@ -167,7 +167,7 @@
|
|||||||
// MOV alias should not accept any fiddling
|
// MOV alias should not accept any fiddling
|
||||||
mov x2, xsp, #123
|
mov x2, xsp, #123
|
||||||
mov wsp, w27, #0xfff, lsl #12
|
mov wsp, w27, #0xfff, lsl #12
|
||||||
// CHECK-ERROR: error: expected compatible register or logical immediate
|
// CHECK-ERROR: error: invalid operand for instruction
|
||||||
// CHECK-ERROR-NEXT: mov x2, xsp, #123
|
// CHECK-ERROR-NEXT: mov x2, xsp, #123
|
||||||
// CHECK-ERROR-NEXT: ^
|
// CHECK-ERROR-NEXT: ^
|
||||||
// CHECK-ERROR-NEXT: error: invalid operand for instruction
|
// CHECK-ERROR-NEXT: error: invalid operand for instruction
|
||||||
|
16
test/MC/AArch64/mov-expr-as-immediate.s
Normal file
16
test/MC/AArch64/mov-expr-as-immediate.s
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// RUN: llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o %t | llvm-objdump --triple aarch64-none-linux-gnu -Dr %t | FileCheck %s
|
||||||
|
|
||||||
|
0:
|
||||||
|
.skip 4
|
||||||
|
1:
|
||||||
|
mov x0, 1b - 0b
|
||||||
|
// CHECK: mov x0, #4
|
||||||
|
mov x0, 0b - 1b
|
||||||
|
// CHECK: mov x0, #-4
|
||||||
|
mov x0, 0b - 0b
|
||||||
|
// CHECK: mov x0, #0
|
||||||
|
mov x0, 1b - 2 - 0b + 6
|
||||||
|
// CHECK: mov x0, #8
|
||||||
|
mov x0, #:abs_g0_s:1b
|
||||||
|
// CHECK: mov x0, #0
|
||||||
|
// CHECK-NEXT: R_AARCH64_MOVW_SABS_G0 .text+0x4
|
9
test/MC/AArch64/mov-expression-as-immediate.s
Normal file
9
test/MC/AArch64/mov-expression-as-immediate.s
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// RUN: llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o %t | llvm-objdump -d %t | FileCheck %s
|
||||||
|
|
||||||
|
0:
|
||||||
|
.skip 4
|
||||||
|
1:
|
||||||
|
mov x0, 1b - 0b
|
||||||
|
// CHECK: mov x0, #4
|
||||||
|
mov x0, 0b - 1b
|
||||||
|
// CHECK: mov x0, #-4
|
17
test/MC/AArch64/mov-unsupported-expr-as-immediate.s
Normal file
17
test/MC/AArch64/mov-unsupported-expr-as-immediate.s
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// RUN: not llvm-mc -triple aarch64-none-linux-gnu %s -filetype=obj -o /dev/null 2>&1 | FileCheck %s
|
||||||
|
|
||||||
|
0:
|
||||||
|
.skip 0x10000
|
||||||
|
1:
|
||||||
|
mov x0, 1b - 0b
|
||||||
|
// CHECK: error: fixup value out of range
|
||||||
|
// CHECK: mov x0, 1b - 0b
|
||||||
|
// CHECK: ^
|
||||||
|
mov x0, 0b - 1b
|
||||||
|
// CHECK: error: fixup value out of range
|
||||||
|
// CHECK: mov x0, 0b - 1b
|
||||||
|
// CHECK: ^
|
||||||
|
mov x0, 1b
|
||||||
|
// CHECK: error: invalid fixup for movz/movk instruction
|
||||||
|
// CHECK: mov x0, 1b
|
||||||
|
// CHECK: ^
|
Loading…
Reference in New Issue
Block a user