Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1032,6 +1032,11 @@ HelpText<"Like -finstrument-functions, but insert the calls after inlining">; def finstrument_function_entry_bare : Flag<["-"], "finstrument-function-entry-bare">, Group, Flags<[CC1Option]>, HelpText<"Instrument function entry only, after inlining, without arguments to the instrumentation call">; +def fcf_arch_protection_EQ : Joined<["-"], "fcf-arch-protection=">, Flags<[CoreOption, CC1Option]>, Group, + HelpText<"Instrument control-flow architecture protection. Options: return, branch, full, none.">, Values<"return,branch,full,none">; +def fcf_arch_protection : Flag<["-"], "fcf-arch-protection">, Group, Flags<[CoreOption, CC1Option]>, + Alias, AliasArgs<["full"]>, + HelpText<"Enable cf-arch-protection in 'full' mode">; def fxray_instrument : Flag<["-"], "fxray-instrument">, Group, Flags<[CC1Option]>, Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -80,7 +80,10 @@ ///< -finstrument-functions-after-inlining is enabled. CODEGENOPT(InstrumentFunctionEntryBare , 1, 0) ///< Set when ///< -finstrument-function-entry-bare is enabled. - +CODEGENOPT(CFProtectionReturn , 1, 0) ///< if -fcf-arch-protection is + ///< set to full or return. +CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-arch-protection is + ///< set to full or branch. CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is ///< enabled. Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1734,6 +1734,10 @@ llvm::utostr(CodeGenOpts.SSPBufferSize)); FuncAttrs.addAttribute("no-signed-zeros-fp-math", llvm::toStringRef(CodeGenOpts.NoSignedZeros)); + FuncAttrs.addAttribute("cf-protection-return", + llvm::toStringRef(CodeGenOpts.CFProtectionReturn)); + FuncAttrs.addAttribute("cf-protection-branch", + llvm::toStringRef(CodeGenOpts.CFProtectionBranch)); FuncAttrs.addAttribute( "correctly-rounded-divide-sqrt-fp-math", llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt)); Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -873,7 +873,8 @@ } // Apply xray attributes to the function (as a string, for now) - if (D && ShouldXRayInstrumentFunction()) { + bool InstrumentXray = ShouldXRayInstrumentFunction(); + if (D && InstrumentXray) { if (const auto *XRayAttr = D->getAttr()) { if (XRayAttr->alwaysXRayInstrument()) Fn->addFnAttr("function-instrument", "xray-always"); Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3977,6 +3977,11 @@ // Forward -cl options to -cc1 RenderOpenCLOptions(Args, CmdArgs); + if (Arg *A = Args.getLastArg(options::OPT_fcf_arch_protection_EQ)) { + CmdArgs.push_back( + Args.MakeArgString(Twine("-fcf-arch-protection=") + A->getValue())); + } + // Forward -f options with positive and negative forms; we translate // these by hand. if (Arg *A = getLastProfileSampleUseArg(Args)) { Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -791,6 +791,21 @@ Opts.CallFEntry = Args.hasArg(OPT_mfentry); Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info); + if (const Arg *A = Args.getLastArg(OPT_fcf_arch_protection_EQ)) { + StringRef Name = A->getValue(); + if (Name == "full") { + Opts.CFProtectionReturn = 1; + Opts.CFProtectionBranch = 1; + } else if (Name == "return") + Opts.CFProtectionReturn = 1; + else if (Name == "branch") + Opts.CFProtectionBranch = 1; + else if (Name != "none") { + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + Success = false; + } + } + if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections, OPT_compress_debug_sections_EQ)) { if (A->getOption().getID() == OPT_compress_debug_sections) { Index: test/CodeGen/cf-arch-protection.c =================================================================== --- /dev/null +++ test/CodeGen/cf-arch-protection.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -S -emit-llvm -fcf-arch-protection=full -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=FULL +// RUN: %clang_cc1 -S -emit-llvm -fcf-arch-protection -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=FULL +// RUN: %clang_cc1 -S -emit-llvm -fcf-arch-protection=return -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=RETURN +// RUN: %clang_cc1 -S -emit-llvm -fcf-arch-protection=branch -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=BRANCH + +// CHECK: define void @foo() [[NUW:#[0-9]+]] +void foo(void) { +} + +// FULL: attributes [[NUW]] = { {{.*}} "cf-protection-branch"="true" "cf-protection-return"="true" {{.*}} } +// BRANCH: attributes [[NUW]] = { {{.*}} "cf-protection-branch"="true" {{.*}} } +// RETURN: attributes [[NUW]] = { {{.*}} "cf-protection-return"="true" {{.*}} } Index: test/CodeGen/complex-builtins.c =================================================================== --- test/CodeGen/complex-builtins.c +++ test/CodeGen/complex-builtins.c @@ -199,8 +199,8 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } Index: test/CodeGen/complex-libcalls.c =================================================================== --- test/CodeGen/complex-libcalls.c +++ test/CodeGen/complex-libcalls.c @@ -201,8 +201,8 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } Index: test/CodeGen/math-builtins.c =================================================================== --- test/CodeGen/math-builtins.c +++ test/CodeGen/math-builtins.c @@ -565,9 +565,9 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } Index: test/CodeGen/math-libcalls.c =================================================================== --- test/CodeGen/math-libcalls.c +++ test/CodeGen/math-libcalls.c @@ -534,11 +534,11 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } // NO__ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } Index: test/Driver/clang_f_opts.c =================================================================== --- test/Driver/clang_f_opts.c +++ test/Driver/clang_f_opts.c @@ -503,3 +503,19 @@ // CHECK-WINDOWS-ISO10646: "-fwchar-type=int" // CHECK-WINDOWS-ISO10646: "-fsigned-wchar" +// RUN: %clang -### -S -fcf-arch-protection %s 2>&1 | FileCheck -check-prefix=CHECK-CF-ARCH-PROTECTION %s +// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-ARCH-PROTECTION %s +// CHECK-CF-ARCH-PROTECTION: -fcf-arch-protection +// CHECK-NO-CF-ARCH-PROTECTION-NOT: -fcf-arch-protection +// RUN: %clang -### -S -fcf-arch-protection=full %s 2>&1 | FileCheck -check-prefix=CHECK-CF-ARCH-PROTECTION-FULL %s +// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-ARCH-PROTECTION-FULL %s +// CHECK-CF-ARCH-PROTECTION-FULL: -fcf-arch-protection=full +// CHECK-NO-CF-ARCH-PROTECTION-FULL-NOT: -fcf-arch-protection=full +// RUN: %clang -### -S -fcf-arch-protection=return %s 2>&1 | FileCheck -check-prefix=CHECK-CF-ARCH-PROTECTION-RETURN %s +// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-ARCH-PROTECTION-RETURN %s +// CHECK-CF-ARCH-PROTECTION-RETURN: -fcf-arch-protection=return +// CHECK-NO-CF-ARCH-PROTECTION-RETURN-NOT: -fcf-arch-protection=return +// RUN: %clang -### -S -fcf-arch-protection=branch %s 2>&1 | FileCheck -check-prefix=CHECK-CF-ARCH-PROTECTION-BRANCH %s +// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CF-ARCH-PROTECTION-BRANCH %s +// CHECK-CF-ARCH-PROTECTION-BRANCH: -fcf-arch-protection=branch +// CHECK-NO-CF-ARCH-PROTECTION-BRANCH-NOT: -fcf-arch-protection=branch