diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 89 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 15 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 9 |
6 files changed, 112 insertions, 21 deletions
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 22a103ce35f..40c18ca3c2a 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index d9b14578114..bd12c4a87c2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/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/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 3b04cc125eb..b4b5bbdb99a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index b93f3c634d3..febb8560367 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/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/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 58a4cdb89b3..87449760a73 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/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/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 2dfc592ec89..6e18f346d56 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/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); |