Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -223,6 +223,8 @@ HelpText<"Do not put zero initialized data in the BSS">; def backend_option : Separate<["-"], "backend-option">, HelpText<"Additional arguments to forward to LLVM backend (during code gen)">; +def function_attribute : Separate<["-"], "function-attribute">, + HelpText<"Function attributes to attach to functions (during code gen)">; def mregparm : Separate<["-"], "mregparm">, HelpText<"Limit the number of registers available for integer arguments">; def mrelocation_model : Separate<["-"], "mrelocation-model">, Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -151,6 +151,10 @@ /// A list of command-line options to forward to the LLVM backend. std::vector BackendOptions; + /// A list of function attributes in the form of key-value pairs to save to + /// the IR. + std::vector> FunctionAttributes; + /// A list of dependent libraries. std::vector DependentLibraries; Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1455,6 +1455,9 @@ FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); } else { // Attributes that should go on the function, but not the call site. + for (auto &KV : CodeGenOpts.FunctionAttributes) + FuncAttrs.addAttribute(KV.first, KV.second); + if (!CodeGenOpts.DisableFPElim) { FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); } else if (CodeGenOpts.OmitLeafFramePointer) { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -4092,17 +4092,17 @@ if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it, options::OPT_mno_restrict_it)) { if (A->getOption().matches(options::OPT_mrestrict_it)) { - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-restrict-it"); + CmdArgs.push_back("-function-attribute"); + CmdArgs.push_back("arm-restrict-it=true"); } else { - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-no-restrict-it"); + CmdArgs.push_back("-function-attribute"); + CmdArgs.push_back("arm-restrict-it=false"); } } else if (TT.isOSWindows() && (TT.getArch() == llvm::Triple::arm || TT.getArch() == llvm::Triple::thumb)) { // Windows on ARM expects restricted IT blocks - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-restrict-it"); + CmdArgs.push_back("-function-attribute"); + CmdArgs.push_back("arm-restrict-it=true"); } if (TT.getArch() == llvm::Triple::arm || Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -333,6 +333,14 @@ } } +static void getFunctionAttributes(CodeGenOptions &Opts, + const std::vector &FnAttrStrs) { + for (const auto &S : FnAttrStrs) { + std::pair KV = StringRef(S).split('='); + Opts.FunctionAttributes.push_back(std::make_pair(KV.first, KV.second)); + } +} + static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, const TargetOptions &TargetOpts) { @@ -644,6 +652,7 @@ Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags, Opts.SanitizeRecover); + getFunctionAttributes(Opts, Args.getAllArgValues(OPT_function_attribute)); Opts.CudaGpuBinaryFileNames = Args.getAllArgValues(OPT_fcuda_include_gpubinary); Index: test/CodeGen/fn-attr.c =================================================================== --- /dev/null +++ test/CodeGen/fn-attr.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -function-attribute arm-restrict-it=false -emit-llvm -o - %s | FileCheck -check-prefix=NO-RESTRICT-IT %s +// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -function-attribute arm-restrict-it=true -emit-llvm -o - %s | FileCheck -check-prefix=RESTRICT-IT %s + +// NO-RESTRICT-IT: attributes #0 = { {{.*}} "arm-restrict-it"="false" +// RESTRICT-IT: attributes #0 = { {{.*}} "arm-restrict-it"="true" + +int foo1(int a) { return a; } Index: test/Driver/arm-restrict-it.c =================================================================== --- test/Driver/arm-restrict-it.c +++ test/Driver/arm-restrict-it.c @@ -4,7 +4,7 @@ // RUN: %clang -target armv8a-none-gnueabi -mrestrict-it -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-RESTRICTED < %t %s -// CHECK-RESTRICTED: "-backend-option" "-arm-restrict-it" +// CHECK-RESTRICTED: "-function-attribute" "arm-restrict-it=true" // RUN: %clang -target arm-none-gnueabi -mno-restrict-it -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-NO-RESTRICTED < %t %s @@ -12,4 +12,4 @@ // RUN: %clang -target armv8a-none-gnueabi -mno-restrict-it -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-NO-RESTRICTED < %t %s -// CHECK-NO-RESTRICTED: "-backend-option" "-arm-no-restrict-it" +// CHECK-NO-RESTRICTED: "-function-attribute" "arm-restrict-it=false" Index: test/Driver/woa-restrict-it.c =================================================================== --- test/Driver/woa-restrict-it.c +++ test/Driver/woa-restrict-it.c @@ -1,4 +1,4 @@ // RUN: %clang -target armv7-windows -### %s 2>&1 | FileCheck %s -// CHECK: "-backend-option" "-arm-restrict-it" +// CHECK: "-function-attribute" "arm-restrict-it=true"