diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 136 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 4 |
3 files changed, 147 insertions, 1 deletions
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<TranslationUnitDecl>(D->getParent()) && + "Only one level of decl context mangling is currently supported!"); + + if (FunctionDecl* FD = dyn_cast<FunctionDecl>(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 //===--------------------------------------------------------------------===// |