CGCXX.cpp revision 9615ecb44f549ae9fa2b4db6ff46bc78befbf62c
1//===--- 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 "clang/AST/DeclObjC.h"
21#include "llvm/ADT/StringExtras.h"
22
23using namespace clang;
24using namespace CodeGen;
25
26using llvm::utostr;
27
28
29// FIXME: Name mangling should be moved to a separate class.
30
31static void mangleDeclContextInternal(const DeclContext *D, std::string &S)
32{
33  // FIXME: Should ObjcMethodDecl have the TranslationUnitDecl as its parent?
34  assert(!D->getParent() || isa<TranslationUnitDecl>(D->getParent()) &&
35         "Only one level of decl context mangling is currently supported!");
36
37  if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
38    S += utostr(FD->getIdentifier()->getLength());
39    S += FD->getIdentifier()->getName();
40
41    if (FD->param_size() == 0)
42      S += 'v';
43    else
44      assert(0 && "mangling of types not supported yet!");
45  } else if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) {
46
47    // FIXME: This should really use GetNameForMethod from CGObjCMac.
48    std::string Name;
49    Name += MD->isInstance() ? '-' : '+';
50    Name += '[';
51    Name += MD->getClassInterface()->getName();
52    Name += ' ';
53    Name += MD->getSelector().getName();
54    Name += ']';
55    S += utostr(Name.length());
56    S += Name;
57  } else
58    assert(0 && "Unsupported decl type!");
59}
60
61static void mangleVarDeclInternal(const VarDecl &D, std::string &S)
62{
63  S += 'Z';
64  mangleDeclContextInternal(D.getDeclContext(), S);
65  S += 'E';
66
67  S += utostr(D.getIdentifier()->getLength());
68  S += D.getIdentifier()->getName();
69}
70
71static std::string mangleVarDecl(const VarDecl& D)
72{
73  std::string S = "_Z";
74
75  mangleVarDeclInternal(D, S);
76
77  return S;
78}
79
80static std::string mangleGuardVariable(const VarDecl& D)
81{
82  std::string S = "_ZGV";
83
84  mangleVarDeclInternal(D, S);
85
86  return S;
87}
88
89llvm::GlobalValue *
90CodeGenFunction::GenerateStaticCXXBlockVarDecl(const VarDecl &D)
91{
92  assert(!getContext().getLangOptions().ThreadsafeStatics &&
93         "thread safe statics are currently not supported!");
94  const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
95
96  // FIXME: If the function is inline, the linkage should be weak.
97  llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::InternalLinkage;
98
99  // Create the guard variable.
100  llvm::GlobalValue *GuardV =
101    new llvm::GlobalVariable(llvm::Type::Int64Ty, false,
102                             linkage,
103                             llvm::Constant::getNullValue(llvm::Type::Int64Ty),
104                             mangleGuardVariable(D),
105                             &CGM.getModule());
106
107  // FIXME: Address space.
108  const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
109
110  // Load the first byte of the guard variable.
111  llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
112                                      "tmp");
113
114  // Compare it against 0.
115  llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::Int8Ty);
116  llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool");
117
118  llvm::BasicBlock *InitBlock = createBasicBlock("init");
119  llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
120
121  // If the guard variable is 0, jump to the initializer code.
122  Builder.CreateCondBr(ICmp, InitBlock, EndBlock);
123
124  EmitBlock(InitBlock);
125
126  llvm::GlobalValue *GV =
127    new llvm::GlobalVariable(LTy, false,
128                             llvm::GlobalValue::InternalLinkage,
129                             llvm::Constant::getNullValue(LTy),
130                             mangleVarDecl(D),
131                             &CGM.getModule(), 0,
132                             D.getType().getAddressSpace());
133
134  const Expr *Init = D.getInit();
135  if (!hasAggregateLLVMType(Init->getType())) {
136    llvm::Value *V = EmitScalarExpr(Init);
137    Builder.CreateStore(V, GV, D.getType().isVolatileQualified());
138  } else if (Init->getType()->isAnyComplexType()) {
139    EmitComplexExprIntoAddr(Init, GV, D.getType().isVolatileQualified());
140  } else {
141    EmitAggExpr(Init, GV, D.getType().isVolatileQualified());
142  }
143
144  Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::Int8Ty, 1),
145                      Builder.CreateBitCast(GuardV, PtrTy));
146
147  EmitBlock(EndBlock);
148  return GV;
149}
150
151