CGCXX.cpp revision e9918d2443ad524e0f488e8f15d9bce4e7373cd1
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/DeclCXX.h"
21#include "clang/AST/DeclObjC.h"
22#include "llvm/ADT/StringExtras.h"
23using namespace clang;
24using namespace CodeGen;
25
26
27// FIXME: Name mangling should be moved to a separate class.
28
29static void mangleDeclContextInternal(const DeclContext *D, std::string &S)
30{
31  // FIXME: Should ObjcMethodDecl have the TranslationUnitDecl as its parent?
32  assert((!D->getParent() || isa<TranslationUnitDecl>(D->getParent())) &&
33         "Only one level of decl context mangling is currently supported!");
34
35  if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
36    S += llvm::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 if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) {
44
45    // FIXME: This should really use GetNameForMethod from CGObjCMac.
46    std::string Name;
47    Name += MD->isInstanceMethod() ? '-' : '+';
48    Name += '[';
49    Name += MD->getClassInterface()->getNameAsString();
50    Name += ' ';
51    Name += MD->getSelector().getAsString();
52    Name += ']';
53    S += llvm::utostr(Name.length());
54    S += Name;
55  } else
56    assert(0 && "Unsupported decl type!");
57}
58
59static void mangleVarDeclInternal(const VarDecl &D, std::string &S)
60{
61  S += 'Z';
62  mangleDeclContextInternal(D.getDeclContext(), S);
63  S += 'E';
64
65  S += llvm::utostr(D.getIdentifier()->getLength());
66  S += D.getIdentifier()->getName();
67}
68
69static std::string mangleVarDecl(const VarDecl& D)
70{
71  std::string S = "_Z";
72
73  mangleVarDeclInternal(D, S);
74
75  return S;
76}
77
78static std::string mangleGuardVariable(const VarDecl& D)
79{
80  std::string S = "_ZGV";
81
82  mangleVarDeclInternal(D, S);
83
84  return S;
85}
86
87void
88CodeGenFunction::GenerateStaticCXXBlockVarDeclInit(const VarDecl &D,
89                                                   llvm::GlobalVariable *GV) {
90  // FIXME: This should use __cxa_guard_{acquire,release}?
91
92  assert(!getContext().getLangOptions().ThreadsafeStatics &&
93         "thread safe statics are currently not supported!");
94
95  // Create the guard variable.
96  llvm::GlobalValue *GuardV =
97    new llvm::GlobalVariable(llvm::Type::Int64Ty, false,
98                             GV->getLinkage(),
99                             llvm::Constant::getNullValue(llvm::Type::Int64Ty),
100                             mangleGuardVariable(D),
101                             &CGM.getModule());
102
103  // Load the first byte of the guard variable.
104  const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
105  llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
106                                      "tmp");
107
108  // Compare it against 0.
109  llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::Int8Ty);
110  llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool");
111
112  llvm::BasicBlock *InitBlock = createBasicBlock("init");
113  llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
114
115  // If the guard variable is 0, jump to the initializer code.
116  Builder.CreateCondBr(ICmp, InitBlock, EndBlock);
117
118  EmitBlock(InitBlock);
119
120  // Patch the name. FIXME: We shouldn't need to do this.
121  GV->setName(mangleVarDecl(D));
122
123  const Expr *Init = D.getInit();
124  if (!hasAggregateLLVMType(Init->getType())) {
125    llvm::Value *V = EmitScalarExpr(Init);
126    Builder.CreateStore(V, GV, D.getType().isVolatileQualified());
127  } else if (Init->getType()->isAnyComplexType()) {
128    EmitComplexExprIntoAddr(Init, GV, D.getType().isVolatileQualified());
129  } else {
130    EmitAggExpr(Init, GV, D.getType().isVolatileQualified());
131  }
132
133  Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::Int8Ty, 1),
134                      Builder.CreateBitCast(GuardV, PtrTy));
135
136  EmitBlock(EndBlock);
137}
138
139RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
140  const MemberExpr *ME = cast<MemberExpr>(CE->getCallee());
141  const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl());
142  assert(MD->isInstance() &&
143         "Trying to emit a member call expr on a static method!");
144
145  const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
146  const llvm::Type *Ty =
147    CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
148                                   FPT->isVariadic());
149  llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, Ty);
150
151  llvm::Value *BaseValue = 0;
152
153  // There's a deref operator node added in Sema::BuildCallToMemberFunction
154  // that's giving the wrong type for -> call exprs so we just ignore them
155  // for now.
156  if (ME->isArrow())
157    return EmitUnsupportedRValue(CE, "C++ member call expr");
158  else {
159    LValue BaseLV = EmitLValue(ME->getBase());
160    BaseValue = BaseLV.getAddress();
161  }
162
163  CallArgList Args;
164
165  // Push the 'this' pointer.
166  Args.push_back(std::make_pair(RValue::get(BaseValue),
167                                MD->getThisType(getContext())));
168
169  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
170       I != E; ++I)
171    Args.push_back(std::make_pair(EmitAnyExprToTemp(*I), I->getType()));
172
173  QualType ResultType = MD->getType()->getAsFunctionType()->getResultType();
174  return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args),
175                  Callee, Args, MD);
176}
177