AArch64: Replace @plt/%gotpcrel in data directives with %pltpcrel %gotpcrel (#155776)

Similar to #132569 for RISC-V, replace the unofficial `@plt` and
`@gotpcrel` relocation specifiers, currently only used by clang
-fexperimental-relative-c++-abi-vtables, with %pltpcrel %gotpcrel. The
syntax is not used in humand-written assembly code, and is not supported
by GNU assembler.

Also replace the recent `@funcinit` with `%funcinit(x)`.
diff --git a/bolt/test/AArch64/skip-non-vfuncptr-reloc-in-relative-vtable.s b/bolt/test/AArch64/skip-non-vfuncptr-reloc-in-relative-vtable.s
index 41a0031..6f29302 100644
--- a/bolt/test/AArch64/skip-non-vfuncptr-reloc-in-relative-vtable.s
+++ b/bolt/test/AArch64/skip-non-vfuncptr-reloc-in-relative-vtable.s
@@ -31,5 +31,5 @@
 _ZTV3gooE:
 	.word	0
 	.word	_fake_rtti_data-_ZTV3gooE-8
-	.word	foo@PLT-_ZTV3gooE-8
+	.word	%pltpcrel(foo)
 	.size	_ZTV3gooE, 12
diff --git a/lld/test/ELF/aarch64-branch-to-branch.s b/lld/test/ELF/aarch64-branch-to-branch.s
index c970fe3..f6c96b2 100644
--- a/lld/test/ELF/aarch64-branch-to-branch.s
+++ b/lld/test/ELF/aarch64-branch-to-branch.s
@@ -35,14 +35,14 @@
 # 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 8d7c1f2..a1f46da 100644
--- a/lld/test/ELF/aarch64-feature-bti.s
+++ b/lld/test/ELF/aarch64-feature-bti.s
@@ -290,5 +290,5 @@
 
 .ifdef RELVTABLE_PLT
 // R_AARCH64_PLT32
-.word funcRelVtable@PLT - .
+.word %pltpcrel(funcRelVtable)
 .endif
diff --git a/lld/test/ELF/aarch64-funcinit64-invalid.s b/lld/test/ELF/aarch64-funcinit64-invalid.s
index 4577db7..c0fc398 100644
--- a/lld/test/ELF/aarch64-funcinit64-invalid.s
+++ b/lld/test/ELF/aarch64-funcinit64-invalid.s
@@ -5,11 +5,11 @@
 
 .rodata
 # ERR: error: relocation R_AARCH64_FUNCINIT64 cannot be used against local symbol
-.8byte func@FUNCINIT
+.8byte %funcinit(func)
 
 .data
 # ERR: error: relocation R_AARCH64_FUNCINIT64 cannot be used against ifunc symbol 'ifunc'
-.8byte ifunc@FUNCINIT
+.8byte %funcinit(ifunc)
 
 .text
 func:
diff --git a/lld/test/ELF/aarch64-funcinit64.s b/lld/test/ELF/aarch64-funcinit64.s
index 5f2b863..1be30e2 100644
--- a/lld/test/ELF/aarch64-funcinit64.s
+++ b/lld/test/ELF/aarch64-funcinit64.s
@@ -10,7 +10,7 @@
 .data
 # CHECK: R_AARCH64_IRELATIVE [[FOO:[0-9a-f]*]]
 # ERR: relocation R_AARCH64_FUNCINIT64 cannot be used against preemptible symbol 'foo'
-.8byte foo@FUNCINIT
+.8byte %funcinit(foo)
 
 .text
 # CHECK: {{0*}}[[FOO]] {{.*}} foo
diff --git a/lld/test/ELF/aarch64-range-thunk-extension-plt32.s b/lld/test/ELF/aarch64-range-thunk-extension-plt32.s
index 9ebf7f5..86b6154 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 4d00777..35dfe75 100644
--- a/lld/test/ELF/aarch64-reloc-gotpcrel32.s
+++ b/lld/test/ELF/aarch64-reloc-gotpcrel32.s
@@ -17,11 +17,11 @@
 // 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 8a3b989..cd442e7 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 52edc87..b7d98c0 100644
--- a/lld/test/ELF/aarch64-undefined-weak.s
+++ b/lld/test/ELF/aarch64-undefined-weak.s
@@ -37,7 +37,7 @@
 // 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/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 2b8db27..87fbe9b 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2671,8 +2671,9 @@
         MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
   OutStreamer->popSection();
 
-  return MCSymbolRefExpr::create(IRelativeSym, AArch64::S_FUNCINIT,
-                                 OutStreamer->getContext());
+  return MCSpecifierExpr::create(
+      MCSymbolRefExpr::create(IRelativeSym, OutStreamer->getContext()),
+      AArch64::S_FUNCINIT, OutStreamer->getContext());
 }
 
 const MCExpr *
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 85778c1..590da8f 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -182,6 +182,7 @@
   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);
 
@@ -8452,8 +8453,31 @@
   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;
@@ -8473,14 +8497,6 @@
   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 892b8da..e33196d 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -104,6 +104,20 @@
     break;
   }
 
+  switch (RefKind) {
+  case AArch64::S_GOTPCREL:
+  case AArch64::S_PLT:
+    if (Kind == FK_Data_4)
+      break;
+    // Only R_AARCH64_PLT32/R_AARCH64_GOTPCREL32 defined at present, but can
+    // be extended to other sizes if additional relocations are defined.
+    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 +131,7 @@
     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 +233,13 @@
     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 c6a4723..9c04365 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
@@ -114,12 +114,24 @@
   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<AArch64::Specifier>(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))
@@ -232,8 +244,13 @@
     raw_ostream &OS, const MCSpecifierExpr &Expr) const {
   if (auto *AE = dyn_cast<AArch64AuthMCExpr>(&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 f2acff5..5bb8ff8 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
@@ -184,6 +184,8 @@
 /// (e.g. ":got:", ":lo12:").
 StringRef getSpecifierName(Specifier S);
 
+Specifier parsePercentSpecifierName(StringRef);
+
 inline Specifier getSymbolLoc(Specifier S) {
   return static_cast<Specifier>(S & AArch64::S_SymLocBits);
 }
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
index 1e0af68..f0ac7a8 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
@@ -8,7 +8,7 @@
 ; CHECK-NEXT: mov x1, #1
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .rodata
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @nullref = constant ptr ptrauth (ptr null, i32 2, i64 1, ptr null), align 8
 
 @dsolocal = external dso_local global i8
@@ -22,7 +22,7 @@
 ; CHECK-NEXT: mov x1, #2
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @dsolocalref = constant ptr ptrauth (ptr @dsolocal, i32 2, i64 2, ptr null), align 8
 
 @ds = external global i8
@@ -39,7 +39,7 @@
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: ret
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @dsolocalrefds = constant ptr ptrauth (ptr @dsolocal, i32 2, i64 2, ptr null, ptr @ds), align 8
 
 ; CHECK: dsolocalref8:
@@ -51,7 +51,7 @@
 ; CHECK-NEXT: mov x1, #3
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @dsolocalref8 = constant ptr ptrauth (ptr getelementptr (i8, ptr @dsolocal, i64 8), i32 2, i64 3, ptr null), align 8
 
 ; CHECK: disc:
@@ -64,7 +64,7 @@
 ; CHECK-NEXT: add x1, x1, :lo12:[[PLACE]]
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @disc = constant ptr ptrauth (ptr @dsolocal, i32 2, i64 0, ptr @disc), align 8
 
 ; CHECK: disc65536:
@@ -77,7 +77,7 @@
 ; CHECK-NEXT: add x1, x1, :lo12:[[PLACE]]+65536
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @disc65536 = constant ptr ptrauth (ptr @dsolocal, i32 2, i64 65536, ptr @disc), align 8
 
 @global = external global i8
@@ -91,7 +91,7 @@
 ; CHECK-NEXT: mov x1, #4
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @globalref = constant ptr ptrauth (ptr @global, i32 2, i64 4, ptr null), align 8
 
 ; CHECK: globalref8:
@@ -104,7 +104,7 @@
 ; CHECK-NEXT: mov x1, #5
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @globalref8 = constant ptr ptrauth (ptr getelementptr (i8, ptr @global, i64 8), i32 2, i64 5, ptr null), align 8
 
 ; CHECK: globalref16777216:
@@ -119,7 +119,7 @@
 ; CHECK-NEXT: mov x1, #5
 ; CHECK-NEXT: b __emupac_pacda
 ; CHECK-NEXT: .section .data.rel.ro
-; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+; CHECK-NEXT: .xword %funcinit([[FUNC]])
 @globalref16777216 = constant ptr ptrauth (ptr getelementptr (i8, ptr @global, i64 16777216), i32 2, i64 5, ptr null), align 8
 
 $comdat = comdat any
diff --git a/llvm/test/MC/AArch64/data-directive-specifier.s b/llvm/test/MC/AArch64/data-directive-specifier.s
index 2d1ec4f..f964b3c 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 %pltpcrel(l)
+.word %pltpcrel(extern + 4), %pltpcrel(g + 8)
 
-.word extern@plt - . + 4
-.word g@plt - . + 8
-.word g@plt - .data + 8
-
-.quad l@funcinit
-
+# 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)
 
-# ERR: [[#@LINE+1]]:9: error: expected ')'
-.quad (l@plt - .)
+.ifdef ERR0
+# ERR0: [[#@LINE+1]]:8: error: invalid relocation specifier
+.word %xxx(l)
+
+# 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)
 
-.word extern@gotpcrel - .
+# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
+.word %pltpcrel(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 %pltpcrel(extern - und)
 
-# OBJERR: [[#@LINE+1]]:7: error: symbol 'und' can not be undefined in a subtraction expression
-.word extern@gotpcrel - und
+# ERR: [[#@LINE+1]]:8: error: %gotpcrel can only be used in a .word directive
+.quad %gotpcrel(g)
+
+# ERR: [[#@LINE+1]]:8: error: expected relocatable expression
+.word %gotpcrel(extern - .)
+
+# 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 53e0107..0603138 100644
--- a/llvm/test/MC/AArch64/elf-reloc-ptrauth.s
+++ b/llvm/test/MC/AArch64/elf-reloc-ptrauth.s
@@ -125,7 +125,7 @@
 // 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 '('