Skip to content

Commit

Permalink
[MC] [AArch64] Support resolving signed fixups for :abs_g0_s: etc.
Browse files Browse the repository at this point in the history
Summary: This patch is a follow-up to D55896.

Reviewers: efriedma, mstorsjo

Reviewed By: efriedma

Subscribers: javed.absar, kristof.beyls, llvm-commits

Differential Revision: https://reviews.llvm.org/D56029

llvm-svn: 350606
  • Loading branch information
Mandeep Singh Grang committed Jan 8, 2019
1 parent a97cad4 commit f286bee
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 28 deletions.
96 changes: 69 additions & 27 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,46 +218,74 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target,
case AArch64::fixup_aarch64_movw: {
AArch64MCExpr::VariantKind RefKind =
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
if (AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_ABS) {
if (AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_SABS) {
// VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
// ever be resolved in the assembler.
Ctx.reportError(Fixup.getLoc(),
"relocation for a thread-local variable points to an "
"absolute symbol");
return Value;
}
if (AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_ABS &&
AArch64MCExpr::getSymbolLoc(RefKind) != AArch64MCExpr::VK_SABS) {
// VK_GOTTPREL, VK_TPREL, VK_DTPREL are movw fixups, but they can't
// ever be resolved in the assembler.
Ctx.reportError(Fixup.getLoc(),
"resolvable R_AARCH64_MOVW_SABS_G* fixups are not "
"yet implemented");
"relocation for a thread-local variable points to an "
"absolute symbol");
return Value;
}

if (!IsResolved) {
// FIXME: Figure out when this can actually happen, and verify our
// behavior.
Ctx.reportError(Fixup.getLoc(), "unresolved movw fixup not yet "
"implemented");
return Value;
}
switch (AArch64MCExpr::getAddressFrag(RefKind)) {
case AArch64MCExpr::VK_G0:
break;
case AArch64MCExpr::VK_G1:
Value = Value >> 16;
break;
case AArch64MCExpr::VK_G2:
Value = Value >> 32;
break;
case AArch64MCExpr::VK_G3:
Value = Value >> 48;
break;
default:
llvm_unreachable("Variant kind doesn't correspond to fixup");

if (AArch64MCExpr::getSymbolLoc(RefKind) == AArch64MCExpr::VK_SABS) {
switch (AArch64MCExpr::getAddressFrag(RefKind)) {
case AArch64MCExpr::VK_G0:
break;
case AArch64MCExpr::VK_G1:
SignedValue = SignedValue >> 16;
break;
case AArch64MCExpr::VK_G2:
SignedValue = SignedValue >> 32;
break;
case AArch64MCExpr::VK_G3:
SignedValue = SignedValue >> 48;
break;
default:
llvm_unreachable("Variant kind doesn't correspond to fixup");
}

} else {
switch (AArch64MCExpr::getAddressFrag(RefKind)) {
case AArch64MCExpr::VK_G0:
break;
case AArch64MCExpr::VK_G1:
Value = Value >> 16;
break;
case AArch64MCExpr::VK_G2:
Value = Value >> 32;
break;
case AArch64MCExpr::VK_G3:
Value = Value >> 48;
break;
default:
llvm_unreachable("Variant kind doesn't correspond to fixup");
}
}
if (RefKind & AArch64MCExpr::VK_NC)

if (RefKind & AArch64MCExpr::VK_NC) {
Value &= 0xFFFF;
else if (Value > 0xFFFF)
}
else if (RefKind & AArch64MCExpr::VK_SABS) {
if (SignedValue > 0xFFFF || SignedValue < -0xFFFF)
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");

// Invert the negative immediate because it will feed into a MOVN.
if (SignedValue < 0)
SignedValue = ~SignedValue;
Value = static_cast<uint64_t>(SignedValue);
}
else if (Value > 0xFFFF) {
Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
}
return Value;
}
case AArch64::fixup_aarch64_pcrel_branch14:
Expand Down Expand Up @@ -336,6 +364,7 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
return; // Doesn't change encoding.
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
MCContext &Ctx = Asm.getContext();
int64_t SignedValue = static_cast<int64_t>(Value);
// Apply any target-specific value adjustments.
Value = adjustFixupValue(Fixup, Target, Value, Ctx, TheTriple, IsResolved);

Expand Down Expand Up @@ -364,6 +393,19 @@ void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}

// FIXME: getFixupKindInfo() and getFixupKindNumBytes() could be fixed to
// handle this more cleanly. This may affect the output of -show-mc-encoding.
AArch64MCExpr::VariantKind RefKind =
static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
if (RefKind & AArch64MCExpr::VK_SABS) {
// If the immediate is negative, generate MOVN else MOVZ.
// (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
if (SignedValue < 0)
Data[Offset + 3] &= ~(1 << 6);
else
Data[Offset + 3] |= (1 << 6);
}
}

bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst,
Expand Down
44 changes: 44 additions & 0 deletions llvm/test/MC/AArch64/fixup-absolute-signed.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o - | llvm-objdump -d - | FileCheck %s

onepart_before = 12345
twopart_before = -12345678
threepart_before = -1234567890

// CHECK: movn x0, #0, lsl #32
// CHECK: movn x0, #0, lsl #32
movz x0, #:abs_g2_s:threepart_before
movz x0, #:abs_g2_s:threepart_after

// CHECK: movk x0, #65535, lsl #32
// CHECK: movk x0, #65535, lsl #32
movk x0, #:abs_g2_nc:threepart_before
movk x0, #:abs_g2_nc:threepart_after

// CHECK: mov x0, #-12320769
// CHECK: mov x0, #-12320769
movz x0, #:abs_g1_s:twopart_before
movz x0, #:abs_g1_s:twopart_after

// CHECK: movk x0, #46697, lsl #16
// CHECK: movk x0, #46697, lsl #16
movk x0, #:abs_g1_nc:threepart_before
movk x0, #:abs_g1_nc:threepart_after

// CHECK: mov x0, #12345
// CHECK: mov x0, #12345
movz x0, #:abs_g0_s:onepart_before
movz x0, #:abs_g0_s:onepart_after

// CHECK: movk x0, #64814
// CHECK: movk x0, #64814
movk x0, #:abs_g0_nc:threepart_before
movk x0, #:abs_g0_nc:threepart_after

// CHECK: mov x0, #12345
// CHECK: mov x0, #12345
movn x0, #:abs_g0_s:onepart_before
movn x0, #:abs_g0_s:onepart_after

onepart_after = 12345
twopart_after = -12345678
threepart_after = -1234567890
5 changes: 4 additions & 1 deletion llvm/test/MC/AArch64/fixup-out-of-range.s
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
movz x0, #:abs_g1:value2

// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: resolvable R_AARCH64_MOVW_SABS_G* fixups are not yet implemented
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
movz x0, #:abs_g0_s:value1

// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
movz x0, #:abs_g1_s:value2

// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: relocation for a thread-local variable points to an absolute symbol
movz x0, #:tprel_g0:value1

Expand Down

0 comments on commit f286bee

Please sign in to comment.