Index: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -110,11 +110,11 @@ case FK_Data_1: return 1; - case AArch64::fixup_aarch64_movw: case FK_Data_2: case FK_SecRel_2: return 2; + case AArch64::fixup_aarch64_movw: case AArch64::fixup_aarch64_pcrel_branch14: case AArch64::fixup_aarch64_add_imm12: case AArch64::fixup_aarch64_ldst_imm12_scale1: @@ -145,9 +145,9 @@ return (hi19 << 5) | (lo2 << 29); } -static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, - MCContext &Ctx, const Triple &TheTriple, - bool IsResolved) { +static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, + uint64_t Value, MCContext &Ctx, + const Triple &TheTriple, bool IsResolved) { unsigned Kind = Fixup.getKind(); int64_t SignedValue = static_cast(Value); switch (Kind) { @@ -215,10 +215,51 @@ if (Value & 0xf) Ctx.reportError(Fixup.getLoc(), "fixup must be 16-byte aligned"); return Value >> 4; - case AArch64::fixup_aarch64_movw: - Ctx.reportError(Fixup.getLoc(), - "no resolvable MOVZ/MOVK fixups supported yet"); + case AArch64::fixup_aarch64_movw: { + AArch64MCExpr::VariantKind RefKind = + static_cast(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; + } + Ctx.reportError(Fixup.getLoc(), + "resolvable R_AARCH64_MOVW_SABS_G* fixups are not " + "yet implemented"); + 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 (RefKind & AArch64MCExpr::VK_NC) + Value &= 0xFFFF; + else if (Value > 0xFFFF) + Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); return Value; + } case AArch64::fixup_aarch64_pcrel_branch14: // Signed 16-bit immediate if (SignedValue > 32767 || SignedValue < -32768) @@ -296,7 +337,7 @@ MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); MCContext &Ctx = Asm.getContext(); // Apply any target-specific value adjustments. - Value = adjustFixupValue(Fixup, Value, Ctx, TheTriple, IsResolved); + Value = adjustFixupValue(Fixup, Target, Value, Ctx, TheTriple, IsResolved); // Shift the value into position. Value <<= Info.TargetOffset; Index: llvm/trunk/test/MC/AArch64/fixup-absolute.s =================================================================== --- llvm/trunk/test/MC/AArch64/fixup-absolute.s +++ llvm/trunk/test/MC/AArch64/fixup-absolute.s @@ -0,0 +1,21 @@ +// RUN: llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o - | llvm-objdump -d - | FileCheck %s + +// CHECK: mov x0, #1311673391471656960 +movz x0, #:abs_g3:fourpart +// CHECK: mov x0, #20014547599360 +movz x0, #:abs_g2:threepart +// CHECK: movk x0, #22136, lsl #32 +movk x0, #:abs_g2_nc:fourpart +// CHECK: mov x0, #305397760 +movz x0, #:abs_g1:twopart +// CHECK: movk x0, #37035, lsl #16 +movk x0, #:abs_g1_nc:fourpart +// CHECK: mov x0, #4660 +movz x0, #:abs_g0:onepart +// CHECK: movk x0, #52719 +movk x0, #:abs_g0_nc:fourpart + +onepart = 0x1234 +twopart = 0x12345678 +threepart = 0x1234567890AB +fourpart = 0x1234567890ABCDEF Index: llvm/trunk/test/MC/AArch64/fixup-out-of-range.s =================================================================== --- llvm/trunk/test/MC/AArch64/fixup-out-of-range.s +++ llvm/trunk/test/MC/AArch64/fixup-out-of-range.s @@ -55,6 +55,19 @@ // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned b unaligned +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range + movz x0, #:abs_g0:value1 + +// 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 + movz x0, #:abs_g0_s:value1 + +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: relocation for a thread-local variable points to an absolute symbol + movz x0, #:tprel_g0:value1 + + .byte 0 unaligned: .byte 0 @@ -63,3 +76,5 @@ .balign 8 distant: .word 0 +value1 = 0x12345678 +value2 = 0x123456789