Index: llvm/trunk/docs/Extensions.rst =================================================================== --- llvm/trunk/docs/Extensions.rst +++ llvm/trunk/docs/Extensions.rst @@ -182,6 +182,30 @@ starting with ".debug" are implicitly discardable. +ARM64/COFF-Dependent +-------------------- + +Relocations +^^^^^^^^^^^ + +The following additional symbol variants are supported: + +**:secrel_lo12:** generates a relocation that corresponds to the COFF relocation +types ``IMAGE_REL_ARM64_SECREL_LOW12A`` or ``IMAGE_REL_ARM64_SECREL_LOW12L``. + +**:secrel_hi12:** generates a relocation that corresponds to the COFF relocation +type ``IMAGE_REL_ARM64_SECREL_HIGH12A``. + +.. code-block:: gas + + add x0, x0, :secrel_hi12:symbol + ldr x0, [x0, :secrel_lo12:symbol] + + add x1, x1, :secrel_hi12:symbol + add x1, x1, :secrel_lo12:symbol + ... + + ELF-Dependent ------------- Index: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -518,7 +518,9 @@ ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC || ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC || - ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) { + ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) { // Note that we don't range-check the addend. It's adjusted modulo page // size when converted, so there is no "out of range" condition when using // @pageoff. @@ -607,7 +609,9 @@ || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC - || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12; + || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 + || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12 + || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12; } // If it's a constant, it should be a real immediate in range: @@ -2854,6 +2858,8 @@ .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1) .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC) .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE) + .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12) + .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12) .Default(AArch64MCExpr::VK_INVALID); if (RefKind == AArch64MCExpr::VK_INVALID) @@ -3466,7 +3472,9 @@ ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC || - ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12) && + ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 || + ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) && (Inst.getOpcode() == AArch64::ADDXri || Inst.getOpcode() == AArch64::ADDWri)) return false; Index: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -276,7 +276,8 @@ if (const AArch64MCExpr *A64E = dyn_cast(Expr)) { AArch64MCExpr::VariantKind RefKind = A64E->getKind(); if (RefKind == AArch64MCExpr::VK_TPREL_HI12 || - RefKind == AArch64MCExpr::VK_DTPREL_HI12) + RefKind == AArch64MCExpr::VK_DTPREL_HI12 || + RefKind == AArch64MCExpr::VK_SECREL_HI12) ShiftVal = 12; } return ShiftVal == 0 ? 0 : (1 << ShiftVal); Index: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h =================================================================== --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h +++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h @@ -35,6 +35,7 @@ VK_GOTTPREL = 0x005, VK_TPREL = 0x006, VK_TLSDESC = 0x007, + VK_SECREL = 0x008, VK_SymLocBits = 0x00f, // Variants specifying which part of the final address calculation is @@ -98,6 +99,8 @@ VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC, VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF, VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE, + VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF, + VK_SECREL_HI12 = VK_SECREL | VK_HI12, VK_INVALID = 0xfff }; Index: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp +++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp @@ -70,6 +70,8 @@ case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:"; case VK_TLSDESC: return ""; case VK_TLSDESC_PAGE: return ":tlsdesc:"; + case VK_SECREL_LO12: return ":secrel_lo12:"; + case VK_SECREL_HI12: return ":secrel_hi12:"; default: llvm_unreachable("Invalid ELF symbol kind"); } Index: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp +++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp @@ -8,6 +8,7 @@ //===---------------------------------------------------------------------===// #include "MCTargetDesc/AArch64FixupKinds.h" +#include "MCTargetDesc/AArch64MCExpr.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/MC/MCAsmBackend.h" @@ -46,6 +47,7 @@ bool IsCrossSection, const MCAsmBackend &MAB) const { auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + const MCExpr *Expr = Fixup.getValue(); switch (static_cast(Fixup.getKind())) { default: { @@ -73,6 +75,13 @@ return COFF::IMAGE_REL_ARM64_SECREL; case AArch64::fixup_aarch64_add_imm12: + if (const AArch64MCExpr *A64E = dyn_cast(Expr)) { + AArch64MCExpr::VariantKind RefKind = A64E->getKind(); + if (RefKind == AArch64MCExpr::VK_SECREL_LO12) + return COFF::IMAGE_REL_ARM64_SECREL_LOW12A; + if (RefKind == AArch64MCExpr::VK_SECREL_HI12) + return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A; + } return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A; case AArch64::fixup_aarch64_ldst_imm12_scale1: @@ -80,6 +89,11 @@ case AArch64::fixup_aarch64_ldst_imm12_scale4: case AArch64::fixup_aarch64_ldst_imm12_scale8: case AArch64::fixup_aarch64_ldst_imm12_scale16: + if (const AArch64MCExpr *A64E = dyn_cast(Expr)) { + AArch64MCExpr::VariantKind RefKind = A64E->getKind(); + if (RefKind == AArch64MCExpr::VK_SECREL_LO12) + return COFF::IMAGE_REL_ARM64_SECREL_LOW12L; + } return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L; case AArch64::fixup_aarch64_pcrel_adrp_imm21: Index: llvm/trunk/test/MC/AArch64/coff-relocations.s =================================================================== --- llvm/trunk/test/MC/AArch64/coff-relocations.s +++ llvm/trunk/test/MC/AArch64/coff-relocations.s @@ -45,6 +45,13 @@ ldrb w0, [x0, :lo12:foo + 0x12345] ldr x0, [x0, :lo12:foo + 0x12348] +; IMAGE_REL_ARM64_SECREL_LOW12A +add x0, x0, :secrel_lo12:foo +; IMAGE_REL_ARM64_SECREL_HIGH12A +add x0, x0, :secrel_hi12:foo +; IMAGE_REL_ARM64_SECREL_LOW12L +ldr x0, [x0, :secrel_lo12:foo] + ; CHECK: Format: COFF-ARM64 ; CHECK: Arch: aarch64 ; CHECK: AddressSize: 64bit @@ -64,6 +71,9 @@ ; CHECK: 0x34 IMAGE_REL_ARM64_PAGEOFFSET_12A foo ; CHECK: 0x38 IMAGE_REL_ARM64_PAGEOFFSET_12L foo ; CHECK: 0x3C IMAGE_REL_ARM64_PAGEOFFSET_12L foo +; CHECK: 0x40 IMAGE_REL_ARM64_SECREL_LOW12A foo +; CHECK: 0x44 IMAGE_REL_ARM64_SECREL_HIGH12A foo +; CHECK: 0x48 IMAGE_REL_ARM64_SECREL_LOW12L foo ; CHECK: } ; CHECK: ] @@ -71,3 +81,6 @@ ; DISASM: 34: 00 14 0d 91 add x0, x0, #837 ; DISASM: 38: 00 14 4d 39 ldrb w0, [x0, #837] ; DISASM: 3c: 00 a4 41 f9 ldr x0, [x0, #840] +; DISASM: 40: 00 00 00 91 add x0, x0, #0 +; DISASM: 44: 00 00 40 91 add x0, x0, #0, lsl #12 +; DISASM: 48: 00 00 40 f9 ldr x0, [x0]