Newer
Older
static bool needsDestructMethod(ObjCImplementationDecl *impl) {
ObjCInterfaceDecl *iface
= const_cast<ObjCInterfaceDecl*>(impl->getClassInterface());
for (ObjCIvarDecl *ivar = iface->all_declared_ivar_begin();
ivar; ivar = ivar->getNextIvar())
if (ivar->getType().isDestructedType())
return true;
return false;
}
/// EmitObjCIvarInitializations - Emit information for ivar initialization
/// for an implementation.
void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
// We might need a .cxx_destruct even if we don't have any ivar initializers.
if (needsDestructMethod(D)) {
IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct");
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
ObjCMethodDecl *DTORMethod =
ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(),
cxxSelector, getContext().VoidTy, 0, D, true,
false, true, false, ObjCMethodDecl::Required);
D->addInstanceMethod(DTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
}
// If the implementation doesn't have any ivar initializers, we don't need
// a .cxx_construct.
David Chisnall
committed
if (D->getNumIvarInitializers() == 0)
IdentifierInfo *II = &getContext().Idents.get(".cxx_construct");
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
// The constructor returns 'self'.
ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(),
D->getLocation(),
D->getLocation(), cxxSelector,
getContext().getObjCIdType(), 0,
D, true, false, true, false,
ObjCMethodDecl::Required);
D->addInstanceMethod(CTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
/// EmitNamespace - Emit all declarations in a namespace.
void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) {
for (RecordDecl::decl_iterator I = ND->decls_begin(), E = ND->decls_end();
I != E; ++I)
EmitTopLevelDecl(*I);
}
// EmitLinkageSpec - Emit all declarations in a linkage spec.
void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
if (LSD->getLanguage() != LinkageSpecDecl::lang_c &&
LSD->getLanguage() != LinkageSpecDecl::lang_cxx) {
ErrorUnsupported(LSD, "linkage spec");
return;
}
for (RecordDecl::decl_iterator I = LSD->decls_begin(), E = LSD->decls_end();
I != E; ++I)
EmitTopLevelDecl(*I);
}
/// EmitTopLevelDecl - Emit code for a single top level declaration.
void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// If an error has occurred, stop code generation, but continue
// parsing and semantic analysis (to ensure all warnings and errors
// are emitted).
if (Diags.hasErrorOccurred())
return;
// Ignore dependent declarations.
if (D->getDeclContext() && D->getDeclContext()->isDependentContext())
return;
case Decl::CXXMethod:
// Skip function templates
if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
cast<FunctionDecl>(D)->isLateTemplateParsed())
return;
EmitGlobal(cast<FunctionDecl>(D));
break;
EmitGlobal(cast<VarDecl>(D));
// Indirect fields from global anonymous structs and unions can be
// ignored; only the actual variable requires IR gen support.
case Decl::IndirectField:
break;
EmitNamespace(cast<NamespaceDecl>(D));
// No code generation needed.
case Decl::Using:
case Decl::UsingDirective:
case Decl::ClassTemplate:
case Decl::FunctionTemplate:
case Decl::TypeAliasTemplate:
case Decl::Block:
break;
case Decl::CXXConstructor:
// Skip function templates
if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
cast<FunctionDecl>(D)->isLateTemplateParsed())
return;
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
Anders Carlsson
committed
case Decl::CXXDestructor:
if (cast<FunctionDecl>(D)->isLateTemplateParsed())
return;
Anders Carlsson
committed
EmitCXXDestructors(cast<CXXDestructorDecl>(D));
break;
case Decl::StaticAssert:
// Nothing to do.
break;
// Objective-C Decls
// Forward declarations, no (immediate) code generation.
case Decl::ObjCClass:
case Decl::ObjCForwardProtocol:
case Decl::ObjCInterface:
case Decl::ObjCCategory: {
ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
if (CD->IsClassExtension() && CD->hasSynthBitfield())
Context.ResetObjCLayout(CD->getClassInterface());
break;
}
Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
break;
case Decl::ObjCCategoryImpl:
// Categories have properties but don't support synthesize so we
// can ignore them here.
Runtime->GenerateCategory(cast<ObjCCategoryImplDecl>(D));
break;
case Decl::ObjCImplementation: {
ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield())
Context.ResetObjCLayout(OMD->getClassInterface());
EmitObjCIvarInitializations(OMD);
case Decl::ObjCMethod: {
ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
// If this is not a prototype, emit the body.
Argyrios Kyrtzidis
committed
if (OMD->getBody())
CodeGenFunction(*this).GenerateObjCMethod(OMD);
break;
}
// compatibility-alias is a directive and has no code gen.
case Decl::LinkageSpec:
EmitLinkageSpec(cast<LinkageSpecDecl>(D));
break;
case Decl::FileScopeAsm: {
FileScopeAsmDecl *AD = cast<FileScopeAsmDecl>(D);
llvm::StringRef AsmString = AD->getAsmString()->getString();
const std::string &S = getModule().getModuleInlineAsm();
if (S.empty())
getModule().setModuleInlineAsm(AsmString);
else
getModule().setModuleInlineAsm(S + '\n' + AsmString.str());
// Make sure we handled everything we should, every other kind is a
// non-top-level decl. FIXME: Would be nice to have an isTopLevelDeclKind
// function. Need to recode Decl::Kind to do that easily.
assert(isa<TypeDecl>(D) && "Unsupported decl kind");
}
}
/// Turns the given pointer into a constant.
static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
const void *Ptr) {
uintptr_t PtrInt = reinterpret_cast<uintptr_t>(Ptr);
llvm::Type *i64 = llvm::Type::getInt64Ty(Context);
return llvm::ConstantInt::get(i64, PtrInt);
}
static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
llvm::NamedMDNode *&GlobalMetadata,
GlobalDecl D,
llvm::GlobalValue *Addr) {
if (!GlobalMetadata)
GlobalMetadata =
CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs");
// TODO: should we report variant information for ctors/dtors?
llvm::Value *Ops[] = {
Addr,
GetPointerConstant(CGM.getLLVMContext(), D.getDecl())
};
GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops));
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
}
/// Emits metadata nodes associating all the global values in the
/// current module with the Decls they came from. This is useful for
/// projects using IR gen as a subroutine.
///
/// Since there's currently no way to associate an MDNode directly
/// with an llvm::GlobalValue, we create a global named metadata
/// with the name 'clang.global.decl.ptrs'.
void CodeGenModule::EmitDeclMetadata() {
llvm::NamedMDNode *GlobalMetadata = 0;
// StaticLocalDeclMap
for (llvm::DenseMap<GlobalDecl,llvm::StringRef>::iterator
I = MangledDeclNames.begin(), E = MangledDeclNames.end();
I != E; ++I) {
llvm::GlobalValue *Addr = getModule().getNamedValue(I->second);
EmitGlobalDeclMetadata(*this, GlobalMetadata, I->first, Addr);
}
}
/// Emits metadata nodes for all the local variables in the current
/// function.
void CodeGenFunction::EmitDeclMetadata() {
if (LocalDeclMap.empty()) return;
llvm::LLVMContext &Context = getLLVMContext();
// Find the unique metadata ID for this name.
unsigned DeclPtrKind = Context.getMDKindID("clang.decl.ptr");
llvm::NamedMDNode *GlobalMetadata = 0;
for (llvm::DenseMap<const Decl*, llvm::Value*>::iterator
I = LocalDeclMap.begin(), E = LocalDeclMap.end(); I != E; ++I) {
const Decl *D = I->first;
llvm::Value *Addr = I->second;
if (llvm::AllocaInst *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, DAddr));
} else if (llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(Addr)) {
GlobalDecl GD = GlobalDecl(cast<VarDecl>(D));
EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV);
}
}
}
void CodeGenModule::EmitCoverageFile() {
if (!getCodeGenOpts().CoverageFile.empty()) {
if (llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu")) {
llvm::NamedMDNode *GCov = TheModule.getOrInsertNamedMetadata("llvm.gcov");
llvm::LLVMContext &Ctx = TheModule.getContext();
llvm::MDString *CoverageFile =
llvm::MDString::get(Ctx, getCodeGenOpts().CoverageFile);
for (int i = 0, e = CUNode->getNumOperands(); i != e; ++i) {
llvm::MDNode *CU = CUNode->getOperand(i);
llvm::Value *node[] = { CoverageFile, CU };
llvm::MDNode *N = llvm::MDNode::get(Ctx, node);
GCov->addOperand(N);
}
}
}
}
///@name Custom Runtime Function Interfaces
///@{
//
// FIXME: These can be eliminated once we can have clients just get the required
// AST nodes from the builtin tables.
llvm::Constant *CodeGenModule::getBlockObjectDispose() {
if (BlockObjectDispose)
return BlockObjectDispose;
// If we saw an explicit decl, use that.
if (BlockObjectDisposeDecl) {
return BlockObjectDispose = GetAddrOfFunction(
BlockObjectDisposeDecl,
getTypes().GetFunctionType(BlockObjectDisposeDecl));
}
// Otherwise construct the function by hand.
llvm::Type *args[] = { Int8PtrTy, Int32Ty };
llvm::FunctionType *fty
= llvm::FunctionType::get(VoidTy, args, false);
return BlockObjectDispose =
CreateRuntimeFunction(fty, "_Block_object_dispose");
}
llvm::Constant *CodeGenModule::getBlockObjectAssign() {
if (BlockObjectAssign)
return BlockObjectAssign;
// If we saw an explicit decl, use that.
if (BlockObjectAssignDecl) {
return BlockObjectAssign = GetAddrOfFunction(
BlockObjectAssignDecl,
getTypes().GetFunctionType(BlockObjectAssignDecl));
}
// Otherwise construct the function by hand.
llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
llvm::FunctionType *fty
= llvm::FunctionType::get(VoidTy, args, false);
return BlockObjectAssign =
CreateRuntimeFunction(fty, "_Block_object_assign");
}
llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
if (NSConcreteGlobalBlock)
return NSConcreteGlobalBlock;
// If we saw an explicit decl, use that.
if (NSConcreteGlobalBlockDecl) {
return NSConcreteGlobalBlock = GetAddrOfGlobalVar(
NSConcreteGlobalBlockDecl,
getTypes().ConvertType(NSConcreteGlobalBlockDecl->getType()));
}
// Otherwise construct the variable by hand.
return NSConcreteGlobalBlock =
CreateRuntimeVariable(Int8PtrTy, "_NSConcreteGlobalBlock");
}
llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
if (NSConcreteStackBlock)
return NSConcreteStackBlock;
// If we saw an explicit decl, use that.
if (NSConcreteStackBlockDecl) {
return NSConcreteStackBlock = GetAddrOfGlobalVar(
NSConcreteStackBlockDecl,
getTypes().ConvertType(NSConcreteStackBlockDecl->getType()));
}
// Otherwise construct the variable by hand.
return NSConcreteStackBlock =
CreateRuntimeVariable(Int8PtrTy, "_NSConcreteStackBlock");
}
///@}