; RUN: rm -rf %t && split-file %s %t && cd %t ;--- err1.ll ; RUN: not --crash llc < err1.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s ; RUN: not --crash llc < err1.ll -mtriple arm64-apple-ios -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s @g = external global i32 define ptr @foo() { ; ERR1: LLVM ERROR: key in ptrauth global out of range [0, 3] ret ptr ptrauth (ptr @g, i32 4) } ;--- err2.ll ; RUN: not --crash llc < err2.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s ; RUN: not --crash llc < err2.ll -mtriple arm64-apple-ios -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s @g = external global i32 define ptr @foo() { ; ERR2: LLVM ERROR: constant discriminator in ptrauth global out of range [0, 0xffff] ret ptr ptrauth (ptr @g, i32 2, i64 65536) } ;--- err3.ll ; RUN: not --crash llc < err3.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s ; RUN: not --crash llc < err3.ll -mtriple arm64-apple-ios -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s @g_weak = extern_weak global i32 define ptr @foo() { ; ERR3: LLVM ERROR: unsupported non-zero offset in weak ptrauth global reference ret ptr ptrauth (ptr getelementptr (i8, ptr @g_weak, i64 16), i32 2, i64 42) } ;--- err4.ll ; RUN: not --crash llc < err4.ll -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s ; RUN: not --crash llc < err4.ll -mtriple arm64-apple-ios -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s @g_weak = extern_weak global i32 @g_weak.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g_weak, i32 2, i64 42, ptr @g_weak.ref.da.42.addr) define ptr @foo() { ; ERR4: LLVM ERROR: unsupported weak addr-div ptrauth global ret ptr ptrauth (ptr @g_weak, i32 0, i64 42, ptr @g_weak.ref.da.42.addr) } ;--- err5.ll ; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth \ ; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR5 %s @g = external global i32 define ptr @foo() { ; ERR5: LLVM ERROR: ptrauth global lowering only supported on MachO/ELF ret ptr ptrauth (ptr @g, i32 0) } ;--- ok.ll ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \ ; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=ELF ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \ ; RUN: -verify-machineinstrs -filetype=obj ; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \ ; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=MACHO ; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=0 \ ; RUN: -verify-machineinstrs -filetype=obj @g = external global i32 @g_weak = extern_weak global i32 @g_strong_def = dso_local constant i32 42 define ptr @test_global_zero_disc() { ; ELF-LABEL: test_global_zero_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: paciza x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_zero_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: paciza x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0) } define ptr @test_global_offset_zero_disc() { ; ELF-LABEL: test_global_offset_zero_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: add x16, x16, #16 ; ELF-NEXT: pacdza x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_offset_zero_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: add x16, x16, #16 ; MACHO-NEXT: pacdza x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) } define ptr @test_global_neg_offset_zero_disc() { ; ELF-LABEL: test_global_neg_offset_zero_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: sub x16, x16, #576 ; ELF-NEXT: sub x16, x16, #30, lsl #12 ; ELF-NEXT: pacdza x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_neg_offset_zero_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: sub x16, x16, #576 ; MACHO-NEXT: sub x16, x16, #30, lsl #12 ; MACHO-NEXT: pacdza x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2) } define ptr @test_global_big_offset_zero_disc() { ; ELF-LABEL: test_global_big_offset_zero_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: mov x17, #1 ; ELF-NEXT: movk x17, #32769, lsl #16 ; ELF-NEXT: add x16, x16, x17 ; ELF-NEXT: pacdza x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_big_offset_zero_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: mov x17, #1 ; MACHO-NEXT: movk x17, #32769, lsl #16 ; MACHO-NEXT: add x16, x16, x17 ; MACHO-NEXT: pacdza x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) } define ptr @test_global_big_neg_offset_zero_disc() { ; ELF-LABEL: test_global_big_neg_offset_zero_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: mov x17, #-52501 ; ELF-NEXT: movk x17, #63652, lsl #16 ; ELF-NEXT: add x16, x16, x17 ; ELF-NEXT: pacdza x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_big_neg_offset_zero_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: mov x17, #-52501 ; MACHO-NEXT: movk x17, #63652, lsl #16 ; MACHO-NEXT: add x16, x16, x17 ; MACHO-NEXT: pacdza x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2) } define ptr @test_global_huge_neg_offset_zero_disc() { ; ELF-LABEL: test_global_huge_neg_offset_zero_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: mov x17, #-65536 ; ELF-NEXT: movk x17, #0, lsl #16 ; ELF-NEXT: movk x17, #0, lsl #32 ; ELF-NEXT: movk x17, #32768, lsl #48 ; ELF-NEXT: add x16, x16, x17 ; ELF-NEXT: pacdza x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: mov x17, #-65536 ; MACHO-NEXT: movk x17, #0, lsl #16 ; MACHO-NEXT: movk x17, #0, lsl #32 ; MACHO-NEXT: movk x17, #32768, lsl #48 ; MACHO-NEXT: add x16, x16, x17 ; MACHO-NEXT: pacdza x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2) } define ptr @test_global_disc() { ; ELF-LABEL: test_global_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: mov x17, #42 // =0x2a ; ELF-NEXT: pacia x16, x17 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: mov x17, #42 ; =0x2a ; MACHO-NEXT: pacia x16, x17 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0, i64 42) } @g.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) define ptr @test_global_addr_disc() { ; ELF-LABEL: test_global_addr_disc: ; ELF: // %bb.0: ; ELF-NEXT: adrp x8, g.ref.da.42.addr ; ELF-NEXT: add x8, x8, :lo12:g.ref.da.42.addr ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: mov x17, x8 ; ELF-NEXT: movk x17, #42, lsl #48 ; ELF-NEXT: pacda x16, x17 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_addr_disc: ; MACHO: ; %bb.0: ; MACHO-NEXT: Lloh{{.*}}: ; MACHO-NEXT: adrp x8, _g.ref.da.42.addr@PAGE ; MACHO-NEXT: Lloh{{.*}}: ; MACHO-NEXT: add x8, x8, _g.ref.da.42.addr@PAGEOFF ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: mov x17, x8 ; MACHO-NEXT: movk x17, #42, lsl #48 ; MACHO-NEXT: pacda x16, x17 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) } define ptr @test_global_process_specific() { ; ELF-LABEL: test_global_process_specific: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, :got:g ; ELF-NEXT: ldr x16, [x16, :got_lo12:g] ; ELF-NEXT: pacizb x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_process_specific: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g@GOTPAGE ; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] ; MACHO-NEXT: pacizb x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 1) } ; Non-external symbols don't need to be accessed through the GOT. define ptr @test_global_strong_def() { ; ELF-LABEL: test_global_strong_def: ; ELF: // %bb.0: ; ELF-NEXT: adrp x16, g_strong_def ; ELF-NEXT: add x16, x16, :lo12:g_strong_def ; ELF-NEXT: pacdza x16 ; ELF-NEXT: mov x0, x16 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_strong_def: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x16, _g_strong_def@PAGE ; MACHO-NEXT: add x16, x16, _g_strong_def@PAGEOFF ; MACHO-NEXT: pacdza x16 ; MACHO-NEXT: mov x0, x16 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g_strong_def, i32 2) } ; weak symbols can't be assumed to be non-nil. Use $auth_ptr$ stub slot always. ; The alternative is to emit a null-check here, but that'd be redundant with ; whatever null-check follows in user code. define ptr @test_global_weak() { ; ELF-LABEL: test_global_weak: ; ELF: // %bb.0: ; ELF-NEXT: adrp x0, g_weak$auth_ptr$ia$42 ; ELF-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42] ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_weak: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x0, l_g_weak$auth_ptr$ia$42@PAGE ; MACHO-NEXT: ldr x0, [x0, l_g_weak$auth_ptr$ia$42@PAGEOFF] ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g_weak, i32 0, i64 42) } ; Test another weak symbol to check that stubs are emitted in a stable order. @g_weak_2 = extern_weak global i32 define ptr @test_global_weak_2() { ; ELF-LABEL: test_global_weak_2: ; ELF: // %bb.0: ; ELF-NEXT: adrp x0, g_weak_2$auth_ptr$ia$42 ; ELF-NEXT: ldr x0, [x0, :lo12:g_weak_2$auth_ptr$ia$42] ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_weak_2: ; MACHO: ; %bb.0: ; MACHO-NEXT: adrp x0, l_g_weak_2$auth_ptr$ia$42@PAGE ; MACHO-NEXT: ldr x0, [x0, l_g_weak_2$auth_ptr$ia$42@PAGEOFF] ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g_weak_2, i32 0, i64 42) } ; ELF-LABEL: g_weak$auth_ptr$ia$42: ; ELF-NEXT: .xword g_weak@AUTH(ia,42) ; ELF-LABEL: g_weak_2$auth_ptr$ia$42: ; ELF-NEXT: .xword g_weak_2@AUTH(ia,42) ; MACHO-LABEL: l_g_weak$auth_ptr$ia$42: ; MACHO-NEXT: .quad _g_weak@AUTH(ia,42) ; MACHO-LABEL: l_g_weak_2$auth_ptr$ia$42: ; MACHO-NEXT: .quad _g_weak_2@AUTH(ia,42)