Newer
Older
//===--- CodeGenModule.cpp - Emit LLVM Code from ASTs for a Module --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This coordinates the per-module state used while generating code.
//
//===----------------------------------------------------------------------===//
#include "CGDebugInfo.h"
#include "CodeGenModule.h"
#include "CodeGenFunction.h"
#include "CGObjCRuntime.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
Nate Begeman
committed
#include "llvm/CallingConv.h"
Chris Lattner
committed
#include "llvm/Module.h"
#include "llvm/Intrinsics.h"
Anton Korobeynikov
committed
#include "llvm/Target/TargetData.h"
using namespace clang;
using namespace CodeGen;
CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
llvm::Module &M, const llvm::TargetData &TD,
: Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags),
Types(C, M, TD), Runtime(0), MemCpyFn(0), MemMoveFn(0), MemSetFn(0),
CFConstantStringClassRef(0) {
if (Features.ObjC1) {
Runtime = CreateMacObjCRuntime(*this);
} else {
Runtime = CreateGNUObjCRuntime(*this);
}
// If debug info generation is enabled, create the CGDebugInfo object.
Ted Kremenek
committed
DebugInfo = GenerateDebugInfo ? new CGDebugInfo(this) : 0;
}
CodeGenModule::~CodeGenModule() {
Ted Kremenek
committed
delete Runtime;
delete DebugInfo;
}
void CodeGenModule::Release() {
Anton Korobeynikov
committed
EmitStatics();
EmitAliases();
if (Runtime)
if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction())
AddGlobalCtor(ObjCInitFunction);
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitAnnotations();
BindRuntimeFunctions();
void CodeGenModule::BindRuntimeFunctions() {
// Deal with protecting runtime function names.
for (unsigned i = 0, e = RuntimeFunctions.size(); i < e; ++i) {
llvm::Function *Fn = RuntimeFunctions[i].first;
const std::string &Name = RuntimeFunctions[i].second;
// See if there is a conflict against a function.
llvm::Function *Conflict = TheModule.getFunction(Name);
if (Conflict) {
// Decide which version to take. If the conflict is a definition
// we are forced to take that, otherwise assume the runtime
// knows best.
if (!Conflict->isDeclaration()) {
llvm::Value *Casted =
llvm::ConstantExpr::getBitCast(Conflict, Fn->getType());
Fn->replaceAllUsesWith(Casted);
Fn->eraseFromParent();
} else {
Fn->takeName(Conflict);
llvm::Value *Casted =
llvm::ConstantExpr::getBitCast(Fn, Conflict->getType());
Conflict->replaceAllUsesWith(Casted);
Conflict->eraseFromParent();
}
} else {
// FIXME: There still may be conflicts with aliases and
// variables.
Fn->setName(Name);
}
}
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type,
bool OmitOnError) {
if (OmitOnError && getDiags().hasErrorOccurred())
return;
unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error,
"cannot codegen this %0 yet");
SourceRange Range = S->getSourceRange();
std::string Msg = Type;
getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID,
&Msg, 1, &Range, 1);
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified decl yet.
void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
bool OmitOnError) {
if (OmitOnError && getDiags().hasErrorOccurred())
return;
unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error,
"cannot codegen this %0 yet");
std::string Msg = Type;
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID,
&Msg, 1);
}
/// setGlobalVisibility - Set the visibility for the given LLVM
/// GlobalValue according to the given clang AST visibility value.
static void setGlobalVisibility(llvm::GlobalValue *GV,
VisibilityAttr::VisibilityTypes Vis) {
switch (Vis) {
default: assert(0 && "Unknown visibility!");
case VisibilityAttr::DefaultVisibility:
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
break;
case VisibilityAttr::HiddenVisibility:
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
break;
case VisibilityAttr::ProtectedVisibility:
GV->setVisibility(llvm::GlobalValue::ProtectedVisibility);
break;
}
}
Chris Lattner
committed
/// AddGlobalCtor - Add a function to the list that will be called before
/// main() runs.
void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) {
Chris Lattner
committed
// TODO: Type coercion of void()* types.
GlobalCtors.push_back(std::make_pair(Ctor, Priority));
Chris Lattner
committed
}
/// AddGlobalDtor - Add a function to the list that will be called
/// when the module is unloaded.
void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) {
// TODO: Type coercion of void()* types.
GlobalDtors.push_back(std::make_pair(Dtor, Priority));
}
void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
// Ctor function type is void()*.
llvm::FunctionType* CtorFTy =
llvm::FunctionType::get(llvm::Type::VoidTy,
std::vector<const llvm::Type*>(),
false);
llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
// Get the type of a ctor entry, { i32, void ()* }.
llvm::StructType* CtorStructTy =
llvm::StructType::get(llvm::Type::Int32Ty,
llvm::PointerType::getUnqual(CtorFTy), NULL);
// Construct the constructor and destructor arrays.
std::vector<llvm::Constant*> Ctors;
for (CtorList::const_iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
std::vector<llvm::Constant*> S;
S.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, I->second, false));
S.push_back(llvm::ConstantExpr::getBitCast(I->first, CtorPFTy));
Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
}
if (!Ctors.empty()) {
llvm::ArrayType *AT = llvm::ArrayType::get(CtorStructTy, Ctors.size());
new llvm::GlobalVariable(AT, false,
llvm::GlobalValue::AppendingLinkage,
llvm::ConstantArray::get(AT, Ctors),
GlobalName,
&TheModule);
Chris Lattner
committed
}
}
void CodeGenModule::EmitAnnotations() {
if (Annotations.empty())
return;
// Create a new global variable for the ConstantStruct in the Module.
llvm::Constant *Array =
llvm::ConstantArray::get(llvm::ArrayType::get(Annotations[0]->getType(),
Annotations.size()),
Annotations);
Loading
Loading full blame...