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,9 @@ /// A list of command-line options to forward to the LLVM backend. std::vector BackendOptions; + /// A list of function attributes 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 @@ -842,8 +842,8 @@ // Kernel code has more strict alignment requirements. if (KernelOrKext) { if (!Triple.isiOS() || Triple.isOSVersionLT(6)) { - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-long-calls"); + CmdArgs.push_back("-function-attribute"); + CmdArgs.push_back("arm-long-calls"); } CmdArgs.push_back("-backend-option"); @@ -3946,8 +3946,8 @@ if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { if (A->getOption().matches(options::OPT_mlong_calls)) { - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back("-arm-long-calls"); + CmdArgs.push_back("-function-attribute"); + CmdArgs.push_back("arm-long-calls"); } } } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -340,6 +340,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) { @@ -651,6 +659,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-long-calls -emit-llvm -o - %s | FileCheck -check-prefix=LONGCALL %s +// RUN: %clang_cc1 -triple thumbv7-apple-ios5 -emit-llvm -o - %s | FileCheck -check-prefix=NOLONGCALL %s + +// LONGCALL: attributes #0 = { {{.*}} "arm-long-calls +// NOLONGCALL-NOT: attributes #0 = { {{.*}} "arm-long-calls + +int foo1(int a) { return a; } Index: test/Driver/apple-kext-mkernel.c =================================================================== --- test/Driver/apple-kext-mkernel.c +++ test/Driver/apple-kext-mkernel.c @@ -11,7 +11,7 @@ // RUN: -arch armv7 -mkernel -mstrict-align -### -fsyntax-only %s 2> %t // RUN: FileCheck --check-prefix=CHECK-ARM < %t %s -// CHECK-ARM: "-backend-option" "-arm-long-calls" +// CHECK-ARM: "-function-attribute" "arm-long-calls" // CHECK-ARM: "-backend-option" "-arm-strict-align" // CHECK-ARM-NOT: "-backend-option" "-arm-strict-align" // CHECK-ARM: "-fno-builtin" Index: test/Driver/arm-long-calls.c =================================================================== --- test/Driver/arm-long-calls.c +++ test/Driver/arm-long-calls.c @@ -7,9 +7,9 @@ // RUN: %clang -target armv7-eabi -### -mlong-calls -mno-long-calls %s 2>&1 \ // RUN: | FileCheck %s -check-prefix CHECK-NO-LONG-CALLS -// CHECK-DEFAULT-NOT: "-backend-option" "-arm-long-calls" +// CHECK-DEFAULT-NOT: "-function-attribute" "arm-long-calls" -// CHECK-LONG-CALLS: "-backend-option" "-arm-long-calls" +// CHECK-LONG-CALLS: "-function-attribute" "arm-long-calls" -// CHECK-NO-LONG-CALLS-NOT: "-backend-option" "-arm-long-calls" +// CHECK-NO-LONG-CALLS-NOT: "-function-attribute" "arm-long-calls"