From e1b29efab32d02e114046d33cca242a88585bf8a Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 22 Aug 2008 16:00:37 +0000 Subject: [PATCH] Add preliminary (and probably broken) codegen support for C++ static initializers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55180 91177308-0d34-0410-b5e6-96231b3b80d8 --- clang.xcodeproj/project.pbxproj | 30 ++++--- include/clang/Basic/LangOptions.h | 7 +- lib/CodeGen/CGCXX.cpp | 136 ++++++++++++++++++++++++++++++ lib/CodeGen/CGDecl.cpp | 8 +- lib/CodeGen/CodeGenFunction.h | 4 + 5 files changed, 170 insertions(+), 15 deletions(-) create mode 100644 lib/CodeGen/CGCXX.cpp diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 5fcaeb130a..6e545c1556 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A30A9E80B93A4C800201A91 /* ExprCXX.h */; }; 1A32C17F0E1C87AD00A6B483 /* ExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */; }; 1A376A2D0D4AED9B002A1C52 /* CGExprConstant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */; }; + 1A5D5E580E5E81010023C059 /* CGCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A5D5E570E5E81010023C059 /* CGCXX.cpp */; }; 1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; }; 1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; }; 1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; }; @@ -263,6 +264,7 @@ 1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = ""; }; 1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ExprConstant.cpp; path = lib/AST/ExprConstant.cpp; sourceTree = ""; tabWidth = 2; }; 1A376A2C0D4AED9B002A1C52 /* CGExprConstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprConstant.cpp; path = lib/CodeGen/CGExprConstant.cpp; sourceTree = ""; }; + 1A5D5E570E5E81010023C059 /* CGCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGCXX.cpp; path = lib/CodeGen/CGCXX.cpp; sourceTree = ""; tabWidth = 2; }; 1A68BC110D0CADDD001A28C8 /* PPCBuiltins.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = PPCBuiltins.def; path = clang/AST/PPCBuiltins.def; sourceTree = ""; }; 1A68BC120D0CADDD001A28C8 /* TargetBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TargetBuiltins.h; path = clang/AST/TargetBuiltins.h; sourceTree = ""; }; 1A68BC130D0CADDD001A28C8 /* X86Builtins.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = X86Builtins.def; path = clang/AST/X86Builtins.def; sourceTree = ""; }; @@ -357,7 +359,7 @@ 8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; }; DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = ""; }; DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = lib/Parse/ParseExprCXX.cpp; sourceTree = ""; }; - DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = ""; }; + DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = ""; tabWidth = 2; }; DE06BECA0A854E4B0050E87E /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Parse/Scope.h; sourceTree = ""; }; DE06D42F0A8BB52D0050E87E /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Parser.cpp; path = lib/Parse/Parser.cpp; sourceTree = ""; }; DE06E8130A8FF9330050E87E /* Action.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Action.h; path = clang/Parse/Action.h; sourceTree = ""; tabWidth = 8; usesTabs = 0; }; @@ -392,7 +394,7 @@ DE38CF260D8C9E6C00A273B6 /* DeclObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeclObjC.cpp; path = lib/AST/DeclObjC.cpp; sourceTree = ""; }; DE3985780CB8ADC800223765 /* ASTConsumers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTConsumers.h; path = Driver/ASTConsumers.h; sourceTree = ""; }; DE39857A0CB8ADCB00223765 /* ASTConsumers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTConsumers.cpp; path = Driver/ASTConsumers.cpp; sourceTree = ""; }; - DE3986EF0CB8D4B300223765 /* IdentifierTable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IdentifierTable.h; sourceTree = ""; }; + DE3986EF0CB8D4B300223765 /* IdentifierTable.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = IdentifierTable.h; sourceTree = ""; tabWidth = 2; }; DE3986F30CB8D50C00223765 /* IdentifierTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IdentifierTable.cpp; sourceTree = ""; }; DE41211B0D7F1BBE0080F80A /* RValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RValues.h; path = clang/Analysis/PathSensitive/RValues.h; sourceTree = ""; }; DE41211D0D7F1BBE0080F80A /* GRWorkList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRWorkList.h; path = clang/Analysis/PathSensitive/GRWorkList.h; sourceTree = ""; }; @@ -412,8 +414,8 @@ DE4121300D7F1C1C0080F80A /* GRBlockCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GRBlockCounter.cpp; path = lib/Analysis/GRBlockCounter.cpp; sourceTree = ""; }; DE4121310D7F1C1C0080F80A /* GRExprEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GRExprEngine.cpp; path = lib/Analysis/GRExprEngine.cpp; sourceTree = ""; }; DE4121320D7F1C1C0080F80A /* ProgramPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProgramPoint.cpp; path = lib/Analysis/ProgramPoint.cpp; sourceTree = ""; }; - DE4264FB0C113592005A861D /* CGDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CGDecl.cpp; path = lib/CodeGen/CGDecl.cpp; sourceTree = ""; }; - DE46BF270AE0A82D00CC047C /* TargetInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetInfo.h; sourceTree = ""; }; + DE4264FB0C113592005A861D /* CGDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDecl.cpp; path = lib/CodeGen/CGDecl.cpp; sourceTree = ""; tabWidth = 2; }; + DE46BF270AE0A82D00CC047C /* TargetInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = TargetInfo.h; sourceTree = ""; tabWidth = 2; }; DE4772F90C10EAE5002239E8 /* CGStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CGStmt.cpp; path = lib/CodeGen/CGStmt.cpp; sourceTree = ""; }; DE4772FB0C10EAEC002239E8 /* CGExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CGExpr.cpp; path = lib/CodeGen/CGExpr.cpp; sourceTree = ""; }; DE47999B0D2EBE1A00706D2D /* SemaExprObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExprObjC.cpp; path = lib/Sema/SemaExprObjC.cpp; sourceTree = ""; }; @@ -450,7 +452,7 @@ DE928B1F0C0565B000231DA4 /* ModuleBuilder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ModuleBuilder.h; path = clang/CodeGen/ModuleBuilder.h; sourceTree = ""; }; DE928B7C0C0A615100231DA4 /* CodeGenModule.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CodeGenModule.h; path = lib/CodeGen/CodeGenModule.h; sourceTree = ""; }; DE928B7E0C0A615600231DA4 /* CodeGenModule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenModule.cpp; path = lib/CodeGen/CodeGenModule.cpp; sourceTree = ""; }; - DE928B800C0A615B00231DA4 /* CodeGenFunction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CodeGenFunction.h; path = lib/CodeGen/CodeGenFunction.h; sourceTree = ""; }; + DE928B800C0A615B00231DA4 /* CodeGenFunction.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CodeGenFunction.h; path = lib/CodeGen/CodeGenFunction.h; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; DE928B820C0A616000231DA4 /* CodeGenFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenFunction.cpp; path = lib/CodeGen/CodeGenFunction.cpp; sourceTree = ""; }; DEA0EBD90DD2D3C8007A02A9 /* RewriteMacros.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteMacros.cpp; path = Driver/RewriteMacros.cpp; sourceTree = ""; }; DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = ""; }; @@ -465,13 +467,13 @@ DED676D00B6C786700AAD4A3 /* Builtins.def */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = Builtins.def; path = clang/AST/Builtins.def; sourceTree = ""; }; DED676F90B6C797B00AAD4A3 /* Builtins.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Builtins.h; path = clang/AST/Builtins.h; sourceTree = ""; }; DED677C80B6C854100AAD4A3 /* Builtins.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Builtins.cpp; path = lib/AST/Builtins.cpp; sourceTree = ""; }; - DED7D7310A524295003AD0FB /* Diagnostic.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Diagnostic.h; sourceTree = ""; }; - DED7D7320A524295003AD0FB /* DiagnosticKinds.def */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = DiagnosticKinds.def; sourceTree = ""; }; - DED7D7330A524295003AD0FB /* FileManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FileManager.h; sourceTree = ""; }; - DED7D7350A524295003AD0FB /* SourceLocation.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SourceLocation.h; sourceTree = ""; }; - DED7D7360A524295003AD0FB /* SourceManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SourceManager.h; sourceTree = ""; }; - DED7D7370A524295003AD0FB /* TokenKinds.def */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = TokenKinds.def; sourceTree = ""; }; - DED7D7380A524295003AD0FB /* TokenKinds.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TokenKinds.h; sourceTree = ""; }; + DED7D7310A524295003AD0FB /* Diagnostic.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = Diagnostic.h; sourceTree = ""; tabWidth = 2; }; + DED7D7320A524295003AD0FB /* DiagnosticKinds.def */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = text; path = DiagnosticKinds.def; sourceTree = ""; tabWidth = 2; }; + DED7D7330A524295003AD0FB /* FileManager.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = FileManager.h; sourceTree = ""; tabWidth = 2; }; + DED7D7350A524295003AD0FB /* SourceLocation.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = SourceLocation.h; sourceTree = ""; tabWidth = 2; }; + DED7D7360A524295003AD0FB /* SourceManager.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = SourceManager.h; sourceTree = ""; tabWidth = 2; }; + DED7D7370A524295003AD0FB /* TokenKinds.def */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = text; path = TokenKinds.def; sourceTree = ""; tabWidth = 2; }; + DED7D7380A524295003AD0FB /* TokenKinds.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = TokenKinds.h; sourceTree = ""; tabWidth = 2; }; DED7D73B0A524295003AD0FB /* Lexer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Lexer.h; sourceTree = ""; }; DED7D73E0A524295003AD0FB /* MacroInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MacroInfo.h; sourceTree = ""; }; DED7D73F0A524295003AD0FB /* Pragma.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Pragma.h; sourceTree = ""; }; @@ -791,7 +793,6 @@ DE927FCC0C0557CD00231DA4 /* CodeGen */ = { isa = PBXGroup; children = ( - 3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */, DE928B800C0A615B00231DA4 /* CodeGenFunction.h */, DE928B820C0A616000231DA4 /* CodeGenFunction.cpp */, DE928B7C0C0A615100231DA4 /* CodeGenModule.h */, @@ -799,6 +800,7 @@ DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */, DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */, 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */, + 1A5D5E570E5E81010023C059 /* CGCXX.cpp */, 35A3E7000DD3874400757F74 /* CGDebugInfo.cpp */, 35A3E7010DD3874400757F74 /* CGDebugInfo.h */, DE4264FB0C113592005A861D /* CGDecl.cpp */, @@ -810,6 +812,7 @@ 1A7342470C7B57D500122F56 /* CGObjC.cpp */, DE38CD4E0D794CF900A273B6 /* CGObjCRuntime.h */, DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */, + 3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */, DE4772F90C10EAE5002239E8 /* CGStmt.cpp */, DE928B120C05659200231DA4 /* ModuleBuilder.cpp */, ); @@ -1201,6 +1204,7 @@ 3552E7550E520D80003A8CA5 /* PPCaching.cpp in Sources */, 3552E7590E520DD7003A8CA5 /* CGObjCMac.cpp in Sources */, 358F51520E529AA4007F2102 /* GRState.cpp in Sources */, + 1A5D5E580E5E81010023C059 /* CGCXX.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index c07fdfe47c..def23e6550 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -46,6 +46,8 @@ struct LangOptions { unsigned NeXTRuntime : 1; // Use NeXT runtime. + unsigned ThreadsafeStatics : 1; // Whether static initializers are protected + // by lockis. private: unsigned GC : 2; // Objective-C Garbage Collection modes. We declare // this enum as unsigned because MSVC insists on making enums @@ -60,7 +62,10 @@ public: GC = ObjC1 = ObjC2 = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0; CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0; - LaxVectorConversions = Exceptions = NeXTRuntime = 0; + LaxVectorConversions = Exceptions = NeXTRuntime = 0; + + // FIXME: The default should be 1. + ThreadsafeStatics = 0; } GCMode getGCMode() const { return (GCMode) GC; } diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp new file mode 100644 index 0000000000..76e044bd9f --- /dev/null +++ b/lib/CodeGen/CGCXX.cpp @@ -0,0 +1,136 @@ +//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with C++ code generation. +// +//===----------------------------------------------------------------------===// + +// We might split this into multiple files if it gets too unwieldy + +#include "CodeGenFunction.h" +#include "CodeGenModule.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "llvm/ADT/StringExtras.h" + +using namespace clang; +using namespace CodeGen; + +using llvm::utostr; + + +// FIXME: Name mangling should be moved to a separate class. + +static void mangleDeclContextInternal(const DeclContext *D, std::string &S) +{ + assert(isa(D->getParent()) && + "Only one level of decl context mangling is currently supported!"); + + if (FunctionDecl* FD = dyn_cast(D)) { + S += utostr(FD->getIdentifier()->getLength()); + S += FD->getIdentifier()->getName(); + + if (FD->param_size() == 0) + S += 'v'; + else + assert(0 && "mangling of types not supported yet!"); + } else + assert(0 && "Unsupported decl type!"); +} + +static void mangleVarDeclInternal(const VarDecl &D, std::string &S) +{ + S += 'Z'; + mangleDeclContextInternal(D.getDeclContext(), S); + S += 'E'; + + S += utostr(D.getIdentifier()->getLength()); + S += D.getIdentifier()->getName(); +} + +static std::string mangleVarDecl(const VarDecl& D) +{ + std::string S = "_Z"; + + mangleVarDeclInternal(D, S); + + return S; +} + +static std::string mangleGuardVariable(const VarDecl& D) +{ + std::string S = "_ZGV"; + + mangleVarDeclInternal(D, S); + + return S; +} + +llvm::GlobalValue * +CodeGenFunction::GenerateStaticCXXBlockVarDecl(const VarDecl &D) +{ + assert(!getContext().getLangOptions().ThreadsafeStatics && + "thread safe statics are currently not supported!"); + const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType()); + + // FIXME: If the function is inline, the linkage should be weak. + llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::InternalLinkage; + + // Create the guard variable. + llvm::GlobalValue *GuardV = + new llvm::GlobalVariable(llvm::Type::Int64Ty, false, + linkage, + llvm::Constant::getNullValue(llvm::Type::Int64Ty), + mangleGuardVariable(D), + &CGM.getModule()); + + // FIXME: Address space. + const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0); + + // Load the first byte of the guard variable. + llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy), + "tmp"); + + // Compare it against 0. + llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::Int8Ty); + llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool"); + + llvm::BasicBlock *InitBlock = llvm::BasicBlock::Create("init"); + llvm::BasicBlock *EndBlock = llvm::BasicBlock::Create("initend"); + + // If the guard variable is 0, jump to the initializer code. + Builder.CreateCondBr(ICmp, InitBlock, EndBlock); + + EmitBlock(InitBlock); + + llvm::GlobalValue *GV = + new llvm::GlobalVariable(LTy, false, + llvm::GlobalValue::InternalLinkage, + llvm::Constant::getNullValue(LTy), + mangleVarDecl(D), + &CGM.getModule(), 0, + D.getType().getAddressSpace()); + + const Expr *Init = D.getInit(); + if (!hasAggregateLLVMType(Init->getType())) { + llvm::Value *V = EmitScalarExpr(Init); + Builder.CreateStore(V, GV, D.getType().isVolatileQualified()); + } else if (Init->getType()->isAnyComplexType()) { + EmitComplexExprIntoAddr(Init, GV, D.getType().isVolatileQualified()); + } else { + EmitAggExpr(Init, GV, D.getType().isVolatileQualified()); + } + + Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::Int8Ty, 1), + Builder.CreateBitCast(GuardV, PtrTy)); + + EmitBlock(EndBlock); + return GV; +} + diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 1d1721011b..b60e20fda5 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -86,7 +86,13 @@ CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D, if ((D.getInit() == 0) || NoInit) { Init = llvm::Constant::getNullValue(LTy); } else { - Init = CGM.EmitConstantExpr(D.getInit(), this); + if (D.getInit()->isConstantExpr(getContext(), 0)) + Init = CGM.EmitConstantExpr(D.getInit(), this); + else { + assert(getContext().getLangOptions().CPlusPlus && + "only C++ supports non-constant static initializers!"); + return GenerateStaticCXXBlockVarDecl(D); + } } assert(Init && "Unable to create initialiser for static decl"); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 8642c1b861..cf057d8edb 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -525,6 +525,10 @@ public: bool NoInit, const char *Separator); + // GenerateStaticBlockVarDecl - return the static declaration of + // a local variable. Performs initialization of the variable if necessary. + llvm::GlobalValue *GenerateStaticCXXBlockVarDecl(const VarDecl &D); + //===--------------------------------------------------------------------===// // Internal Helpers //===--------------------------------------------------------------------===// -- 2.40.0