diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -2005,6 +2005,25 @@ break; } + case X86::ENDBR32: + case X86::ENDBR64: { + // CurrentPatchableFunctionEntrySym can be CurrentFnBegin only for + // -fpatchable-function-entry=N,0. The entry MBB is guaranteed to be + // non-empty. If MI is the initial ENDBR, place the + // __patchable_function_entries label after ENDBR. + if (CurrentPatchableFunctionEntrySym && + CurrentPatchableFunctionEntrySym == CurrentFnBegin && + MI == &MF->front().front()) { + MCInst Inst; + MCInstLowering.Lower(MI, Inst); + EmitAndCountInstruction(Inst); + CurrentPatchableFunctionEntrySym = createTempSymbol("patch"); + OutStreamer->EmitLabel(CurrentPatchableFunctionEntrySym); + return; + } + break; + } + case X86::TAILJMPr: case X86::TAILJMPm: case X86::TAILJMPd: diff --git a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll --- a/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll +++ b/llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll @@ -15,7 +15,8 @@ define void @f1() "patchable-function-entry"="1" "branch-target-enforcement" { ; CHECK-LABEL: f1: ; CHECK-NEXT: .Lfunc_begin1: -; CHECK: // %bb.0: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: hint #34 ; CHECK-NEXT: .Lpatch0: ; CHECK-NEXT: nop @@ -33,7 +34,8 @@ ; CHECK-NEXT: nop ; CHECK-NEXT: f2_1: ; CHECK-NEXT: .Lfunc_begin2: -; CHECK: // %bb.0: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: // %bb.0: ; CHECK-NEXT: hint #34 ; CHECK-NEXT: nop ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll b/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll --- a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll +++ b/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll @@ -1,26 +1,37 @@ -; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK %s +; RUN: llc -mtriple=i686 %s -o - | FileCheck --check-prefixes=CHECK,32 %s +; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,64 %s ;; -fpatchable-function-entry=0 -fcf-protection=branch -define void @f0() "patchable-function-entry"="0" "branch-target-enforcement" { +define void @f0() "patchable-function-entry"="0" { ; CHECK-LABEL: f0: ; CHECK-NEXT: .Lfunc_begin0: -; CHECK: # %bb.0: -; CHECK-NEXT: endbr64 -; CHECK-NEXT: retq +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: # %bb.0: +; 32-NEXT: endbr32 +; 64-NEXT: endbr64 +; CHECK-NEXT: ret ; CHECK-NOT: .section __patchable_function_entries ret void } ;; -fpatchable-function-entry=1 -fcf-protection=branch +;; For M=0, place the label .Lpatch0 after the initial ENDBR. +;; .cfi_startproc should be placed at the function entry. define void @f1() "patchable-function-entry"="1" { ; CHECK-LABEL: f1: ; CHECK-NEXT: .Lfunc_begin1: -; CHECK: endbr64 +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: # %bb.0: +; 32-NEXT: endbr32 +; 64-NEXT: endbr64 +; CHECK-NEXT: .Lpatch0: ; CHECK-NEXT: nop -; CHECK-NEXT: retq +; CHECK-NEXT: ret ; CHECK: .section __patchable_function_entries,"awo",@progbits,f1,unique,0 -; CHECK-NEXT: .p2align 3 -; CHECK-NEXT: .quad .Lfunc_begin1 +; 32-NEXT: .p2align 2 +; 32-NEXT: .long .Lpatch0 +; 64-NEXT: .p2align 3 +; 64-NEXT: .quad .Lpatch0 ret void } @@ -31,15 +42,44 @@ ; CHECK-NEXT: nop ; CHECK-NEXT: f2_1: ; CHECK-NEXT: .Lfunc_begin2: -; CHECK: # %bb.0: -; CHECK-NEXT: endbr64 +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: # %bb.0: +; 32-NEXT: endbr32 +; 64-NEXT: endbr64 ; CHECK-NEXT: nop -; CHECK-NEXT: retq +; CHECK-NEXT: ret ; CHECK: .Lfunc_end2: ; CHECK-NEXT: .size f2_1, .Lfunc_end2-f2_1 ; CHECK: .section __patchable_function_entries,"awo",@progbits,f1,unique,0 -; CHECK-NEXT: .p2align 3 -; CHECK-NEXT: .quad .Ltmp0 +; 32-NEXT: .p2align 2 +; 32-NEXT: .long .Ltmp0 +; 64-NEXT: .p2align 3 +; 64-NEXT: .quad .Ltmp0 + ret void +} + +;; -fpatchable-function-entry=1 -fcf-protection=branch +;; For M=0, don't create .Lpatch0 if the initial instruction is not ENDBR, +;; even if other basic blocks may have ENDBR. +@buf = internal global [5 x i8*] zeroinitializer +declare i32 @llvm.eh.sjlj.setjmp(i8*) + +define internal void @f1i() "patchable-function-entry"="1" { +; CHECK-LABEL: f1i: +; CHECK-NEXT: .Lfunc_begin3: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: nop +; CHECK-NOT: .Lpatch0: +;; Another basic block has ENDBR, but it doesn't affect our decision to not create .Lpatch0 +; CHECK: endbr +; CHECK: .section __patchable_function_entries,"awo",@progbits,f1,unique,0 +; 32-NEXT: .p2align 2 +; 32-NEXT: .long .Lfunc_begin3 +; 64-NEXT: .p2align 3 +; 64-NEXT: .quad .Lfunc_begin3 +entry: + tail call i32 @llvm.eh.sjlj.setjmp(i8* bitcast ([5 x i8*]* @buf to i8*)) ret void }