CGCXX.cpp revision 193326
1191783Srmacklem//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// 2191783Srmacklem// 3191783Srmacklem// The LLVM Compiler Infrastructure 4191783Srmacklem// 5191783Srmacklem// This file is distributed under the University of Illinois Open Source 6191783Srmacklem// License. See LICENSE.TXT for details. 7191783Srmacklem// 8191783Srmacklem//===----------------------------------------------------------------------===// 9191783Srmacklem// 10191783Srmacklem// This contains code dealing with C++ code generation. 11191783Srmacklem// 12191783Srmacklem//===----------------------------------------------------------------------===// 13191783Srmacklem 14191783Srmacklem// We might split this into multiple files if it gets too unwieldy 15191783Srmacklem 16191783Srmacklem#include "CodeGenFunction.h" 17191783Srmacklem#include "CodeGenModule.h" 18191783Srmacklem#include "Mangle.h" 19191783Srmacklem#include "clang/AST/ASTContext.h" 20191783Srmacklem#include "clang/AST/Decl.h" 21191783Srmacklem#include "clang/AST/DeclCXX.h" 22191783Srmacklem#include "clang/AST/DeclObjC.h" 23191783Srmacklem#include "llvm/ADT/StringExtras.h" 24191783Srmacklemusing namespace clang; 25191783Srmacklemusing namespace CodeGen; 26191783Srmacklem 27191783Srmacklemvoid 28191783SrmacklemCodeGenFunction::GenerateStaticCXXBlockVarDeclInit(const VarDecl &D, 29191783Srmacklem llvm::GlobalVariable *GV) { 30191783Srmacklem // FIXME: This should use __cxa_guard_{acquire,release}? 31191783Srmacklem 32191783Srmacklem assert(!getContext().getLangOptions().ThreadsafeStatics && 33191783Srmacklem "thread safe statics are currently not supported!"); 34191783Srmacklem 35191783Srmacklem llvm::SmallString<256> GuardVName; 36191783Srmacklem llvm::raw_svector_ostream GuardVOut(GuardVName); 37191783Srmacklem mangleGuardVariable(&D, getContext(), GuardVOut); 38191783Srmacklem 39191783Srmacklem // Create the guard variable. 40191783Srmacklem llvm::GlobalValue *GuardV = 41191783Srmacklem new llvm::GlobalVariable(llvm::Type::Int64Ty, false, 42191783Srmacklem GV->getLinkage(), 43191783Srmacklem llvm::Constant::getNullValue(llvm::Type::Int64Ty), 44191783Srmacklem GuardVName.c_str(), 45191783Srmacklem &CGM.getModule()); 46191783Srmacklem 47191783Srmacklem // Load the first byte of the guard variable. 48191783Srmacklem const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0); 49191783Srmacklem llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy), 50191783Srmacklem "tmp"); 51191783Srmacklem 52191783Srmacklem // Compare it against 0. 53191783Srmacklem llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::Int8Ty); 54191783Srmacklem llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool"); 55191783Srmacklem 56191783Srmacklem llvm::BasicBlock *InitBlock = createBasicBlock("init"); 57191783Srmacklem llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); 58191783Srmacklem 59191783Srmacklem // If the guard variable is 0, jump to the initializer code. 60191783Srmacklem Builder.CreateCondBr(ICmp, InitBlock, EndBlock); 61191783Srmacklem 62191783Srmacklem EmitBlock(InitBlock); 63191783Srmacklem 64191783Srmacklem const Expr *Init = D.getInit(); 65191783Srmacklem if (!hasAggregateLLVMType(Init->getType())) { 66191783Srmacklem llvm::Value *V = EmitScalarExpr(Init); 67191783Srmacklem Builder.CreateStore(V, GV, D.getType().isVolatileQualified()); 68191783Srmacklem } else if (Init->getType()->isAnyComplexType()) { 69191783Srmacklem EmitComplexExprIntoAddr(Init, GV, D.getType().isVolatileQualified()); 70191783Srmacklem } else { 71191783Srmacklem EmitAggExpr(Init, GV, D.getType().isVolatileQualified()); 72244042Srmacklem } 73191783Srmacklem 74191783Srmacklem Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::Int8Ty, 1), 75191783Srmacklem Builder.CreateBitCast(GuardV, PtrTy)); 76244042Srmacklem 77244042Srmacklem EmitBlock(EndBlock); 78191783Srmacklem} 79191783Srmacklem 80191783SrmacklemRValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, 81191783Srmacklem llvm::Value *Callee, 82191783Srmacklem llvm::Value *This, 83191783Srmacklem CallExpr::const_arg_iterator ArgBeg, 84191783Srmacklem CallExpr::const_arg_iterator ArgEnd) { 85191783Srmacklem assert(MD->isInstance() && 86191783Srmacklem "Trying to emit a member call expr on a static method!"); 87191783Srmacklem 88191783Srmacklem const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 89191783Srmacklem 90192115Srmacklem CallArgList Args; 91191783Srmacklem 92191783Srmacklem // Push the this ptr. 93191783Srmacklem Args.push_back(std::make_pair(RValue::get(This), 94191783Srmacklem MD->getThisType(getContext()))); 95191783Srmacklem 96191783Srmacklem // And the rest of the call args 97191783Srmacklem EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); 98191783Srmacklem 99191783Srmacklem QualType ResultType = MD->getType()->getAsFunctionType()->getResultType(); 100191783Srmacklem return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), 101191783Srmacklem Callee, Args, MD); 102191783Srmacklem} 103191783Srmacklem 104191783SrmacklemRValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { 105191783Srmacklem const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()); 106191783Srmacklem const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); 107191783Srmacklem 108191783Srmacklem const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 109191783Srmacklem const llvm::Type *Ty = 110191783Srmacklem CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 111191783Srmacklem FPT->isVariadic()); 112191783Srmacklem llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty); 113191783Srmacklem 114191783Srmacklem llvm::Value *This; 115191783Srmacklem 116191783Srmacklem if (ME->isArrow()) 117191783Srmacklem This = EmitScalarExpr(ME->getBase()); 118191783Srmacklem else { 119191783Srmacklem LValue BaseLV = EmitLValue(ME->getBase()); 120191783Srmacklem This = BaseLV.getAddress(); 121191783Srmacklem } 122191783Srmacklem 123191783Srmacklem return EmitCXXMemberCall(MD, Callee, This, 124191783Srmacklem CE->arg_begin(), CE->arg_end()); 125191783Srmacklem} 126191783Srmacklem 127191783SrmacklemRValue 128191783SrmacklemCodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, 129220530Srmacklem const CXXMethodDecl *MD) { 130191783Srmacklem assert(MD->isInstance() && 131192115Srmacklem "Trying to emit a member call expr on a static method!"); 132191783Srmacklem 133191783Srmacklem 134191783Srmacklem const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 135191783Srmacklem const llvm::Type *Ty = 136191783Srmacklem CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 137191783Srmacklem FPT->isVariadic()); 138191783Srmacklem llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty); 139191783Srmacklem 140191783Srmacklem llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 141191783Srmacklem 142191783Srmacklem return EmitCXXMemberCall(MD, Callee, This, 143191783Srmacklem E->arg_begin() + 1, E->arg_end()); 144191783Srmacklem} 145191783Srmacklem 146191783Srmacklemllvm::Value *CodeGenFunction::LoadCXXThis() { 147191783Srmacklem assert(isa<CXXMethodDecl>(CurFuncDecl) && 148191783Srmacklem "Must be in a C++ member function decl to load 'this'"); 149191783Srmacklem assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() && 150191783Srmacklem "Must be in a C++ member function decl to load 'this'"); 151191783Srmacklem 152191783Srmacklem // FIXME: What if we're inside a block? 153191783Srmacklem // ans: See how CodeGenFunction::LoadObjCSelf() uses 154191783Srmacklem // CodeGenFunction::BlockForwardSelf() for how to do this. 155191783Srmacklem return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); 156191783Srmacklem} 157191783Srmacklem 158191783Srmacklemvoid 159191783SrmacklemCodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, 160191783Srmacklem CXXCtorType Type, 161191783Srmacklem llvm::Value *This, 162191783Srmacklem CallExpr::const_arg_iterator ArgBeg, 163191783Srmacklem CallExpr::const_arg_iterator ArgEnd) { 164191783Srmacklem llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); 165191783Srmacklem 166191783Srmacklem EmitCXXMemberCall(D, Callee, This, ArgBeg, ArgEnd); 167191783Srmacklem} 168191783Srmacklem 169191783Srmacklemvoid CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D, 170191783Srmacklem CXXDtorType Type, 171191783Srmacklem llvm::Value *This) { 172191783Srmacklem llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(D, Type); 173191783Srmacklem 174191783Srmacklem EmitCXXMemberCall(D, Callee, This, 0, 0); 175191783Srmacklem} 176191783Srmacklem 177191783Srmacklemvoid 178191783SrmacklemCodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, 179191783Srmacklem const CXXConstructExpr *E) { 180191783Srmacklem assert(Dest && "Must have a destination!"); 181191783Srmacklem 182191783Srmacklem const CXXRecordDecl *RD = 183191783Srmacklem cast<CXXRecordDecl>(E->getType()->getAsRecordType()->getDecl()); 184191783Srmacklem if (RD->hasTrivialConstructor()) 185191783Srmacklem return; 186191783Srmacklem 187191783Srmacklem // Call the constructor. 188191783Srmacklem EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest, 189191783Srmacklem E->arg_begin(), E->arg_end()); 190191783Srmacklem} 191191783Srmacklem 192191783Srmacklemvoid CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, 193191783Srmacklem llvm::Value *Ptr) { 194191783Srmacklem LiveTemporaries.push_back(Temporary); 195191783Srmacklem 196191783Srmacklem // Make a cleanup scope and emit the destructor. 197191783Srmacklem { 198191783Srmacklem CleanupScope Scope(*this); 199191783Srmacklem 200191783Srmacklem EmitCXXDestructorCall(Temporary->getDestructor(), Dtor_Complete, Ptr); 201191783Srmacklem } 202191783Srmacklem} 203191783Srmacklem 204191783SrmacklemRValue 205191783SrmacklemCodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, 206191783Srmacklem llvm::Value *AggLoc, 207191783Srmacklem bool isAggLocVolatile) { 208191783Srmacklem // Keep track of the current cleanup stack depth. 209191783Srmacklem size_t CleanupStackDepth = CleanupEntries.size(); 210191783Srmacklem 211191783Srmacklem unsigned OldNumLiveTemporaries = LiveTemporaries.size(); 212191783Srmacklem 213191783Srmacklem RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile); 214191783Srmacklem 215192115Srmacklem // Go through the temporaries backwards. 216191783Srmacklem for (unsigned i = E->getNumTemporaries(); i != 0; --i) { 217191783Srmacklem assert(LiveTemporaries.back() == E->getTemporary(i - 1)); 218191783Srmacklem LiveTemporaries.pop_back(); 219192115Srmacklem } 220191783Srmacklem 221191783Srmacklem assert(OldNumLiveTemporaries == LiveTemporaries.size() && 222191783Srmacklem "Live temporary stack mismatch!"); 223191783Srmacklem 224191783Srmacklem EmitCleanupBlocks(CleanupStackDepth); 225191783Srmacklem 226191783Srmacklem return RV; 227191783Srmacklem} 228191783Srmacklem 229191783Srmacklemllvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { 230192115Srmacklem if (E->isArray()) { 231191783Srmacklem ErrorUnsupported(E, "new[] expression"); 232191783Srmacklem return llvm::UndefValue::get(ConvertType(E->getType())); 233191783Srmacklem } 234191783Srmacklem 235191783Srmacklem QualType AllocType = E->getAllocatedType(); 236191783Srmacklem FunctionDecl *NewFD = E->getOperatorNew(); 237191783Srmacklem const FunctionProtoType *NewFTy = NewFD->getType()->getAsFunctionProtoType(); 238249592Sken 239191783Srmacklem CallArgList NewArgs; 240191783Srmacklem 241191783Srmacklem // The allocation size is the first argument. 242191783Srmacklem QualType SizeTy = getContext().getSizeType(); 243191783Srmacklem llvm::Value *AllocSize = 244191783Srmacklem llvm::ConstantInt::get(ConvertType(SizeTy), 245191783Srmacklem getContext().getTypeSize(AllocType) / 8); 246191783Srmacklem 247191783Srmacklem NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); 248191783Srmacklem 249191783Srmacklem // Emit the rest of the arguments. 250191783Srmacklem // FIXME: Ideally, this should just use EmitCallArgs. 251191783Srmacklem CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); 252191783Srmacklem 253222389Srmacklem // First, use the types from the function type. 254191783Srmacklem // We start at 1 here because the first argument (the allocation size) 255191783Srmacklem // has already been emitted. 256222389Srmacklem for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { 257211951Srmacklem QualType ArgType = NewFTy->getArgType(i); 258205941Srmacklem 259191783Srmacklem assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). 260191783Srmacklem getTypePtr() == 261192115Srmacklem getContext().getCanonicalType(NewArg->getType()).getTypePtr() && 262192115Srmacklem "type mismatch in call argument!"); 263244042Srmacklem 264244042Srmacklem NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 265244042Srmacklem ArgType)); 266244042Srmacklem 267244042Srmacklem } 268259238Srmacklem 269259238Srmacklem // Either we've emitted all the call args, or we have a call to a 270244042Srmacklem // variadic function. 271191783Srmacklem assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && 272192115Srmacklem "Extra arguments in non-variadic function!"); 273191783Srmacklem 274191783Srmacklem // If we still have any arguments, emit them using the type of the argument. 275244042Srmacklem for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); 276191783Srmacklem NewArg != NewArgEnd; ++NewArg) { 277191783Srmacklem QualType ArgType = NewArg->getType(); 278191783Srmacklem NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 279191783Srmacklem ArgType)); 280191783Srmacklem } 281191783Srmacklem 282191783Srmacklem // Emit the call to new. 283191783Srmacklem RValue RV = 284191783Srmacklem EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), 285191783Srmacklem CGM.GetAddrOfFunction(GlobalDecl(NewFD)), 286191783Srmacklem NewArgs, NewFD); 287191783Srmacklem 288191783Srmacklem // If an allocation function is declared with an empty exception specification 289191783Srmacklem // it returns null to indicate failure to allocate storage. [expr.new]p13. 290191783Srmacklem // (We don't need to check for null when there's no new initializer and 291191783Srmacklem // we're allocating a POD type). 292192115Srmacklem bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && 293216700Srmacklem !(AllocType->isPODType() && !E->hasInitializer()); 294191783Srmacklem 295191783Srmacklem llvm::BasicBlock *NewNull = 0; 296191783Srmacklem llvm::BasicBlock *NewNotNull = 0; 297191783Srmacklem llvm::BasicBlock *NewEnd = 0; 298191783Srmacklem 299191783Srmacklem llvm::Value *NewPtr = RV.getScalarVal(); 300191783Srmacklem 301220645Srmacklem if (NullCheckResult) { 302191783Srmacklem NewNull = createBasicBlock("new.null"); 303220648Srmacklem NewNotNull = createBasicBlock("new.notnull"); 304191783Srmacklem NewEnd = createBasicBlock("new.end"); 305191783Srmacklem 306191783Srmacklem llvm::Value *IsNull = 307191783Srmacklem Builder.CreateICmpEQ(NewPtr, 308191783Srmacklem llvm::Constant::getNullValue(NewPtr->getType()), 309240720Srmacklem "isnull"); 310240720Srmacklem 311191783Srmacklem Builder.CreateCondBr(IsNull, NewNull, NewNotNull); 312240720Srmacklem EmitBlock(NewNotNull); 313240720Srmacklem } 314191783Srmacklem 315191783Srmacklem NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); 316191783Srmacklem 317191783Srmacklem if (AllocType->isPODType()) { 318191783Srmacklem if (E->getNumConstructorArgs() > 0) { 319191783Srmacklem assert(E->getNumConstructorArgs() == 1 && 320191783Srmacklem "Can only have one argument to initializer of POD type."); 321191783Srmacklem 322191783Srmacklem const Expr *Init = E->getConstructorArg(0); 323191783Srmacklem 324192121Srmacklem if (!hasAggregateLLVMType(AllocType)) 325191783Srmacklem Builder.CreateStore(EmitScalarExpr(Init), NewPtr); 326192115Srmacklem else if (AllocType->isAnyComplexType()) 327243782Srmacklem EmitComplexExprIntoAddr(Init, NewPtr, AllocType.isVolatileQualified()); 328191783Srmacklem else 329192115Srmacklem EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); 330191783Srmacklem } 331191783Srmacklem } else { 332191783Srmacklem // Call the constructor. 333191783Srmacklem CXXConstructorDecl *Ctor = E->getConstructor(); 334191783Srmacklem 335191783Srmacklem EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, 336191783Srmacklem E->constructor_arg_begin(), 337191783Srmacklem E->constructor_arg_end()); 338191783Srmacklem } 339191783Srmacklem 340207170Srmacklem if (NullCheckResult) { 341191783Srmacklem Builder.CreateBr(NewEnd); 342224078Szack EmitBlock(NewNull); 343224078Szack Builder.CreateBr(NewEnd); 344191783Srmacklem EmitBlock(NewEnd); 345192115Srmacklem 346220648Srmacklem llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); 347191783Srmacklem PHI->reserveOperandSpace(2); 348192115Srmacklem PHI->addIncoming(NewPtr, NewNotNull); 349191783Srmacklem PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull); 350191783Srmacklem 351191783Srmacklem NewPtr = PHI; 352191783Srmacklem } 353191783Srmacklem 354191783Srmacklem return NewPtr; 355191783Srmacklem} 356191783Srmacklem 357192115Srmacklemstatic bool canGenerateCXXstructor(const CXXRecordDecl *RD, 358191783Srmacklem ASTContext &Context) { 359191783Srmacklem // The class has base classes - we don't support that right now. 360191783Srmacklem if (RD->getNumBases() > 0) 361191783Srmacklem return false; 362191783Srmacklem 363191783Srmacklem for (CXXRecordDecl::field_iterator I = RD->field_begin(Context), 364191783Srmacklem E = RD->field_end(Context); I != E; ++I) { 365191783Srmacklem // We don't support ctors for fields that aren't POD. 366191783Srmacklem if (!I->getType()->isPODType()) 367191783Srmacklem return false; 368191783Srmacklem } 369192337Srmacklem 370191783Srmacklem return true; 371191783Srmacklem} 372191783Srmacklem 373191783Srmacklemvoid CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { 374244042Srmacklem if (!canGenerateCXXstructor(D->getParent(), getContext())) { 375191783Srmacklem ErrorUnsupported(D, "C++ constructor", true); 376191783Srmacklem return; 377191783Srmacklem } 378191783Srmacklem 379244042Srmacklem EmitGlobal(GlobalDecl(D, Ctor_Complete)); 380191783Srmacklem EmitGlobal(GlobalDecl(D, Ctor_Base)); 381191783Srmacklem} 382191783Srmacklem 383191783Srmacklemvoid CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, 384191783Srmacklem CXXCtorType Type) { 385191783Srmacklem 386191783Srmacklem llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type); 387191783Srmacklem 388191783Srmacklem CodeGenFunction(*this).GenerateCode(D, Fn); 389222289Srmacklem 390207082Srmacklem SetFunctionDefinitionAttributes(D, Fn); 391191783Srmacklem SetLLVMFunctionAttributesForDefinition(D, Fn); 392191783Srmacklem} 393191783Srmacklem 394191783Srmacklemllvm::Function * 395191783SrmacklemCodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, 396191783Srmacklem CXXCtorType Type) { 397191783Srmacklem const llvm::FunctionType *FTy = 398191783Srmacklem getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 399191783Srmacklem 400191783Srmacklem const char *Name = getMangledCXXCtorName(D, Type); 401191783Srmacklem return cast<llvm::Function>( 402191783Srmacklem GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 403191783Srmacklem} 404191783Srmacklem 405191783Srmacklemconst char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D, 406191783Srmacklem CXXCtorType Type) { 407191783Srmacklem llvm::SmallString<256> Name; 408191783Srmacklem llvm::raw_svector_ostream Out(Name); 409191783Srmacklem mangleCXXCtor(D, Type, Context, Out); 410191783Srmacklem 411191783Srmacklem Name += '\0'; 412191783Srmacklem return UniqueMangledName(Name.begin(), Name.end()); 413191783Srmacklem} 414191783Srmacklem 415191783Srmacklemvoid CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) { 416191783Srmacklem if (!canGenerateCXXstructor(D->getParent(), getContext())) { 417191783Srmacklem ErrorUnsupported(D, "C++ destructor", true); 418244042Srmacklem return; 419191783Srmacklem } 420222719Srmacklem 421191783Srmacklem EmitCXXDestructor(D, Dtor_Complete); 422191783Srmacklem EmitCXXDestructor(D, Dtor_Base); 423222719Srmacklem} 424191783Srmacklem 425191783Srmacklemvoid CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, 426191783Srmacklem CXXDtorType Type) { 427191783Srmacklem llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type); 428191783Srmacklem 429191783Srmacklem CodeGenFunction(*this).GenerateCode(D, Fn); 430191783Srmacklem 431191783Srmacklem SetFunctionDefinitionAttributes(D, Fn); 432191783Srmacklem SetLLVMFunctionAttributesForDefinition(D, Fn); 433244042Srmacklem} 434191783Srmacklem 435227760Srmacklemllvm::Function * 436227760SrmacklemCodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, 437191783Srmacklem CXXDtorType Type) { 438191783Srmacklem const llvm::FunctionType *FTy = 439191783Srmacklem getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 440191783Srmacklem 441191783Srmacklem const char *Name = getMangledCXXDtorName(D, Type); 442191783Srmacklem return cast<llvm::Function>( 443244042Srmacklem GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 444244042Srmacklem} 445244042Srmacklem 446244042Srmacklemconst char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, 447244042Srmacklem CXXDtorType Type) { 448244042Srmacklem llvm::SmallString<256> Name; 449244042Srmacklem llvm::raw_svector_ostream Out(Name); 450244042Srmacklem mangleCXXDtor(D, Type, Context, Out); 451244042Srmacklem 452244042Srmacklem Name += '\0'; 453244042Srmacklem return UniqueMangledName(Name.begin(), Name.end()); 454244042Srmacklem} 455244042Srmacklem