diff options
-rw-r--r-- | include/clang/CodeGen/CodeGenOptions.h | 8 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 6 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 89 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 14 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 15 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 5 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 9 | ||||
-rw-r--r-- | test/CodeGenCXX/deferred-global-init.cpp | 2 | ||||
-rw-r--r-- | test/CodeGenCXX/global-dtor-no-atexit.cpp | 14 | ||||
-rw-r--r-- | test/CodeGenCXX/global-init.cpp | 2 |
12 files changed, 140 insertions, 28 deletions
diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index e0e0f779bf..85c6c3e3ab 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -30,6 +30,9 @@ public: }; unsigned AsmVerbose : 1; /// -dA, -fverbose-asm. + unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors. + unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker + /// aliases to base ctors when possible. unsigned DebugInfo : 1; /// Should generate deubg info (-g). unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled. unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in @@ -53,8 +56,6 @@ public: unsigned UnwindTables : 1; /// Emit unwind tables. unsigned VerifyModule : 1; /// Control whether the module should be run /// through the LLVM Verifier. - unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker - /// aliases to base ctors when possible. /// The code model to use (-mcmodel). std::string CodeModel; @@ -86,6 +87,8 @@ public: public: CodeGenOptions() { AsmVerbose = 0; + CXAAtExit = 1; + CXXCtorDtorAliases = 0; DebugInfo = 0; DisableFPElim = 0; DisableLLVMOpts = 0; @@ -103,7 +106,6 @@ public: UnrollLoops = 0; UnwindTables = 0; VerifyModule = 1; - CXXCtorDtorAliases = 0; Inlining = NoInlining; RelocationModel = "pic"; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 3696a4b1fb..feebbc7886 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -355,10 +355,12 @@ def fno_elide_constructors : Flag<"-fno-elide-constructors">, HelpText<"Disable C++ copy constructor elision">; def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">; -def fno_signed_char : Flag<"-fno-signed-char">, - HelpText<"Char is unsigned">; def fno_operator_names : Flag<"-fno-operator-names">, HelpText<"Do not treat C++ operator name keywords as synonyms for operators">; +def fno_signed_char : Flag<"-fno-signed-char">, + HelpText<"Char is unsigned">; +def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, + HelpText<"Don't use __cxa_atexit for calling destructors">; def fconstant_string_class : Separate<"-fconstant-string-class">, MetaVarName<"<class name>">, HelpText<"Specify the class to use for constant Objective-C string objects.">; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 00fb7d0975..71258f9814 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -263,6 +263,7 @@ def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>; def fencoding_EQ : Joined<"-fencoding=">, Group<f_Group>; def fexceptions : Flag<"-fexceptions">, Group<f_Group>; def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; +def fhosted : Flag<"-fhosted">, Group<f_Group>; def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>; def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>; def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; @@ -315,6 +316,7 @@ def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group> def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<clang_ignored_f_Group>; def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; +def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>; def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; @@ -363,6 +365,7 @@ def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>; def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>; def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>; +def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>; def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>; def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>; def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>; diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 22a103ce35..40c18ca3c2 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenFunction.h" +#include "clang/CodeGen/CodeGenOptions.h" using namespace clang; using namespace CodeGen; @@ -89,8 +90,15 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, "global variable that binds reference to a non-lvalue"); } -void CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, - llvm::Constant *DeclPtr) { +void +CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, + llvm::Constant *DeclPtr) { + // Generate a global destructor entry if not using __cxa_atexit. + if (!CGM.getCodeGenOpts().CXAAtExit) { + CGM.AddCXXDtorEntry(DtorFn, DeclPtr); + return; + } + const llvm::Type *Int8PtrTy = llvm::Type::getInt8Ty(VMContext)->getPointerTo(); @@ -123,7 +131,8 @@ void CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); } -void CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { +void +CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false); @@ -133,18 +142,13 @@ void CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) { llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, "__cxx_global_var_init", &TheModule); - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), - SourceLocation()); - - llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); - EmitCXXGlobalVarDeclInit(*D, DeclPtr); - - FinishFunction(); + CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D); CXXGlobalInits.push_back(Fn); } -void CodeGenModule::EmitCXXGlobalInitFunc() { +void +CodeGenModule::EmitCXXGlobalInitFunc() { if (CXXGlobalInits.empty()) return; @@ -153,20 +157,73 @@ void CodeGenModule::EmitCXXGlobalInitFunc() { false); // Create our global initialization function. - // FIXME: Should this be tweakable by targets? llvm::Function *Fn = llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, - "__cxx_global_initialization", &TheModule); + "_GLOBAL__I_a", &TheModule); + + CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, + &CXXGlobalInits[0], + CXXGlobalInits.size()); + AddGlobalCtor(Fn); +} + +void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn, + llvm::Constant *Object) { + CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object)); +} + +void CodeGenModule::EmitCXXGlobalDtorFunc() { + if (CXXGlobalDtors.empty()) + return; + + const llvm::FunctionType *FTy + = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + false); + + // Create our global destructor function. + llvm::Function *Fn = + llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, + "_GLOBAL__D_a", &TheModule); + + CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors); + AddGlobalDtor(Fn); +} +void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, + const VarDecl *D) { StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), SourceLocation()); - for (unsigned i = 0, e = CXXGlobalInits.size(); i != e; ++i) - Builder.CreateCall(CXXGlobalInits[i]); + llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); + EmitCXXGlobalVarDeclInit(*D, DeclPtr); FinishFunction(); +} - AddGlobalCtor(Fn); +void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, + llvm::Constant **Decls, + unsigned NumDecls) { + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), + SourceLocation()); + + for (unsigned i = 0; i != NumDecls; ++i) + Builder.CreateCall(Decls[i]); + + FinishFunction(); +} + +void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, + const std::vector<std::pair<llvm::Constant*, llvm::Constant*> > + &DtorsAndObjects) { + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), + SourceLocation()); + + // Emit the dtors, in reverse order from construction. + for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) + Builder.CreateCall(DtorsAndObjects[e - i - 1].first, + DtorsAndObjects[e - i - 1].second); + + FinishFunction(); } static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d9b1457811..bd12c4a87c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1225,6 +1225,20 @@ public: void EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn, llvm::Constant *DeclPtr); + /// GenerateCXXGlobalInitFunc - Generates code for initializing global + /// variables. + void GenerateCXXGlobalInitFunc(llvm::Function *Fn, + llvm::Constant **Decls, + unsigned NumDecls); + + /// GenerateCXXGlobalDtorFunc - Generates code for destroying global + /// variables. + void GenerateCXXGlobalDtorFunc(llvm::Function *Fn, + const std::vector<std::pair<llvm::Constant*, + llvm::Constant*> > &DtorsAndObjects); + + void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D); + void EmitCXXConstructExpr(llvm::Value *Dest, const CXXConstructExpr *E); RValue EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 3b04cc125e..b4b5bbdb99 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -81,6 +81,7 @@ void CodeGenModule::createObjCRuntime() { void CodeGenModule::Release() { EmitDeferred(); EmitCXXGlobalInitFunc(); + EmitCXXGlobalDtorFunc(); if (Runtime) if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction()) AddGlobalCtor(ObjCInitFunction); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index b93f3c634d..febb856036 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -138,10 +138,14 @@ class CodeGenModule : public BlockModule { llvm::StringMap<llvm::Constant*> CFConstantStringMap; llvm::StringMap<llvm::Constant*> ConstantStringMap; - /// CXXGlobalInits - Variables with global initializers that need to run + /// CXXGlobalInits - Global variables with initializers that need to run /// before main. std::vector<llvm::Constant*> CXXGlobalInits; + /// CXXGlobalDtors - Global destructor functions and arguments that need to + /// run on termination. + std::vector<std::pair<llvm::Constant*,llvm::Constant*> > CXXGlobalDtors; + /// CFConstantStringClassRef - Cached reference to the class for constant /// strings. This value has type int * but is actually an Obj-C class pointer. llvm::Constant *CFConstantStringClassRef; @@ -321,6 +325,10 @@ public: void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); } + /// AddCXXDtorEntry - Add a destructor and object to add to the C++ global + /// destructor function. + void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object); + /// CreateRuntimeFunction - Create a new runtime function with the specified /// type and name. llvm::Constant *CreateRuntimeFunction(const llvm::FunctionType *Ty, @@ -496,9 +504,12 @@ private: /// a C++ destructor Decl. void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type); - /// EmitCXXGlobalInitFunc - Emit a function that initializes C++ globals. + /// EmitCXXGlobalInitFunc - Emit the function that initializes C++ globals. void EmitCXXGlobalInitFunc(); + /// EmitCXXGlobalDtorFunc - Emit the function that destroys C++ globals. + void EmitCXXGlobalDtorFunc(); + void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D); // FIXME: Hardcoding priority here is gross. diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 58a4cdb89b..87449760a7 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1118,6 +1118,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_threadsafe_statics)) CmdArgs.push_back("-fno-threadsafe-statics"); + // -fuse-cxa-atexit is default. + if (!Args.hasFlag(options::OPT_fuse_cxa_atexit, + options::OPT_fno_use_cxa_atexit)) + CmdArgs.push_back("-fno-use-cxa-atexit"); + // -fms-extensions=0 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, getToolChain().getTriple().getOS() == llvm::Triple::Win32)) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 2dfc592ec8..6e18f346d5 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -154,6 +154,10 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-mcode-model"); Res.push_back(Opts.CodeModel); } + if (!Opts.CXAAtExit) + Res.push_back("-fno-use-cxa-atexit"); + if (Opts.CXXCtorDtorAliases) + Res.push_back("-mconstructor-aliases"); if (!Opts.DebugPass.empty()) { Res.push_back("-mdebug-pass"); Res.push_back(Opts.DebugPass); @@ -180,8 +184,6 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, Res.push_back("-mrelocation-model"); Res.push_back(Opts.RelocationModel); } - if (Opts.CXXCtorDtorAliases) - Res.push_back("-mconstructor-aliases"); if (!Opts.VerifyModule) Res.push_back("-disable-llvm-verifier"); } @@ -784,6 +786,8 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize); Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); + Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit); + Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases); Opts.CodeModel = getLastArgValue(Args, OPT_mcode_model); Opts.DebugPass = getLastArgValue(Args, OPT_mdebug_pass); Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim); @@ -794,7 +798,6 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); Opts.RelocationModel = getLastArgValue(Args, OPT_mrelocation_model, "pic"); - Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases); Opts.MainFileName = getLastArgValue(Args, OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); diff --git a/test/CodeGenCXX/deferred-global-init.cpp b/test/CodeGenCXX/deferred-global-init.cpp index 802042dd8b..24c8c675b0 100644 --- a/test/CodeGenCXX/deferred-global-init.cpp +++ b/test/CodeGenCXX/deferred-global-init.cpp @@ -11,6 +11,6 @@ void* bar() { return a; } // CHECK: load i8** @foo // CHECK: ret void -// CHECK: define internal void @__cxx_global_initialization +// CHECK: define internal void @_GLOBAL__I_a // CHECK: call void @__cxx_global_var_init() // CHECK: ret void diff --git a/test/CodeGenCXX/global-dtor-no-atexit.cpp b/test/CodeGenCXX/global-dtor-no-atexit.cpp new file mode 100644 index 0000000000..81e2199898 --- /dev/null +++ b/test/CodeGenCXX/global-dtor-no-atexit.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple x86_64 %s -fno-use-cxa-atexit -emit-llvm -o - | FileCheck %s + +// CHECK: define internal void @_GLOBAL__D_a() +// CHECK: call void @_ZN1AD1Ev(%class.A* @b) +// CHECK: call void @_ZN1AD1Ev(%class.A* @a) +// CHECK: } + +class A { +public: + A(); + ~A(); +}; + +A a, b; diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index b60e056d70..7cbd55940b 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -28,4 +28,4 @@ C c; // CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1DD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @d, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*)) D d; -// CHECK: define internal void @__cxx_global_initialization() { +// CHECK: define internal void @_GLOBAL__I_a() { |