diff --git a/lld/test/ELF/aarch64-branch-to-branch.s b/lld/test/ELF/aarch64-branch-to-branch.s index c970fe308579d..f6c96b2e10e52 100644 --- a/lld/test/ELF/aarch64-branch-to-branch.s +++ b/lld/test/ELF/aarch64-branch-to-branch.s @@ -35,14 +35,14 @@ vtable: # B2B-NEXT: [[VF:[0-9a-f]{8}]] # B2B-RELOC-NEXT: R_AARCH64_PLT32 f3 # NOB2B-RELOC-NEXT: R_AARCH64_PLT32 f1 -.4byte f1@PLT - vtable +.4byte %pltpcrel(f1) # B2B-SAME: [[VF]] # B2B-RELOC-NEXT: R_AARCH64_PLT32 f3+0x4 # NOB2B-RELOC-NEXT: R_AARCH64_PLT32 f2+0x4 -.4byte f2@PLT - vtable +.4byte %pltpcrel(f2+4) # B2B-SAME: [[VF]] # RELOC-NEXT: R_AARCH64_PLT32 f3+0x8 -.4byte f3@PLT - vtable +.4byte %pltpcrel(f3+8) .section .text._start,"ax" .globl _start diff --git a/lld/test/ELF/aarch64-feature-bti.s b/lld/test/ELF/aarch64-feature-bti.s index 8d7c1f2826c17..a1f46da156dc6 100644 --- a/lld/test/ELF/aarch64-feature-bti.s +++ b/lld/test/ELF/aarch64-feature-bti.s @@ -290,5 +290,5 @@ func1: .ifdef RELVTABLE_PLT // R_AARCH64_PLT32 -.word funcRelVtable@PLT - . +.word %pltpcrel(funcRelVtable) .endif diff --git a/lld/test/ELF/aarch64-range-thunk-extension-plt32.s b/lld/test/ELF/aarch64-range-thunk-extension-plt32.s index 9ebf7f5c69526..86b6154d9af2f 100644 --- a/lld/test/ELF/aarch64-range-thunk-extension-plt32.s +++ b/lld/test/ELF/aarch64-range-thunk-extension-plt32.s @@ -25,7 +25,7 @@ .global _start .type _start, %function _start: - .word callee@PLT - . + .word %pltpcrel(callee) .section .text.2, "ax", %progbits .global callee diff --git a/lld/test/ELF/aarch64-reloc-gotpcrel32.s b/lld/test/ELF/aarch64-reloc-gotpcrel32.s index 4d007776a86a7..35dfe756f4b24 100644 --- a/lld/test/ELF/aarch64-reloc-gotpcrel32.s +++ b/lld/test/ELF/aarch64-reloc-gotpcrel32.s @@ -17,11 +17,11 @@ _start: // PC = 0x303a0 // bar@GOTPCREL-4 = 0x20390 (got entry for `bar`) - 0x303a8 (.) - 4 = 0xe4fffeff // CHECK: Contents of section .data: // CHECK-NEXT: {{.*}} f0fffeff f0fffeff e4fffeff - .word bar@GOTPCREL - .word bar@GOTPCREL+4 - .word bar@GOTPCREL-4 + .word %gotpcrel(bar) + .word %gotpcrel(bar+4) + .word %gotpcrel(bar-4) // WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz' // WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz' - .word baz@GOTPCREL+0xffffffff - .word baz@GOTPCREL-0xffffffff + .word %gotpcrel(baz+0xffffffff) + .word %gotpcrel(baz-0xffffffff) diff --git a/lld/test/ELF/aarch64-reloc-plt32.s b/lld/test/ELF/aarch64-reloc-plt32.s index 8a3b989a909b8..cd442e76fcf3d 100644 --- a/lld/test/ELF/aarch64-reloc-plt32.s +++ b/lld/test/ELF/aarch64-reloc-plt32.s @@ -32,6 +32,6 @@ .globl _start _start: .data - .word foo@PLT - . + 2149589079 - .word foo@PLT - . - 2145378212 - .word foo@PLT - . + .word %pltpcrel(foo + 2149589079) + .word %pltpcrel(foo - 2145378212) + .word %pltpcrel(foo) diff --git a/lld/test/ELF/aarch64-undefined-weak.s b/lld/test/ELF/aarch64-undefined-weak.s index 52edc8776773f..b7d98c0fde463 100644 --- a/lld/test/ELF/aarch64-undefined-weak.s +++ b/lld/test/ELF/aarch64-undefined-weak.s @@ -37,7 +37,7 @@ _start: // R_AARCH64_PREL16 .hword target - . // R_AARCH64_PLT32 - .word target@PLT - . + .word %pltpcrel(target) bl_undefweak2: bl undefweak2 diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 636d4f8a9ca3a..1b921e5ac7b9d 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -181,6 +181,7 @@ class AArch64AsmParser : public MCTargetAsmParser { bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo, OperandVector &Operands); + bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E); bool parseDataExpr(const MCExpr *&Res) override; bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc); @@ -8190,8 +8191,31 @@ bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) { return false; } +bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) { + SMLoc Loc = getLoc(); + if (getLexer().getKind() != AsmToken::Identifier) + return TokError("expected '%' relocation specifier"); + StringRef Identifier = getParser().getTok().getIdentifier(); + auto Spec = AArch64::parsePercentSpecifierName(Identifier); + if (!Spec) + return TokError("invalid relocation specifier"); + + getParser().Lex(); // Eat the identifier + if (parseToken(AsmToken::LParen, "expected '('")) + return true; + + const MCExpr *SubExpr; + if (getParser().parseParenExpression(SubExpr, E)) + return true; + + Res = MCSpecifierExpr::create(SubExpr, Spec, getContext(), Loc); + return false; +} + bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) { SMLoc EndLoc; + if (parseOptionalToken(AsmToken::Percent)) + return parseExprWithSpecifier(Res, EndLoc); if (getParser().parseExpression(Res)) return true; @@ -8211,14 +8235,6 @@ bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) { if (STI->getTargetTriple().isOSBinFormatMachO()) { if (Identifier == "got") Spec = AArch64::S_MACHO_GOT; - } else { - // Unofficial, experimental syntax that will be changed. - if (Identifier == "gotpcrel") - Spec = AArch64::S_GOTPCREL; - else if (Identifier == "plt") - Spec = AArch64::S_PLT; - else if (Identifier == "funcinit") - Spec = AArch64::S_FUNCINIT; } if (Spec == AArch64::S_None) return Error(Loc, "invalid relocation specifier"); diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 892b8da37eb69..a945b9077f412 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -104,6 +104,18 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup, break; } + switch (RefKind) { + case AArch64::S_GOTPCREL: + case AArch64::S_PLT: + if (Kind == FK_Data_4) + break; + reportError(Fixup.getLoc(), AArch64::getSpecifierName(RefKind) + + " can only be used in a .word directive"); + return ELF::R_AARCH64_NONE; + default: + break; + } + // Extract the relocation type from the fixup kind, after applying STT_TLS as // needed. if (mc::isRelocation(Fixup.getKind())) @@ -117,8 +129,7 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup, case FK_Data_2: return R_CLS(PREL16); case FK_Data_4: { - return Target.getSpecifier() == AArch64::S_PLT ? R_CLS(PLT32) - : R_CLS(PREL32); + return R_CLS(PREL32); } case FK_Data_8: if (IsILP32) { @@ -220,9 +231,13 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup, case FK_Data_2: return R_CLS(ABS16); case FK_Data_4: - return (!IsILP32 && Target.getSpecifier() == AArch64::S_GOTPCREL) - ? ELF::R_AARCH64_GOTPCREL32 - : R_CLS(ABS32); + if (!IsILP32) { + if (Target.getSpecifier() == AArch64::S_GOTPCREL) + return ELF::R_AARCH64_GOTPCREL32; + if (Target.getSpecifier() == AArch64::S_PLT) + return ELF::R_AARCH64_PLT32; + } + return R_CLS(ABS32); case FK_Data_8: { if (IsILP32) { reportError( diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp index bc090c6157eef..6a521fde39c56 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp @@ -114,12 +114,24 @@ StringRef AArch64::getSpecifierName(AArch64::Specifier S) { case AArch64::S_GOT_AUTH: return ":got_auth:"; case AArch64::S_GOT_AUTH_PAGE: return ":got_auth:"; case AArch64::S_GOT_AUTH_LO12: return ":got_auth_lo12:"; + + case AArch64::S_GOTPCREL: return "%gotpcrel"; + case AArch64::S_PLT: return "%pltpcrel"; + case AArch64::S_FUNCINIT: return "%funcinit"; default: llvm_unreachable("Invalid relocation specifier"); } // clang-format on } +AArch64::Specifier AArch64::parsePercentSpecifierName(StringRef name) { + return StringSwitch(name) + .Case("pltpcrel", AArch64::S_PLT) + .Case("gotpcrel", AArch64::S_GOTPCREL) + .Case("funcinit", AArch64::S_FUNCINIT) + .Default(0); +} + static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm) { if (!Expr.getSubExpr()->evaluateAsRelocatable(Res, Asm)) @@ -233,8 +245,13 @@ void AArch64MCAsmInfoELF::printSpecifierExpr( raw_ostream &OS, const MCSpecifierExpr &Expr) const { if (auto *AE = dyn_cast(&Expr)) return AE->print(OS, this); - OS << AArch64::getSpecifierName(Expr.getSpecifier()); + auto Str = AArch64::getSpecifierName(Expr.getSpecifier()); + OS << Str; + if (!Str.empty() && Str[0] == '%') + OS << '('; printExpr(OS, *Expr.getSubExpr()); + if (!Str.empty() && Str[0] == '%') + OS << ')'; } bool AArch64MCAsmInfoELF::evaluateAsRelocatableImpl( diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h index f2acff54f1665..5bb8ff8599b2a 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h @@ -184,6 +184,8 @@ enum { /// (e.g. ":got:", ":lo12:"). StringRef getSpecifierName(Specifier S); +Specifier parsePercentSpecifierName(StringRef); + inline Specifier getSymbolLoc(Specifier S) { return static_cast(S & AArch64::S_SymLocBits); } diff --git a/llvm/test/MC/AArch64/data-directive-specifier.s b/llvm/test/MC/AArch64/data-directive-specifier.s index 2d1ec4feddfa3..f964b3cf92ecb 100644 --- a/llvm/test/MC/AArch64/data-directive-specifier.s +++ b/llvm/test/MC/AArch64/data-directive-specifier.s @@ -1,57 +1,65 @@ +# RUN: llvm-mc -triple=aarch64 %s | FileCheck %s --check-prefix=ASM # RUN: llvm-mc -triple=aarch64 -filetype=obj %s | llvm-readobj -r - | FileCheck %s -# RUN: not llvm-mc -triple=aarch64 %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error: -# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym OBJERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=OBJERR --implicit-check-not=error: + +# RUN: not llvm-mc -triple=aarch64 %s --defsym ERR0=1 2>&1 | FileCheck %s --check-prefix=ERR0 --implicit-check-not=error: +# RUN: not llvm-mc -triple=aarch64 -filetype=obj %s --defsym ERR=1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error: .globl g g: l: +# ASM: .word %pltpcrel(l) # CHECK: Section ({{.*}}) .rela.data { # CHECK-NEXT: 0x0 R_AARCH64_PLT32 l 0x0 -# CHECK-NEXT: 0x4 R_AARCH64_PLT32 l 0x4 -# CHECK-NEXT: 0x8 R_AARCH64_PLT32 extern 0x4 -# CHECK-NEXT: 0xC R_AARCH64_PLT32 g 0x8 -# CHECK-NEXT: 0x10 R_AARCH64_PLT32 g 0x18 -# CHECK-NEXT: 0x14 R_AARCH64_FUNCINIT64 .text 0x0 +# CHECK-NEXT: 0x4 R_AARCH64_PLT32 extern 0x4 +# CHECK-NEXT: 0x8 R_AARCH64_PLT32 g 0x8 # CHECK-NEXT: } .data -.word l@plt - . -.word l@plt - .data - -.word extern@plt - . + 4 -.word g@plt - . + 8 -.word g@plt - .data + 8 - -.quad l@funcinit +.word %pltpcrel(l) +.word %pltpcrel(extern + 4), %pltpcrel(g + 8) +# ASM: .word %gotpcrel(data1) # CHECK: Section ({{.*}}) .rela.data1 { # CHECK-NEXT: 0x0 R_AARCH64_GOTPCREL32 data1 0x0 # CHECK-NEXT: 0x4 R_AARCH64_GOTPCREL32 extern 0x4 -# CHECK-NEXT: 0x8 R_AARCH64_GOTPCREL32 extern 0xFFFFFFFFFFFFFFFB +# CHECK-NEXT: 0x8 R_AARCH64_GOTPCREL32 extern 0xFFFFFFFFFFFFFFFB +# CHECK-NEXT: 0xC R_AARCH64_FUNCINIT64 .text 0 # CHECK-NEXT: } .section .data1,"aw" data1: -.word data1@GOTPCREL -.word extern@gotpcrel+4 -.word extern@GOTPCREL-5 +.word %gotpcrel(data1) +.word %gotpcrel(extern+4), %gotpcrel(extern-5) -## Test parse-time errors -.ifdef ERR -# ERR: [[#@LINE+1]]:9: error: @ specifier only allowed after a symbol -.quad 3@plt - . +.quad %funcinit(l) + +.ifdef ERR0 +# ERR0: [[#@LINE+1]]:8: error: invalid relocation specifier +.word %xxx(l) -# ERR: [[#@LINE+1]]:9: error: expected ')' -.quad (l@plt - .) +# ERR0: [[#@LINE+1]]:17: error: expected '(' +.word %pltpcrel l + +# ERR0: [[#@LINE+2]]:14: error: unknown token in expression +# ERR0: [[#@LINE+1]]:14: error: invalid operand +ldr w0, [x1, %pltpcrel(g)] .endif -.ifdef OBJERR -.quad g@plt - . +.ifdef ERR +# ERR: [[#@LINE+1]]:8: error: %pltpcrel can only be used in a .word directive +.quad %pltpcrel(g) + +# ERR: [[#@LINE+1]]:8: error: expected relocatable expression +.word %pltpcrel(g-.) + +# ERR: [[#@LINE+1]]:8: error: expected relocatable expression +.word %pltpcrel(extern - und) -.word extern@gotpcrel - . +# ERR: [[#@LINE+1]]:8: error: %gotpcrel can only be used in a .word directive +.quad %gotpcrel(g) -# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression -.word extern@plt - und +# ERR: [[#@LINE+1]]:8: error: expected relocatable expression +.word %gotpcrel(extern - .) -# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression -.word extern@gotpcrel - und +# ERR: [[#@LINE+1]]:8: error: expected relocatable expression +.word %gotpcrel(extern - und) .endif diff --git a/llvm/test/MC/AArch64/elf-reloc-ptrauth.s b/llvm/test/MC/AArch64/elf-reloc-ptrauth.s index 53e0107c5cca1..06031383fe356 100644 --- a/llvm/test/MC/AArch64/elf-reloc-ptrauth.s +++ b/llvm/test/MC/AArch64/elf-reloc-ptrauth.s @@ -125,7 +125,7 @@ _g9: // ERR: :[[#@LINE+1]]:21: error: expected ')' .quad sym@AUTH(ia,42( -// ERR: :[[#@LINE+1]]:14: error: unexpected token +// ERR: :[[#@LINE+1]]:11: error: invalid relocation specifier .quad sym@PLT@AUTH(ia,42) // ERR: :[[#@LINE+1]]:15: error: expected '('