1; RUN: llc -mtriple=i686 %s -o - | FileCheck --check-prefixes=CHECK,X86 %s 2; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,X64 %s 3 4;; -fpatchable-function-entry=0 -fcf-protection=branch 5define void @f0() "patchable-function-entry"="0" { 6; CHECK-LABEL: f0: 7; CHECK-NEXT: .Lfunc_begin0: 8; CHECK-NEXT: .cfi_startproc 9; CHECK-NEXT: # %bb.0: 10; X86-NEXT: endbr32 11; X64-NEXT: endbr64 12; CHECK-NEXT: ret 13; CHECK-NOT: .section __patchable_function_entries 14 ret void 15} 16 17;; -fpatchable-function-entry=1 -fcf-protection=branch 18;; For M=0, place the label .Lpatch0 after the initial ENDBR. 19;; .cfi_startproc should be placed at the function entry. 20define void @f1() "patchable-function-entry"="1" { 21; CHECK-LABEL: f1: 22; CHECK-NEXT: .Lfunc_begin1: 23; CHECK-NEXT: .cfi_startproc 24; CHECK-NEXT: # %bb.0: 25; X86-NEXT: endbr32 26; X64-NEXT: endbr64 27; CHECK-NEXT: .Lpatch0: 28; CHECK-NEXT: nop 29; CHECK-NEXT: ret 30; CHECK: .section __patchable_function_entries,"awo",@progbits,f1{{$}} 31; X86-NEXT: .p2align 2 32; X86-NEXT: .long .Lpatch0 33; X64-NEXT: .p2align 3 34; X64-NEXT: .quad .Lpatch0 35 ret void 36} 37 38;; -fpatchable-function-entry=2,1 -fcf-protection=branch 39define void @f2_1() "patchable-function-entry"="1" "patchable-function-prefix"="1" { 40; CHECK-LABEL: .type f2_1,@function 41; CHECK-NEXT: .Ltmp0: 42; CHECK-NEXT: nop 43; CHECK-NEXT: f2_1: 44; CHECK-NEXT: .Lfunc_begin2: 45; CHECK-NEXT: .cfi_startproc 46; CHECK-NEXT: # %bb.0: 47; X86-NEXT: endbr32 48; X64-NEXT: endbr64 49; CHECK-NEXT: nop 50; CHECK-NEXT: ret 51; CHECK: .Lfunc_end2: 52; CHECK-NEXT: .size f2_1, .Lfunc_end2-f2_1 53; CHECK: .section __patchable_function_entries,"awo",@progbits,f2_1{{$}} 54; X86-NEXT: .p2align 2 55; X86-NEXT: .long .Ltmp0 56; X64-NEXT: .p2align 3 57; X64-NEXT: .quad .Ltmp0 58 ret void 59} 60 61;; -fpatchable-function-entry=1 -fcf-protection=branch 62;; For M=0, don't create .Lpatch0 if the initial instruction is not ENDBR, 63;; even if other basic blocks may have ENDBR. 64@buf = internal global [5 x ptr] zeroinitializer 65declare i32 @llvm.eh.sjlj.setjmp(ptr) 66 67define internal void @f1i() "patchable-function-entry"="1" { 68; CHECK-LABEL: f1i: 69; CHECK-NEXT: .Lfunc_begin3: 70; CHECK-NEXT: .cfi_startproc 71; CHECK-NEXT: # %bb.0: 72; CHECK-NEXT: nop 73; CHECK-NOT: .Lpatch0: 74;; Another basic block has ENDBR, but it doesn't affect our decision to not create .Lpatch0 75; CHECK: endbr 76; CHECK: .section __patchable_function_entries,"awo",@progbits,f1i{{$}} 77; X86-NEXT: .p2align 2 78; X86-NEXT: .long .Lfunc_begin3 79; X64-NEXT: .p2align 3 80; X64-NEXT: .quad .Lfunc_begin3 81entry: 82 tail call i32 @llvm.eh.sjlj.setjmp(ptr @buf) 83 ret void 84} 85 86;; Test the interaction with -fsanitize=function. 87; CHECK: .type sanitize_function,@function 88; CHECK-NEXT: .Ltmp{{.*}}: 89; CHECK-NEXT: nop 90; CHECK-NEXT: .long 3238382334 91; CHECK-NEXT: .long 42 92; CHECK-NEXT: sanitize_function: 93; CHECK-NEXT: .Lfunc_begin{{.*}}: 94; CHECK-NEXT: .cfi_startproc 95; CHECK-NEXT: # %bb.0: 96; X86-NEXT: endbr32 97; X64-NEXT: endbr64 98; CHECK-NEXT: nop 99; CHECK-NEXT: ret 100define void @sanitize_function(ptr noundef %x) "patchable-function-prefix"="1" "patchable-function-entry"="1" !func_sanitize !1 { 101 ret void 102} 103 104!llvm.module.flags = !{!0} 105 106!0 = !{i32 8, !"cf-protection-branch", i32 1} 107!1 = !{i32 3238382334, i32 42} 108