Newer
Older
Anders Carlsson
committed
//===--- 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 "clang/AST/DeclObjC.h"
Anders Carlsson
committed
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace CodeGen;
// FIXME: Name mangling should be moved to a separate class.
static void mangleDeclContextInternal(const DeclContext *D, std::string &S)
{
// FIXME: Should ObjcMethodDecl have the TranslationUnitDecl as its parent?
assert((!D->getParent() || isa<TranslationUnitDecl>(D->getParent())) &&
Anders Carlsson
committed
"Only one level of decl context mangling is currently supported!");
if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
S += llvm::utostr(FD->getIdentifier()->getLength());
Anders Carlsson
committed
S += FD->getIdentifier()->getName();
if (FD->param_size() == 0)
S += 'v';
else
assert(0 && "mangling of types not supported yet!");
} else if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) {
// FIXME: This should really use GetNameForMethod from CGObjCMac.
std::string Name;
Name += MD->isInstanceMethod() ? '-' : '+';
Name += MD->getClassInterface()->getNameAsString();
Name += MD->getSelector().getAsString();
S += llvm::utostr(Name.length());
Anders Carlsson
committed
} else
assert(0 && "Unsupported decl type!");
}
static void mangleVarDeclInternal(const VarDecl &D, std::string &S)
{
S += 'Z';
mangleDeclContextInternal(D.getDeclContext(), S);
S += 'E';
S += llvm::utostr(D.getIdentifier()->getLength());
Anders Carlsson
committed
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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 = createBasicBlock("init");
llvm::BasicBlock *EndBlock = createBasicBlock("init.end");
Anders Carlsson
committed
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// 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;
}