diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1823,6 +1823,23 @@ std::tie(Var, Value) = Attr.split('='); FuncAttrs.addAttribute(Var, Value); } + + if (CodeGenOpts.BranchTargetEnforcement) { + FuncAttrs.addAttribute("branch-target-enforcement"); + } + + auto RASignKind = CodeGenOpts.getSignReturnAddress(); + if (RASignKind != CodeGenOptions::SignReturnAddressScope::None) { + FuncAttrs.addAttribute( + "sign-return-address", + RASignKind == CodeGenOptions::SignReturnAddressScope::All ? "all" + : "non-leaf"); + auto RASignKey = CodeGenOpts.getSignReturnAddressKey(); + FuncAttrs.addAttribute( + "sign-return-address-key", + RASignKey == CodeGenOptions::SignReturnAddressKeyValue::AKey ? "a_key" + : "b_key"); + } } void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3390,6 +3390,8 @@ if (F->empty()) { F->setCallingConv(getRuntimeCC()); + AddDefaultFnAttrs(*F); + // In Windows Itanium environments, try to mark runtime functions // dllimport. For Mingw and MSVC, don't. We don't really know if the user // will link their standard library statically or dynamically. Marking diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5134,10 +5134,18 @@ Key == CodeGenOptions::SignReturnAddressKeyValue::AKey ? "a_key" : "b_key"); + } else { + Fn->removeAttribute(llvm::AttributeList::FunctionIndex, + "sign-return-address"); + Fn->removeAttribute(llvm::AttributeList::FunctionIndex, + "sign-return-address-key"); } if (BranchTargetEnforcement) Fn->addFnAttr("branch-target-enforcement"); + else + Fn->removeAttribute(llvm::AttributeList::FunctionIndex, + "branch-target-enforcement"); } llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override { diff --git a/clang/test/CodeGen/ignore-exceptions.cpp b/clang/test/CodeGen/ignore-exceptions.cpp --- a/clang/test/CodeGen/ignore-exceptions.cpp +++ b/clang/test/CodeGen/ignore-exceptions.cpp @@ -12,10 +12,10 @@ } catch(...) { } // CHECK: %a = alloca %struct.A, align 1 -// CHECK: %exception = call i8* @__cxa_allocate_exception(i64 4) #1 +// CHECK: %exception = call i8* @__cxa_allocate_exception(i64 4) #2 // CHECK: %0 = bitcast i8* %exception to i32* // CHECK: store i32 1, i32* %0, align 16 -// CHECK: call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #2 +// CHECK: call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #3 // CHECK: unreachable // CHECK-NOT: invoke diff --git a/clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp b/clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp @@ -0,0 +1,34 @@ +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -mbranch-protection=none -c %s -o - | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=standard %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTI +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=bti %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTI +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key+leaf+bti %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTI + +void a(); +void d(); + +void c() { + try { + d(); + } catch (...) { + a(); + } +} + +// CHECK: ; Function Attrs: noinline noreturn nounwind +// CHECK: define linkonce_odr hidden void @__clang_call_terminate(i8* %0) #[[ATTR:[0-9]*]] comdat { + +// CHECK-NONE-NOT: attributes #[[ATTR]] = {{{.*}} "branch-target-enforcement" {{.*}} } +// CHECK-NONE: attributes #[[ATTR]] = { noinline noreturn nounwind {{.*}} } +// CHECK-BTI: attributes #[[ATTR]] = { noinline noreturn nounwind "branch-target-enforcement" {{.*}} } diff --git a/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp --- a/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp +++ b/clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp @@ -54,11 +54,11 @@ void *a1(long n) { return new A[n]; } // CHECK-LABEL: define {{.*}} @_Z2a2P1A( -// CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #9 +// CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #10 void a2(A *p) { delete p; } // CHECK-LABEL: define {{.*}} @_Z2a3P1A( -// CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #9 +// CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #10 void a3(A *p) { delete[] p; } diff --git a/clang/test/CodeGenCXX/dynamic-cast.cpp b/clang/test/CodeGenCXX/dynamic-cast.cpp --- a/clang/test/CodeGenCXX/dynamic-cast.cpp +++ b/clang/test/CodeGenCXX/dynamic-cast.cpp @@ -20,5 +20,5 @@ // CHECK: declare i8* @__dynamic_cast(i8*, i8*, i8*, i64) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO]] = { nounwind readonly {{.*}}} // CHECK: attributes [[NR]] = { noreturn } diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp --- a/clang/test/CodeGenCXX/exceptions.cpp +++ b/clang/test/CodeGenCXX/exceptions.cpp @@ -594,4 +594,4 @@ // CHECK11: call void @_ZN6test121AdlEPvS1_(i8* [[PTR]], i8* [[PTR]]) } -// CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind } +// CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind {{.*}}} diff --git a/clang/test/CodeGenCXX/runtimecc.cpp b/clang/test/CodeGenCXX/runtimecc.cpp --- a/clang/test/CodeGenCXX/runtimecc.cpp +++ b/clang/test/CodeGenCXX/runtimecc.cpp @@ -22,11 +22,11 @@ A global; // CHECK-LABEL: define internal void @__cxx_global_var_init() // CHECK: call [[A]]* @_ZN5test01AC1Ev([[A]]* @_ZN5test06globalE) -// CHECK-NEXT: call i32 @__cxa_atexit(void (i8*)* bitcast ([[A]]* ([[A]]*)* @_ZN5test01AD1Ev to void (i8*)*), i8* bitcast ([[A]]* @_ZN5test06globalE to i8*), i8* @__dso_handle) [[NOUNWIND:#[0-9]+]] +// CHECK-NEXT: call i32 @__cxa_atexit(void (i8*)* bitcast ([[A]]* ([[A]]*)* @_ZN5test01AD1Ev to void (i8*)*), i8* bitcast ([[A]]* @_ZN5test06globalE to i8*), i8* @__dso_handle) [[NOUNWIND_CALL:#[0-9]+]] // CHECK-NEXT: ret void } -// CHECK: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOUNWIND]] +// CHECK: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOUNWIND_DEC:#[0-9]+]] namespace test1 { void test() { @@ -34,7 +34,7 @@ } // CHECK-LABEL: define void @_ZN5test14testEv() -// CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i32 4) [[NOUNWIND]] +// CHECK: [[T0:%.*]] = call i8* @__cxa_allocate_exception(i32 4) [[NOUNWIND_CALL]] // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32* // CHECK-NEXT: store i32 0, i32* [[T1]] // CHECK-NEXT: call void @__cxa_throw(i8* [[T0]], i8* bitcast (i8** @_ZTIi to i8*), i8* null) [[NORETURN:#[0-9]+]] @@ -49,5 +49,6 @@ // CHECK: call void @__cxx_global_var_init() -// CHECK: attributes [[NOUNWIND]] = { nounwind } +// CHECK: attributes [[NOUNWIND_DEC]] = { nounwind {{.*}} } +// CHECK: attributes [[NOUNWIND_CALL]] = { nounwind } // CHECK: attributes [[NORETURN]] = { noreturn } diff --git a/clang/test/CodeGenCXX/wasm-eh.cpp b/clang/test/CodeGenCXX/wasm-eh.cpp --- a/clang/test/CodeGenCXX/wasm-eh.cpp +++ b/clang/test/CodeGenCXX/wasm-eh.cpp @@ -35,7 +35,7 @@ // CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.get.exception(token %[[CATCHPAD]]) // CHECK-NEXT: store i8* %[[EXN]], i8** %exn.slot // CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]]) -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #3 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]] @@ -53,7 +53,7 @@ // CHECK-NEXT: br label %[[TRY_CONT_BB:.*]] // CHECK: [[CATCH_FALLTHROUGH_BB]] -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) #2 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) #3 // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]] diff --git a/clang/test/CodeGenObjC/arc.m b/clang/test/CodeGenObjC/arc.m --- a/clang/test/CodeGenObjC/arc.m +++ b/clang/test/CodeGenObjC/arc.m @@ -1557,6 +1557,6 @@ getAggDtor(); } -// ARC-ALIEN: attributes [[NLB]] = { nonlazybind } -// ARC-NATIVE: attributes [[NLB]] = { nonlazybind } +// ARC-ALIEN: attributes [[NLB]] = { nonlazybind {{.*}}} +// ARC-NATIVE: attributes [[NLB]] = { nonlazybind {{.*}}} // CHECK: attributes [[NUW]] = { nounwind } diff --git a/clang/test/CodeGenObjC/attr-objc-runtime-visible.m b/clang/test/CodeGenObjC/attr-objc-runtime-visible.m --- a/clang/test/CodeGenObjC/attr-objc-runtime-visible.m +++ b/clang/test/CodeGenObjC/attr-objc-runtime-visible.m @@ -14,6 +14,6 @@ // CHECK: [[CLASSNAME:@.*]] = private unnamed_addr constant [22 x i8] c"MyRuntimeVisibleClass // CHECK: define i8* @getClass() #0 { Class getClass(void) { - // CHECK: call i8* @objc_lookUpClass(i8* getelementptr inbounds ([22 x i8], [22 x i8]* [[CLASSNAME]], i32 0, i32 0)) #2 + // CHECK: call i8* @objc_lookUpClass(i8* getelementptr inbounds ([22 x i8], [22 x i8]* [[CLASSNAME]], i32 0, i32 0)) #3 return [A class]; } diff --git a/clang/test/CodeGenObjC/class-stubs.m b/clang/test/CodeGenObjC/class-stubs.m --- a/clang/test/CodeGenObjC/class-stubs.m +++ b/clang/test/CodeGenObjC/class-stubs.m @@ -81,4 +81,4 @@ @end // -- calls to objc_loadClassRef() are readnone -// CHECK: attributes [[ATTRLIST]] = { nounwind nonlazybind readnone } +// CHECK: attributes [[ATTRLIST]] = { nounwind nonlazybind readnone {{.*}} } diff --git a/clang/test/CodeGenObjC/nonlazy-msgSend.m b/clang/test/CodeGenObjC/nonlazy-msgSend.m --- a/clang/test/CodeGenObjC/nonlazy-msgSend.m +++ b/clang/test/CodeGenObjC/nonlazy-msgSend.m @@ -5,4 +5,4 @@ [x foo]; } -// CHECK: attributes [[NLB]] = { nonlazybind } +// CHECK: attributes [[NLB]] = { nonlazybind {{.*}}} diff --git a/clang/test/CodeGenObjC/objc-literal-debugger-test.m b/clang/test/CodeGenObjC/objc-literal-debugger-test.m --- a/clang/test/CodeGenObjC/objc-literal-debugger-test.m +++ b/clang/test/CodeGenObjC/objc-literal-debugger-test.m @@ -52,4 +52,4 @@ // CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]] -// CHECK: attributes [[NLB]] = { nonlazybind } +// CHECK: attributes [[NLB]] = { nonlazybind {{.*}} } diff --git a/clang/test/OpenMP/barrier_codegen.cpp b/clang/test/OpenMP/barrier_codegen.cpp --- a/clang/test/OpenMP/barrier_codegen.cpp +++ b/clang/test/OpenMP/barrier_codegen.cpp @@ -42,8 +42,7 @@ return tmain(argc) + tmain(argv[0][0]) + a; } -// CLANGCG: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) -// CLANGCG-NOT: # +// CLANGCG: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) # // IRBUILDER: ; Function Attrs: nounwind // IRBUILDER-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) # // IRBUILDER_OPT: ; Function Attrs: nofree nosync nounwind readonly diff --git a/clang/test/OpenMP/nvptx_parallel_codegen.cpp b/clang/test/OpenMP/nvptx_parallel_codegen.cpp --- a/clang/test/OpenMP/nvptx_parallel_codegen.cpp +++ b/clang/test/OpenMP/nvptx_parallel_codegen.cpp @@ -321,7 +321,7 @@ // CHECK: call void @__kmpc_barrier(%struct.ident_t* @{{.+}}, i32 %{{.+}}) #[[#CONVERGENT:]] // CHECK: ret void -// CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32) #[[#CONVERGENT]] +// CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32) #[[#CONVERGENT_DEC:]] // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l55}}_worker() // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l55}}( @@ -369,9 +369,11 @@ // CHECK: br label -// CHECK: declare i32 @__kmpc_warp_active_thread_mask() #[[#CONVERGENT:]] -// CHECK: declare void @__kmpc_syncwarp(i32) #[[#CONVERGENT:]] +// CHECK: declare i32 @__kmpc_warp_active_thread_mask() # +// CHECK: declare void @__kmpc_syncwarp(i32) # + +// CHECK: attributes #[[#CONVERGENT_DEC]] = { convergent {{.*}} } +// CHECK: attributes #[[#CONVERGENT]] = { convergent } -// CHECK: attributes #[[#CONVERGENT]] = {{.*}} convergent {{.*}} #endif diff --git a/clang/test/OpenMP/openmp_win_codegen.cpp b/clang/test/OpenMP/openmp_win_codegen.cpp --- a/clang/test/OpenMP/openmp_win_codegen.cpp +++ b/clang/test/OpenMP/openmp_win_codegen.cpp @@ -61,9 +61,9 @@ // CHECK-NEXT: call void @__kmpc_end_critical(%struct.ident_t* {{.*}}@0, i32 [[GID]], // CHECK-NEXT: cleanupret from {{.*}} unwind label %[[CATCHTERM:[^ ]+]] // CHECK: cleanuppad within none [] -// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ] +// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #6 [ "funclet"(token %{{.*}}) ] // CHECK-NEXT: unreachable // CHECK: [[CATCHTERM]] // CHECK-NEXT: cleanuppad within [[CATCHPAD]] [] -// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ] +// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #6 [ "funclet"(token %{{.*}}) ] // CHECK-NEXT: unreachable diff --git a/clang/test/PCH/objc_container.m b/clang/test/PCH/objc_container.m --- a/clang/test/PCH/objc_container.m +++ b/clang/test/PCH/objc_container.m @@ -22,4 +22,4 @@ // CHECK-IR: ret void // CHECK-IR: attributes #0 = { noinline nounwind {{.*}} } -// CHECK-IR: attributes #1 = { nonlazybind } +// CHECK-IR: attributes #1 = { nonlazybind {{.*}} }