Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,40 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
MI.eraseFromParent();
return true;
}
case AArch64::LOADgotAUTH: {
Register DstReg = MI.getOperand(0).getReg();
const MachineOperand &MO1 = MI.getOperand(1);

MachineOperand GAHiOp(MO1);
MachineOperand GALoOp(MO1);
GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);

DebugLoc DL = MI.getDebugLoc();
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), AArch64::X16)
.add(GAHiOp);

BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDXri), AArch64::X16)
.addReg(AArch64::X16)
.add(GALoOp)
.addImm(0);

BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui), DstReg)
.addReg(AArch64::X16)
.addImm(0);

assert(MO1.isGlobal());
assert(MO1.getGlobal()->getValueType() != nullptr);
unsigned AuthOpcode = MO1.getGlobal()->getValueType()->isFunctionTy()
? AArch64::AUTIA
: AArch64::AUTDA;
BuildMI(MBB, MBBI, DL, TII->get(AuthOpcode), DstReg)
.addReg(DstReg)
.addReg(AArch64::X16);

MI.eraseFromParent();
return true;
}
case AArch64::LOADgot: {
MachineFunction *MF = MBB.getParent();
Register DstReg = MI.getOperand(0).getReg();
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/AArch64/AArch64FastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@ unsigned AArch64FastISel::materializeGV(const GlobalValue *GV) {
if (!Subtarget->useSmallAddressing() && !Subtarget->isTargetMachO())
return 0;

if (FuncInfo.MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT())
return 0;

unsigned OpFlags = Subtarget->ClassifyGlobalReference(GV, TM);

EVT DestEVT = TLI.getValueType(DL, GV->getType(), true);
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9044,6 +9044,11 @@ SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG,
SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT | Flags);
// FIXME: Once remat is capable of dealing with instructions with register
// operands, expand this into two nodes instead of using a wrapper node.
if (DAG.getMachineFunction()
.getInfo<AArch64FunctionInfo>()
->hasELFSignedGOT())
return SDValue(DAG.getMachineNode(AArch64::LOADgotAUTH, DL, Ty, GotAddr),
0);
return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr);
}

Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -1785,6 +1785,10 @@ let Predicates = [HasPAuth] in {
(AUTH_TCRETURN_BTI tcGPRx16x17:$dst, imm:$FPDiff, imm:$Key,
imm:$Disc, tcGPR64:$AddrDisc)>;

def LOADgotAUTH : Pseudo<(outs GPR64common:$dst), (ins i64imm:$addr), []>,
Sched<[WriteI, ReadI]> {
let Defs = [X16];
}
}

// v9.5-A pointer authentication extensions
Expand Down
10 changes: 7 additions & 3 deletions llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "AArch64MCInstLower.h"
#include "AArch64MachineFunctionInfo.h"
#include "MCTargetDesc/AArch64MCExpr.h"
#include "Utils/AArch64BaseInfo.h"
#include "llvm/CodeGen/AsmPrinter.h"
Expand Down Expand Up @@ -184,9 +185,12 @@ MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
MCSymbol *Sym) const {
uint32_t RefFlags = 0;

if (MO.getTargetFlags() & AArch64II::MO_GOT)
RefFlags |= AArch64MCExpr::VK_GOT;
else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
if (MO.getTargetFlags() & AArch64II::MO_GOT) {
const MachineFunction *MF = MO.getParent()->getParent()->getParent();
RefFlags |= (MF->getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
? AArch64MCExpr::VK_GOT_AUTH
: AArch64MCExpr::VK_GOT);
} else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
TLSModel::Model Model;
if (MO.isGlobal()) {
const GlobalValue *GV = MO.getGlobal();
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "AArch64MachineFunctionInfo.h"
#include "AArch64InstrInfo.h"
#include "AArch64Subtarget.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
Expand Down Expand Up @@ -82,6 +83,25 @@ static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
return Key == "b_key";
}

static bool hasELFSignedGOTHelper(const Function &F,
const AArch64Subtarget *STI) {
if (!Triple(STI->getTargetTriple()).isOSBinFormatELF())
return false;
const Module *M = F.getParent();
uint64_t PAuthABIPlatform = -1;
if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
M->getModuleFlag("aarch64-elf-pauthabi-platform")))
PAuthABIPlatform = PAP->getZExtValue();
if (PAuthABIPlatform != ELF::AARCH64_PAUTH_PLATFORM_LLVM_LINUX)
return false;
uint64_t PAuthABIVersion = -1;
if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
M->getModuleFlag("aarch64-elf-pauthabi-version")))
PAuthABIVersion = PAV->getZExtValue();
return (PAuthABIVersion &
(1 << ELF::AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT)) != 0;
}

AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
const AArch64Subtarget *STI) {
// If we already know that the function doesn't have a redzone, set
Expand All @@ -90,6 +110,7 @@ AArch64FunctionInfo::AArch64FunctionInfo(const Function &F,
HasRedZone = false;
std::tie(SignReturnAddress, SignReturnAddressAll) = GetSignReturnAddress(F);
SignWithBKey = ShouldSignWithBKey(F, *STI);
HasELFSignedGOT = hasELFSignedGOTHelper(F, STI);
// TODO: skip functions that have no instrumented allocas for optimization
IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag);

Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
/// SignWithBKey modifies the default PAC-RET mode to signing with the B key.
bool SignWithBKey = false;

/// HasELFSignedGOT is true if the target binary format is ELF and the IR
/// module containing the corresponding function has the following flags:
/// - aarch64-elf-pauthabi-platform flag equal to
/// AARCH64_PAUTH_PLATFORM_LLVM_LINUX;
/// - aarch64-elf-pauthabi-version flag with
/// AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_GOT bit set.
bool HasELFSignedGOT = false;

/// SigningInstrOffset captures the offset of the PAC-RET signing instruction
/// within the prologue, so it can be re-used for authentication in the
/// epilogue when using PC as a second salt (FEAT_PAuth_LR)
Expand Down Expand Up @@ -482,6 +490,8 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {

bool shouldSignWithBKey() const { return SignWithBKey; }

bool hasELFSignedGOT() const { return HasELFSignedGOT; }

MCSymbol *getSigningInstrLabel() const { return SignInstrLabel; }
void setSigningInstrLabel(MCSymbol *Label) { SignInstrLabel = Label; }

Expand Down
32 changes: 19 additions & 13 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,7 @@ class AArch64Operand : public MCParsedAsmOperand {
if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
ELFRefKind == AArch64MCExpr::VK_LO12 ||
ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
Expand Down Expand Up @@ -986,19 +987,20 @@ class AArch64Operand : public MCParsedAsmOperand {
int64_t Addend;
if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
DarwinRefKind, Addend)) {
return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
|| DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
|| (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
|| ELFRefKind == AArch64MCExpr::VK_LO12
|| ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
|| ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
|| ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
|| ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
|| ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
|| ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
|| ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
|| ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
|| ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF ||
(DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0) ||
ELFRefKind == AArch64MCExpr::VK_LO12 ||
ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
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.
Expand Down Expand Up @@ -3250,6 +3252,7 @@ ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
ELFRefKind != AArch64MCExpr::VK_ABS_PAGE_NC &&
ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE &&
ELFRefKind != AArch64MCExpr::VK_GOT_PAGE_LO15 &&
ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
Expand Down Expand Up @@ -4334,6 +4337,8 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
.Case("got", AArch64MCExpr::VK_GOT_PAGE)
.Case("gotpage_lo15", AArch64MCExpr::VK_GOT_PAGE_LO15)
.Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
.Case("got_auth", AArch64MCExpr::VK_GOT_AUTH_PAGE)
.Case("got_auth_lo12", AArch64MCExpr::VK_GOT_AUTH_LO12)
.Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
.Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
.Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
Expand Down Expand Up @@ -5708,6 +5713,7 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,

// Only allow these with ADDXri/ADDWri
if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
ELFRefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2827,7 +2827,9 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
}

if (OpFlags & AArch64II::MO_GOT) {
I.setDesc(TII.get(AArch64::LOADgot));
I.setDesc(TII.get(MF.getInfo<AArch64FunctionInfo>()->hasELFSignedGOT()
? AArch64::LOADgotAUTH
: AArch64::LOADgot));
I.getOperand(1).setTargetFlags(OpFlags);
} else if (TM.getCodeModel() == CodeModel::Large &&
!TM.isPositionIndependent()) {
Expand Down
34 changes: 29 additions & 5 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
}
if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
return R_CLS(ADR_GOT_PAGE);
if (SymLoc == AArch64MCExpr::VK_GOT_AUTH && !IsNC) {
if (IsILP32) {
Ctx.reportError(Fixup.getLoc(),
"ILP32 ADRP AUTH relocation not supported "
"(LP64 eqv: AUTH_ADR_GOT_PAGE)");
return ELF::R_AARCH64_NONE;
}
return ELF::R_AARCH64_AUTH_ADR_GOT_PAGE;
}
if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21);
if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
Expand Down Expand Up @@ -237,6 +246,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
return R_CLS(TLSLE_ADD_TPREL_LO12);
if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
return R_CLS(TLSDESC_ADD_LO12);
if (RefKind == AArch64MCExpr::VK_GOT_AUTH_LO12 && IsNC) {
if (IsILP32) {
Ctx.reportError(Fixup.getLoc(),
"ILP32 ADD AUTH relocation not supported "
"(LP64 eqv: AUTH_GOT_ADD_LO12_NC)");
return ELF::R_AARCH64_NONE;
}
return ELF::R_AARCH64_AUTH_GOT_ADD_LO12_NC;
}
if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
return R_CLS(ADD_ABS_LO12_NC);

Expand Down Expand Up @@ -329,17 +347,23 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
case AArch64::fixup_aarch64_ldst_imm12_scale8:
if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
return R_CLS(LDST64_ABS_LO12_NC);
if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
if ((SymLoc == AArch64MCExpr::VK_GOT ||
SymLoc == AArch64MCExpr::VK_GOT_AUTH) &&
IsNC) {
AArch64MCExpr::VariantKind AddressLoc =
AArch64MCExpr::getAddressFrag(RefKind);
bool IsAuth = (SymLoc == AArch64MCExpr::VK_GOT_AUTH);
if (!IsILP32) {
if (AddressLoc == AArch64MCExpr::VK_LO15)
return ELF::R_AARCH64_LD64_GOTPAGE_LO15;
return ELF::R_AARCH64_LD64_GOT_LO12_NC;
return (IsAuth ? ELF::R_AARCH64_AUTH_GOT_LO12_NC
: ELF::R_AARCH64_LD64_GOT_LO12_NC);
}
Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
"relocation not supported (LP64 eqv: "
"LD64_GOT_LO12_NC)");
Ctx.reportError(Fixup.getLoc(),
Twine("ILP32 64-bit load/store "
"relocation not supported (LP64 eqv: ") +
(IsAuth ? "AUTH_GOT_LO12_NC" : "LD64_GOT_LO12_NC") +
Twine(')'));
return ELF::R_AARCH64_NONE;
}
if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const AArch64MCExpr *AArch64MCExpr::create(const MCExpr *Expr, VariantKind Kind,
}

StringRef AArch64MCExpr::getVariantKindName() const {
// clang-format off
switch (static_cast<uint32_t>(getKind())) {
case VK_CALL: return "";
case VK_LO12: return ":lo12:";
Expand Down Expand Up @@ -82,9 +83,13 @@ StringRef AArch64MCExpr::getVariantKindName() const {
case VK_TLSDESC_PAGE: return ":tlsdesc:";
case VK_SECREL_LO12: return ":secrel_lo12:";
case VK_SECREL_HI12: return ":secrel_hi12:";
case VK_GOT_AUTH: return ":got_auth:";
case VK_GOT_AUTH_PAGE: return ":got_auth:";
case VK_GOT_AUTH_LO12: return ":got_auth_lo12:";
default:
llvm_unreachable("Invalid ELF symbol kind");
}
// clang-format on
}

void AArch64MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace llvm {
class AArch64MCExpr : public MCTargetExpr {
public:
enum VariantKind {
// clang-format off
// Symbol locations specifying (roughly speaking) what calculation should be
// performed to construct the final address for the relocated
// symbol. E.g. direct, via the GOT, ...
Expand All @@ -38,6 +39,7 @@ class AArch64MCExpr : public MCTargetExpr {
VK_SECREL = 0x009,
VK_AUTH = 0x00a,
VK_AUTHADDR = 0x00b,
VK_GOT_AUTH = 0x00c,
VK_SymLocBits = 0x00f,

// Variants specifying which part of the final address calculation is
Expand Down Expand Up @@ -88,6 +90,8 @@ class AArch64MCExpr : public MCTargetExpr {
VK_GOT_LO12 = VK_GOT | VK_PAGEOFF | VK_NC,
VK_GOT_PAGE = VK_GOT | VK_PAGE,
VK_GOT_PAGE_LO15 = VK_GOT | VK_LO15 | VK_NC,
VK_GOT_AUTH_LO12 = VK_GOT_AUTH | VK_PAGEOFF | VK_NC,
VK_GOT_AUTH_PAGE = VK_GOT_AUTH | VK_PAGE,
VK_DTPREL_G2 = VK_DTPREL | VK_G2,
VK_DTPREL_G1 = VK_DTPREL | VK_G1,
VK_DTPREL_G1_NC = VK_DTPREL | VK_G1 | VK_NC,
Expand All @@ -114,6 +118,7 @@ class AArch64MCExpr : public MCTargetExpr {
VK_SECREL_HI12 = VK_SECREL | VK_HI12,

VK_INVALID = 0xfff
// clang-format on
};

private:
Expand Down
39 changes: 39 additions & 0 deletions llvm/test/CodeGen/AArch64/basic-pic-auth.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \
; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s
; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \
; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s
; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=1 -verify-machineinstrs \
; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s

;; Note: for FastISel, we fall back to SelectionDAG

@var = global i32 0

define i32 @get_globalvar() {
; CHECK-LABEL: get_globalvar:

%val = load i32, ptr @var

; CHECK: adrp x[[GOT:[0-9]+]], :got_auth:var
; CHECK: add x[[GOT]], x[[GOT]], :got_auth_lo12:var
; CHECK: ldr x[[SYM:[0-9]+]], [x[[GOT]]]
; CHECK: autda x[[SYM]], x[[GOT]]
; CHECK: ldr w0, [x[[SYM]]]
ret i32 %val
}

define ptr @get_globalvaraddr() {
; CHECK-LABEL: get_globalvaraddr:

%val = load i32, ptr @var

; CHECK: adrp x[[GOT:[0-9]+]], :got_auth:var
; CHECK: add x[[GOT]], x[[GOT]], :got_auth_lo12:var
; CHECK: ldr x0, [x[[GOT]]]
; CHECK: autda x0, x[[GOT]]
ret ptr @var
}

!llvm.module.flags = !{!0, !1}
!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 128}
Loading