blob: 76e044bd9f39b9937263a4935d374c7882b3c9fc [file] [log] [blame]
Anders Carlssonc9f8ccd2008-08-22 16:00:37 +00001//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code dealing with C++ code generation.
11//
12//===----------------------------------------------------------------------===//
13
14// We might split this into multiple files if it gets too unwieldy
15
16#include "CodeGenFunction.h"
17#include "CodeGenModule.h"
18#include "clang/AST/ASTContext.h"
19#include "clang/AST/Decl.h"
20#include "llvm/ADT/StringExtras.h"
21
22using namespace clang;
23using namespace CodeGen;
24
25using llvm::utostr;
26
27
28// FIXME: Name mangling should be moved to a separate class.
29
30static void mangleDeclContextInternal(const DeclContext *D, std::string &S)
31{
32 assert(isa<TranslationUnitDecl>(D->getParent()) &&
33 "Only one level of decl context mangling is currently supported!");
34
35 if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
36 S += utostr(FD->getIdentifier()->getLength());
37 S += FD->getIdentifier()->getName();
38
39 if (FD->param_size() == 0)
40 S += 'v';
41 else
42 assert(0 && "mangling of types not supported yet!");
43 } else
44 assert(0 && "Unsupported decl type!");
45}
46
47static void mangleVarDeclInternal(const VarDecl &D, std::string &S)
48{
49 S += 'Z';
50 mangleDeclContextInternal(D.getDeclContext(), S);
51 S += 'E';
52
53 S += utostr(D.getIdentifier()->getLength());
54 S += D.getIdentifier()->getName();
55}
56
57static std::string mangleVarDecl(const VarDecl& D)
58{
59 std::string S = "_Z";
60
61 mangleVarDeclInternal(D, S);
62
63 return S;
64}
65
66static std::string mangleGuardVariable(const VarDecl& D)
67{
68 std::string S = "_ZGV";
69
70 mangleVarDeclInternal(D, S);
71
72 return S;
73}
74
75llvm::GlobalValue *
76CodeGenFunction::GenerateStaticCXXBlockVarDecl(const VarDecl &D)
77{
78 assert(!getContext().getLangOptions().ThreadsafeStatics &&
79 "thread safe statics are currently not supported!");
80 const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
81
82 // FIXME: If the function is inline, the linkage should be weak.
83 llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::InternalLinkage;
84
85 // Create the guard variable.
86 llvm::GlobalValue *GuardV =
87 new llvm::GlobalVariable(llvm::Type::Int64Ty, false,
88 linkage,
89 llvm::Constant::getNullValue(llvm::Type::Int64Ty),
90 mangleGuardVariable(D),
91 &CGM.getModule());
92
93 // FIXME: Address space.
94 const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
95
96 // Load the first byte of the guard variable.
97 llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
98 "tmp");
99
100 // Compare it against 0.
101 llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::Int8Ty);
102 llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool");
103
104 llvm::BasicBlock *InitBlock = llvm::BasicBlock::Create("init");
105 llvm::BasicBlock *EndBlock = llvm::BasicBlock::Create("initend");
106
107 // If the guard variable is 0, jump to the initializer code.
108 Builder.CreateCondBr(ICmp, InitBlock, EndBlock);
109
110 EmitBlock(InitBlock);
111
112 llvm::GlobalValue *GV =
113 new llvm::GlobalVariable(LTy, false,
114 llvm::GlobalValue::InternalLinkage,
115 llvm::Constant::getNullValue(LTy),
116 mangleVarDecl(D),
117 &CGM.getModule(), 0,
118 D.getType().getAddressSpace());
119
120 const Expr *Init = D.getInit();
121 if (!hasAggregateLLVMType(Init->getType())) {
122 llvm::Value *V = EmitScalarExpr(Init);
123 Builder.CreateStore(V, GV, D.getType().isVolatileQualified());
124 } else if (Init->getType()->isAnyComplexType()) {
125 EmitComplexExprIntoAddr(Init, GV, D.getType().isVolatileQualified());
126 } else {
127 EmitAggExpr(Init, GV, D.getType().isVolatileQualified());
128 }
129
130 Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::Int8Ty, 1),
131 Builder.CreateBitCast(GuardV, PtrTy));
132
133 EmitBlock(EndBlock);
134 return GV;
135}
136