Index: docs/CommandGuide/clang.rst =================================================================== --- docs/CommandGuide/clang.rst +++ docs/CommandGuide/clang.rst @@ -313,6 +313,13 @@ model can be overridden with the tls_model attribute. The compiler will try to choose a more efficient model if possible. +.. option:: -fruntime-init + + Emit code for functions that permits them to be used both during and after + initialization of the runtime environment. This is only meaningful when + combined with the SafeStack pass. See the documentation associated with that + pass for more details. + .. option:: -flto, -emit-llvm Generate output files in LLVM formats, suitable for link time optimization. Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -132,6 +132,7 @@ LANGOPT(Freestanding, 1, 0, "freestanding implementation") LANGOPT(NoBuiltin , 1, 0, "disable builtin functions") LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions") +LANGOPT(RuntimeInit , 1, 0, "used during runtime initialization") LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly") LANGOPT(Coroutines , 1, 0, "C++ coroutines") Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1031,6 +1031,7 @@ def freg_struct_return : Flag<["-"], "freg-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Override the default ABI to return small structs in registers">; def frtti : Flag<["-"], "frtti">, Group; +def fruntime_init : Flag<["-"], "fruntime-init">, Group, Flags<[CC1Option]>; def : Flag<["-"], "fsched-interblock">, Group; def fshort_enums : Flag<["-"], "fshort-enums">, Group, Flags<[CC1Option]>, HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; Index: lib/CodeGen/CGDeclCXX.cpp =================================================================== --- lib/CodeGen/CGDeclCXX.cpp +++ lib/CodeGen/CGDeclCXX.cpp @@ -279,6 +279,9 @@ Fn->addFnAttr(llvm::Attribute::SafeStack); } + if (getLangOpts().RuntimeInit) + Fn->addFnAttr(llvm::Attribute::RuntimeInit); + return Fn; } Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -698,6 +698,9 @@ if (SanOpts.has(SanitizerKind::SafeStack)) Fn->addFnAttr(llvm::Attribute::SafeStack); + if (getLangOpts().RuntimeInit) + Fn->addFnAttr(llvm::Attribute::RuntimeInit); + // Pass inline keyword to optimizer if it appears explicitly on any // declaration. Also, in the case of -fno-inline attach NoInline // attribute to all function that are not marked AlwaysInline. Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -4777,6 +4777,9 @@ KernelOrKext) CmdArgs.push_back("-ffreestanding"); + if (Args.hasArg(options::OPT_fruntime_init)) + CmdArgs.push_back("-fruntime-init"); + // Forward -f (flag) options which we can pass directly. Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1730,6 +1730,7 @@ if (!Opts.NoBuiltin) getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); + Opts.RuntimeInit = Args.hasArg(OPT_fruntime_init); Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation); Opts.ConceptsTS = Args.hasArg(OPT_fconcepts_ts); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); Index: test/CodeGen/runtime-init-attr.c =================================================================== --- /dev/null +++ test/CodeGen/runtime-init-attr.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s -fruntime-init | FileCheck -check-prefix=DEF -check-prefix=CHECK %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s -fruntime-init -fsanitize=safe-stack | FileCheck -check-prefix=DEF -check-prefix=SAFESTACK %s + +// DEF: define {{.*}}void @test1() #[[A:.*]] { +void test1() { +} + +// CHECK: attributes #[[A]] = {{.*}} runtime_init +// SAFESTACK: attributes #[[A]] = {{.*}} runtime_init safestack