diff options
Diffstat (limited to 'lib/CodeGen')
43 files changed, 11437 insertions, 5312 deletions
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h index 58e5a778cf33c..1ab2f55295fa0 100644 --- a/lib/CodeGen/ABIInfo.h +++ b/lib/CodeGen/ABIInfo.h @@ -17,6 +17,7 @@ namespace llvm { class Type; class Value; + class LLVMContext; } namespace clang { @@ -71,11 +72,12 @@ namespace clang { Kind TheKind; const llvm::Type *TypeData; unsigned UIntData; + bool BoolData; ABIArgInfo(Kind K, const llvm::Type *TD=0, - unsigned UI=0) : TheKind(K), - TypeData(TD), - UIntData(UI) {} + unsigned UI=0, bool B = false) + : TheKind(K), TypeData(TD), UIntData(UI), BoolData(B) {} + public: ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {} @@ -91,8 +93,8 @@ namespace clang { static ABIArgInfo getCoerce(const llvm::Type *T) { return ABIArgInfo(Coerce, T); } - static ABIArgInfo getIndirect(unsigned Alignment) { - return ABIArgInfo(Indirect, 0, Alignment); + static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true) { + return ABIArgInfo(Indirect, 0, Alignment, ByVal); } static ABIArgInfo getExpand() { return ABIArgInfo(Expand); @@ -112,12 +114,17 @@ namespace clang { return TypeData; } - // ByVal accessors + // Indirect accessors unsigned getIndirectAlign() const { assert(TheKind == Indirect && "Invalid kind!"); return UIntData; } + bool getIndirectByVal() const { + assert(TheKind == Indirect && "Invalid kind!"); + return BoolData; + } + void dump() const; }; @@ -128,7 +135,8 @@ namespace clang { virtual ~ABIInfo(); virtual void computeInfo(CodeGen::CGFunctionInfo &FI, - ASTContext &Ctx) const = 0; + ASTContext &Ctx, + llvm::LLVMContext &VMContext) const = 0; /// EmitVAArg - Emit the target dependent code to load a value of /// \arg Ty from the va_list pointed to by \arg VAListAddr. diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index d5f803ba98bfd..736425e01276c 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -11,12 +11,15 @@ // //===----------------------------------------------------------------------===// +#include "CGDebugInfo.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "clang/AST/DeclObjC.h" #include "llvm/Module.h" #include "llvm/Target/TargetData.h" #include <algorithm> +#include <cstdio> + using namespace clang; using namespace CodeGen; @@ -48,24 +51,24 @@ BuildDescriptorBlockDecl(bool BlockHasCopyDispose, uint64_t Size, Elts.push_back(BuildDestroyHelper(Ty, NoteForHelper)); } - C = llvm::ConstantStruct::get(Elts); + C = llvm::ConstantStruct::get(VMContext, Elts, false); - C = new llvm::GlobalVariable(C->getType(), true, + C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, llvm::GlobalValue::InternalLinkage, - C, "__block_descriptor_tmp", &CGM.getModule()); + C, "__block_descriptor_tmp"); return C; } llvm::Constant *BlockModule::getNSConcreteGlobalBlock() { if (NSConcreteGlobalBlock == 0) - NSConcreteGlobalBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty, + NSConcreteGlobalBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty, "_NSConcreteGlobalBlock"); return NSConcreteGlobalBlock; } llvm::Constant *BlockModule::getNSConcreteStackBlock() { if (NSConcreteStackBlock == 0) - NSConcreteStackBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty, + NSConcreteStackBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty, "_NSConcreteStackBlock"); return NSConcreteStackBlock; } @@ -125,7 +128,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls; bool subBlockHasCopyDispose = false; llvm::Function *Fn - = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, CurFuncDecl, LocalDeclMap, + = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, CurFuncDecl, + LocalDeclMap, subBlockSize, subBlockAlign, subBlockDeclRefDecls, @@ -161,13 +165,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { Elts[0] = CGM.getNSConcreteGlobalBlock(); Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL); - C = llvm::ConstantStruct::get(Elts); + C = llvm::ConstantStruct::get(VMContext, Elts, false); char Name[32]; sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount()); - C = new llvm::GlobalVariable(C->getType(), true, + C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, llvm::GlobalValue::InternalLinkage, - C, Name, &CGM.getModule()); + C, Name); QualType BPT = BE->getType(); C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT)); return C; @@ -183,13 +187,12 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); QualType Ty = E->getType(); if (BDRE && BDRE->isByRef()) { - uint64_t Align = getContext().getDeclAlignInBytes(BDRE->getDecl()); - Types[i+5] = llvm::PointerType::get(BuildByRefType(Ty, Align), 0); + Types[i+5] = llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0); } else Types[i+5] = ConvertType(Ty); } - llvm::StructType *Ty = llvm::StructType::get(Types, true); + llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true); llvm::AllocaInst *A = CreateTempAlloca(Ty); A->setAlignment(subBlockAlign); @@ -217,20 +220,21 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp"); NoteForHelper[helpersize].index = i+5; - NoteForHelper[helpersize].RequiresCopying = BlockRequiresCopying(VD->getType()); + NoteForHelper[helpersize].RequiresCopying + = BlockRequiresCopying(VD->getType()); NoteForHelper[helpersize].flag - = VD->getType()->isBlockPointerType() ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT; + = (VD->getType()->isBlockPointerType() + ? BLOCK_FIELD_IS_BLOCK + : BLOCK_FIELD_IS_OBJECT); if (LocalDeclMap[VD]) { if (BDRE->isByRef()) { NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF | // FIXME: Someone double check this. (VD->getType().isObjCGCWeak() ? BLOCK_FIELD_IS_WEAK : 0); - const llvm::Type *Ty = Types[i+5]; llvm::Value *Loc = LocalDeclMap[VD]; Loc = Builder.CreateStructGEP(Loc, 1, "forwarding"); Loc = Builder.CreateLoad(Loc, false); - Loc = Builder.CreateBitCast(Loc, Ty); Builder.CreateStore(Loc, Addr); ++helpersize; continue; @@ -265,7 +269,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { llvm::Value *BlockLiteral = LoadBlockStruct(); Loc = Builder.CreateGEP(BlockLiteral, - llvm::ConstantInt::get(llvm::Type::Int64Ty, + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), offset), "block.literal"); Ty = llvm::PointerType::get(Ty, 0); @@ -310,7 +314,8 @@ const llvm::Type *BlockModule::getBlockDescriptorType() { // unsigned long reserved; // unsigned long block_size; // }; - BlockDescriptorType = llvm::StructType::get(UnsignedLongTy, + BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(), + UnsignedLongTy, UnsignedLongTy, NULL); @@ -337,7 +342,8 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() { // void (*__invoke)(void *); // struct __block_descriptor *__descriptor; // }; - GenericBlockLiteralType = llvm::StructType::get(PtrToInt8Ty, + GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(), + PtrToInt8Ty, IntTy, IntTy, PtrToInt8Ty, @@ -369,7 +375,8 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() { // void *__copy_func_helper_decl; // void *__destroy_func_decl; // }; - GenericExtendedBlockLiteralType = llvm::StructType::get(PtrToInt8Ty, + GenericExtendedBlockLiteralType = llvm::StructType::get(IntTy->getContext(), + PtrToInt8Ty, IntTy, IntTy, PtrToInt8Ty, @@ -384,9 +391,13 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() { return GenericExtendedBlockLiteralType; } +bool BlockFunction::BlockRequiresCopying(QualType Ty) { + return CGM.BlockRequiresCopying(Ty); +} + RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { const BlockPointerType *BPT = - E->getCallee()->getType()->getAsBlockPointerType(); + E->getCallee()->getType()->getAs<BlockPointerType>(); llvm::Value *Callee = EmitScalarExpr(E->getCallee()); @@ -403,7 +414,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { BlockLiteral = Builder.CreateBitCast(BlockLiteral, - llvm::PointerType::getUnqual(llvm::Type::Int8Ty), + llvm::Type::getInt8PtrTy(VMContext), "tmp"); // Add the block literal. @@ -414,33 +425,33 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { QualType FnType = BPT->getPointeeType(); // And the rest of the arguments. - EmitCallArgs(Args, FnType->getAsFunctionProtoType(), + EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arg_begin(), E->arg_end()); // Load the function. llvm::Value *Func = Builder.CreateLoad(FuncPtr, false, "tmp"); - QualType ResultType = FnType->getAsFunctionType()->getResultType(); + QualType ResultType = FnType->getAs<FunctionType>()->getResultType(); - const CGFunctionInfo &FnInfo = + const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(ResultType, Args); - + // Cast the function pointer to the right type. - const llvm::Type *BlockFTy = + const llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo, false); - + const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); Func = Builder.CreateBitCast(Func, BlockFTyPtr); - + // And call the block. return EmitCall(FnInfo, Func, Args); } llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { - uint64_t &offset = BlockDecls[E->getDecl()]; + const ValueDecl *VD = E->getDecl(); + + uint64_t &offset = BlockDecls[VD]; - const llvm::Type *Ty; - Ty = CGM.getTypes().ConvertType(E->getDecl()->getType()); // See if we have already allocated an offset for this variable. if (offset == 0) { @@ -453,25 +464,27 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { llvm::Value *BlockLiteral = LoadBlockStruct(); llvm::Value *V = Builder.CreateGEP(BlockLiteral, - llvm::ConstantInt::get(llvm::Type::Int64Ty, - offset), + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + offset), "block.literal"); if (E->isByRef()) { - bool needsCopyDispose = BlockRequiresCopying(E->getType()); - uint64_t Align = getContext().getDeclAlignInBytes(E->getDecl()); const llvm::Type *PtrStructTy - = llvm::PointerType::get(BuildByRefType(E->getType(), Align), 0); + = llvm::PointerType::get(BuildByRefType(VD), 0); // The block literal will need a copy/destroy helper. BlockHasCopyDispose = true; - Ty = PtrStructTy; + + const llvm::Type *Ty = PtrStructTy; Ty = llvm::PointerType::get(Ty, 0); V = Builder.CreateBitCast(V, Ty); V = Builder.CreateLoad(V, false); V = Builder.CreateStructGEP(V, 1, "forwarding"); V = Builder.CreateLoad(V, false); V = Builder.CreateBitCast(V, PtrStructTy); - V = Builder.CreateStructGEP(V, needsCopyDispose*2 + 4, "x"); + V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD), + VD->getNameAsString()); } else { + const llvm::Type *Ty = CGM.getTypes().ConvertType(VD->getType()); + Ty = llvm::PointerType::get(Ty, 0); V = Builder.CreateBitCast(V, Ty); } @@ -507,16 +520,16 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { // block literal struct. uint64_t BlockLiteralSize = TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8; - DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize); + DescriptorFields[1] = + llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize); llvm::Constant *DescriptorStruct = - llvm::ConstantStruct::get(&DescriptorFields[0], 2); + llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 2, false); llvm::GlobalVariable *Descriptor = - new llvm::GlobalVariable(DescriptorStruct->getType(), true, + new llvm::GlobalVariable(getModule(), DescriptorStruct->getType(), true, llvm::GlobalVariable::InternalLinkage, - DescriptorStruct, "__block_descriptor_global", - &getModule()); + DescriptorStruct, "__block_descriptor_global"); // Generate the constants for the block literal. llvm::Constant *LiteralFields[5]; @@ -552,13 +565,12 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { LiteralFields[4] = Descriptor; llvm::Constant *BlockLiteralStruct = - llvm::ConstantStruct::get(&LiteralFields[0], 5); + llvm::ConstantStruct::get(VMContext, &LiteralFields[0], 5, false); llvm::GlobalVariable *BlockLiteral = - new llvm::GlobalVariable(BlockLiteralStruct->getType(), true, + new llvm::GlobalVariable(getModule(), BlockLiteralStruct->getType(), true, llvm::GlobalVariable::InternalLinkage, - BlockLiteralStruct, "__block_literal_global", - &getModule()); + BlockLiteralStruct, "__block_literal_global"); return BlockLiteral; } @@ -580,7 +592,7 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, // Check if we should generate debug info for this block. if (CGM.getDebugInfo()) DebugInfo = CGM.getDebugInfo(); - + // Arrange for local static and local extern declarations to appear // to be local to this function as well, as they are directly referenced // in a block. @@ -588,7 +600,7 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, i != ldm.end(); ++i) { const VarDecl *VD = dyn_cast<VarDecl>(i->first); - + if (VD->getStorageClass() == VarDecl::Static || VD->hasExternalStorage()) LocalDeclMap[VD] = i->second; } @@ -606,12 +618,11 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, const FunctionType *BlockFunctionType = BExpr->getFunctionType(); QualType ResultType; bool IsVariadic; - if (const FunctionProtoType *FTy = + if (const FunctionProtoType *FTy = dyn_cast<FunctionProtoType>(BlockFunctionType)) { ResultType = FTy->getResultType(); IsVariadic = FTy->isVariadic(); - } - else { + } else { // K&R style block. ResultType = BlockFunctionType->getResultType(); IsVariadic = false; @@ -650,9 +661,44 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, StartFunction(BD, ResultType, Fn, Args, BExpr->getBody()->getLocEnd()); + CurFuncDecl = OuterFuncDecl; CurCodeDecl = BD; + + // Save a spot to insert the debug information for all the BlockDeclRefDecls. + llvm::BasicBlock *entry = Builder.GetInsertBlock(); + llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); + --entry_ptr; + EmitStmt(BExpr->getBody()); + + // Remember where we were... + llvm::BasicBlock *resume = Builder.GetInsertBlock(); + + // Go back to the entry. + ++entry_ptr; + Builder.SetInsertPoint(entry, entry_ptr); + + if (CGDebugInfo *DI = getDebugInfo()) { + // Emit debug information for all the BlockDeclRefDecls. + for (unsigned i=0; i < BlockDeclRefDecls.size(); ++i) { + const Expr *E = BlockDeclRefDecls[i]; + const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); + if (BDRE) { + const ValueDecl *D = BDRE->getDecl(); + DI->setLocation(D->getLocation()); + DI->EmitDeclareOfBlockDeclRefVariable(BDRE, + LocalDeclMap[getBlockStructDecl()], + Builder, this); + } + } + } + // And resume where we left off. + if (resume == 0) + Builder.ClearInsertionPoint(); + else + Builder.SetInsertPoint(resume); + FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc()); // The runtime needs a minimum alignment of a void *. @@ -687,13 +733,12 @@ uint64_t BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { uint64_t Pad = BlockOffset - OldOffset; if (Pad) { - llvm::ArrayType::get(llvm::Type::Int8Ty, Pad); + llvm::ArrayType::get(llvm::Type::getInt8Ty(VMContext), Pad); QualType PadTy = getContext().getConstantArrayType(getContext().CharTy, llvm::APInt(32, Pad), ArrayType::Normal, 0); ValueDecl *PadDecl = VarDecl::Create(getContext(), 0, SourceLocation(), - 0, QualType(PadTy), VarDecl::None, - SourceLocation()); + 0, QualType(PadTy), 0, VarDecl::None); Expr *E; E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(), SourceLocation(), false, false); @@ -720,7 +765,7 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T, ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); - + const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args); @@ -740,7 +785,7 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T, FunctionDecl *FD = FunctionDecl::Create(getContext(), getContext().getTranslationUnitDecl(), - SourceLocation(), II, R, + SourceLocation(), II, R, 0, FunctionDecl::Static, false, true); CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -776,7 +821,8 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T, llvm::Value *Dstv = Builder.CreateStructGEP(DstObj, index); Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty); - llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag); + llvm::Value *N = llvm::ConstantInt::get( + llvm::Type::getInt32Ty(T->getContext()), flag); llvm::Value *F = getBlockObjectAssign(); Builder.CreateCall3(F, Dstv, Srcv, N); } @@ -801,7 +847,7 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); - + const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args); @@ -821,7 +867,7 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose, FunctionDecl *FD = FunctionDecl::Create(getContext(), getContext().getTranslationUnitDecl(), - SourceLocation(), II, R, + SourceLocation(), II, R, 0, FunctionDecl::Static, false, true); CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -885,7 +931,7 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); - + const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args); @@ -905,7 +951,7 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { FunctionDecl *FD = FunctionDecl::Create(getContext(), getContext().getTranslationUnitDecl(), - SourceLocation(), II, R, + SourceLocation(), II, R, 0, FunctionDecl::Static, false, true); CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -924,10 +970,11 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { V = Builder.CreateStructGEP(V, 6, "x"); V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0)); llvm::Value *SrcObj = Builder.CreateLoad(V); - + flag |= BLOCK_BYREF_CALLER; - llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag); + llvm::Value *N = llvm::ConstantInt::get( + llvm::Type::getInt32Ty(T->getContext()), flag); llvm::Value *F = getBlockObjectAssign(); Builder.CreateCall3(F, DstObj, SrcObj, N); @@ -948,7 +995,7 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); - + const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args); @@ -968,7 +1015,7 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, FunctionDecl *FD = FunctionDecl::Create(getContext(), getContext().getTranslationUnitDecl(), - SourceLocation(), II, R, + SourceLocation(), II, R, 0, FunctionDecl::Static, false, true); CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -1024,9 +1071,9 @@ llvm::Value *BlockFunction::getBlockObjectDispose() { if (CGM.BlockObjectDispose == 0) { const llvm::FunctionType *FTy; std::vector<const llvm::Type*> ArgTys; - const llvm::Type *ResultType = llvm::Type::VoidTy; + const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); ArgTys.push_back(PtrToInt8Ty); - ArgTys.push_back(llvm::Type::Int32Ty); + ArgTys.push_back(llvm::Type::getInt32Ty(VMContext)); FTy = llvm::FunctionType::get(ResultType, ArgTys, false); CGM.BlockObjectDispose = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose"); @@ -1038,10 +1085,10 @@ llvm::Value *BlockFunction::getBlockObjectAssign() { if (CGM.BlockObjectAssign == 0) { const llvm::FunctionType *FTy; std::vector<const llvm::Type*> ArgTys; - const llvm::Type *ResultType = llvm::Type::VoidTy; + const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); ArgTys.push_back(PtrToInt8Ty); ArgTys.push_back(PtrToInt8Ty); - ArgTys.push_back(llvm::Type::Int32Ty); + ArgTys.push_back(llvm::Type::getInt32Ty(VMContext)); FTy = llvm::FunctionType::get(ResultType, ArgTys, false); CGM.BlockObjectAssign = CGM.CreateRuntimeFunction(FTy, "_Block_object_assign"); @@ -1053,7 +1100,7 @@ void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) { llvm::Value *F = getBlockObjectDispose(); llvm::Value *N; V = Builder.CreateBitCast(V, PtrToInt8Ty); - N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag); + N = llvm::ConstantInt::get(llvm::Type::getInt32Ty(V->getContext()), flag); Builder.CreateCall2(F, V, N); } @@ -1061,8 +1108,9 @@ ASTContext &BlockFunction::getContext() const { return CGM.getContext(); } BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B) - : CGM(cgm), CGF(cgf), Builder(B) { - PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + : CGM(cgm), CGF(cgf), VMContext(cgm.getLLVMContext()), Builder(B) { + PtrToInt8Ty = llvm::PointerType::getUnqual( + llvm::Type::getInt8Ty(VMContext)); BlockHasCopyDispose = false; } diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 5d46ac78f693e..3a860c0d3c369 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -16,6 +16,7 @@ #include "CodeGenTypes.h" #include "clang/AST/Type.h" +#include "llvm/Module.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "clang/Basic/TargetInfo.h" @@ -38,6 +39,7 @@ namespace llvm { class TargetData; class FunctionType; class Value; + class LLVMContext; } namespace clang { @@ -63,7 +65,8 @@ class BlockModule : public BlockBase { const llvm::TargetData &TheTargetData; CodeGenTypes &Types; CodeGenModule &CGM; - + llvm::LLVMContext &VMContext; + ASTContext &getContext() const { return Context; } llvm::Module &getModule() const { return TheModule; } CodeGenTypes &getTypes() { return Types; } @@ -86,7 +89,7 @@ public: /// NSConcreteStackBlock - Cached reference to the class poinnter for stack /// blocks. llvm::Constant *NSConcreteStackBlock; - + const llvm::Type *BlockDescriptorType; const llvm::Type *GenericBlockLiteralType; const llvm::Type *GenericExtendedBlockLiteralType; @@ -104,12 +107,22 @@ public: BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD, CodeGenTypes &T, CodeGenModule &CodeGen) : Context(C), TheModule(M), TheTargetData(TD), Types(T), - CGM(CodeGen), + CGM(CodeGen), VMContext(M.getContext()), NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0), GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0), BlockObjectAssign(0), BlockObjectDispose(0) { Block.GlobalUniqueCount = 0; - PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext()); + } + + bool BlockRequiresCopying(QualType Ty) { + if (Ty->isBlockPointerType()) + return true; + if (getContext().isObjCNSObjectType(Ty)) + return true; + if (Ty->isObjCObjectPointerType()) + return true; + return false; } }; @@ -118,6 +131,9 @@ class BlockFunction : public BlockBase { CodeGenFunction &CGF; ASTContext &getContext() const; +protected: + llvm::LLVMContext &VMContext; + public: const llvm::Type *PtrToInt8Ty; struct HelperInfo { @@ -150,11 +166,11 @@ public: /// ByCopyDeclRefs - Variables from parent scopes that have been imported /// into this block. llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs; - - // ByRefDeclRefs - __block variables from parent scopes that have been + + // ByRefDeclRefs - __block variables from parent scopes that have been // imported into this block. llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs; - + BlockInfo(const llvm::Type *blt, const char *n) : BlockLiteralTy(blt), Name(n) { // Skip asm prefix, if any. @@ -212,15 +228,7 @@ public: llvm::Value *getBlockObjectDispose(); void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF); - bool BlockRequiresCopying(QualType Ty) { - if (Ty->isBlockPointerType()) - return true; - if (getContext().isObjCNSObjectType(Ty)) - return true; - if (getContext().isObjCObjectPointerType(Ty)) - return true; - return false; - } + bool BlockRequiresCopying(QualType Ty); }; } // end namespace CodeGen diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index a919dfa2e32cf..987cd24e2c8b5 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -25,21 +25,21 @@ using namespace llvm; /// Utility to insert an atomic instruction based on Instrinsic::ID /// and the expression node. -static RValue EmitBinaryAtomic(CodeGenFunction& CGF, +static RValue EmitBinaryAtomic(CodeGenFunction& CGF, Intrinsic::ID Id, const CallExpr *E) { const llvm::Type *ResType[2]; ResType[0] = CGF.ConvertType(E->getType()); ResType[1] = CGF.ConvertType(E->getArg(0)->getType()); Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2); - return RValue::get(CGF.Builder.CreateCall2(AtomF, - CGF.EmitScalarExpr(E->getArg(0)), + return RValue::get(CGF.Builder.CreateCall2(AtomF, + CGF.EmitScalarExpr(E->getArg(0)), CGF.EmitScalarExpr(E->getArg(1)))); } /// Utility to insert an atomic instruction based Instrinsic::ID and // the expression node, where the return value is the result of the // operation. -static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF, +static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF, Intrinsic::ID Id, const CallExpr *E, Instruction::BinaryOps Op) { const llvm::Type *ResType[2]; @@ -49,25 +49,26 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF, Value *Ptr = CGF.EmitScalarExpr(E->getArg(0)); Value *Operand = CGF.EmitScalarExpr(E->getArg(1)); Value *Result = CGF.Builder.CreateCall2(AtomF, Ptr, Operand); - + if (Id == Intrinsic::atomic_load_nand) Result = CGF.Builder.CreateNot(Result); - - + + return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Operand)); } -RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, +RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E) { // See if we can constant fold this builtin. If so, don't emit it at all. Expr::EvalResult Result; if (E->Evaluate(Result, CGM.getContext())) { if (Result.Val.isInt()) - return RValue::get(llvm::ConstantInt::get(Result.Val.getInt())); + return RValue::get(llvm::ConstantInt::get(VMContext, + Result.Val.getInt())); else if (Result.Val.isFloat()) - return RValue::get(llvm::ConstantFP::get(Result.Val.getFloat())); + return RValue::get(ConstantFP::get(VMContext, Result.Val.getFloat())); } - + switch (BuiltinID) { default: break; // Handle intrinsics and libm functions below. case Builtin::BI__builtin___CFStringMakeConstantString: @@ -76,13 +77,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_va_start: case Builtin::BI__builtin_va_end: { Value *ArgValue = EmitVAListRef(E->getArg(0)); - const llvm::Type *DestType = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext); if (ArgValue->getType() != DestType) - ArgValue = Builder.CreateBitCast(ArgValue, DestType, - ArgValue->getNameStart()); + ArgValue = Builder.CreateBitCast(ArgValue, DestType, + ArgValue->getName().data()); - Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ? + Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ? Intrinsic::vaend : Intrinsic::vastart; return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue)); } @@ -90,35 +90,35 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *DstPtr = EmitVAListRef(E->getArg(0)); Value *SrcPtr = EmitVAListRef(E->getArg(1)); - const llvm::Type *Type = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext); DstPtr = Builder.CreateBitCast(DstPtr, Type); SrcPtr = Builder.CreateBitCast(SrcPtr, Type); - return RValue::get(Builder.CreateCall2(CGM.getIntrinsic(Intrinsic::vacopy), + return RValue::get(Builder.CreateCall2(CGM.getIntrinsic(Intrinsic::vacopy), DstPtr, SrcPtr)); } case Builtin::BI__builtin_abs: { - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - + Value *ArgValue = EmitScalarExpr(E->getArg(0)); + Value *NegOp = Builder.CreateNeg(ArgValue, "neg"); - Value *CmpResult = - Builder.CreateICmpSGE(ArgValue, Constant::getNullValue(ArgValue->getType()), + Value *CmpResult = + Builder.CreateICmpSGE(ArgValue, + llvm::Constant::getNullValue(ArgValue->getType()), "abscond"); - Value *Result = + Value *Result = Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs"); - + return RValue::get(Result); } case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: { Value *ArgValue = EmitScalarExpr(E->getArg(0)); - + const llvm::Type *ArgType = ArgValue->getType(); Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1); - const llvm::Type *ResultType = ConvertType(E->getType()); + const llvm::Type *ResultType = ConvertType(E->getType()); Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); if (Result->getType() != ResultType) Result = Builder.CreateIntCast(Result, ResultType, "cast"); @@ -128,11 +128,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_clzl: case Builtin::BI__builtin_clzll: { Value *ArgValue = EmitScalarExpr(E->getArg(0)); - + const llvm::Type *ArgType = ArgValue->getType(); Value *F = CGM.getIntrinsic(Intrinsic::ctlz, &ArgType, 1); - const llvm::Type *ResultType = ConvertType(E->getType()); + const llvm::Type *ResultType = ConvertType(E->getType()); Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); if (Result->getType() != ResultType) Result = Builder.CreateIntCast(Result, ResultType, "cast"); @@ -143,13 +143,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_ffsll: { // ffs(x) -> x ? cttz(x) + 1 : 0 Value *ArgValue = EmitScalarExpr(E->getArg(0)); - + const llvm::Type *ArgType = ArgValue->getType(); Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1); - + const llvm::Type *ResultType = ConvertType(E->getType()); - Value *Tmp = Builder.CreateAdd(Builder.CreateCall(F, ArgValue, "tmp"), - ConstantInt::get(ArgType, 1), "tmp"); + Value *Tmp = Builder.CreateAdd(Builder.CreateCall(F, ArgValue, "tmp"), + llvm::ConstantInt::get(ArgType, 1), "tmp"); Value *Zero = llvm::Constant::getNullValue(ArgType); Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero"); Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs"); @@ -162,13 +162,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_parityll: { // parity(x) -> ctpop(x) & 1 Value *ArgValue = EmitScalarExpr(E->getArg(0)); - + const llvm::Type *ArgType = ArgValue->getType(); Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1); - + const llvm::Type *ResultType = ConvertType(E->getType()); Value *Tmp = Builder.CreateCall(F, ArgValue, "tmp"); - Value *Result = Builder.CreateAnd(Tmp, ConstantInt::get(ArgType, 1), + Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1), "tmp"); if (Result->getType() != ResultType) Result = Builder.CreateIntCast(Result, ResultType, "cast"); @@ -178,10 +178,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_popcountl: case Builtin::BI__builtin_popcountll: { Value *ArgValue = EmitScalarExpr(E->getArg(0)); - + const llvm::Type *ArgType = ArgValue->getType(); Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1); - + const llvm::Type *ResultType = ConvertType(E->getType()); Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); if (Result->getType() != ResultType) @@ -197,7 +197,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, const llvm::Type *ArgType = ArgValue->getType(); Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1); return RValue::get(Builder.CreateCall(F, ArgValue, "tmp")); - } + } case Builtin::BI__builtin_object_size: { // FIXME: Implement. For now we just always fail and pretend we // don't know the object size. @@ -205,15 +205,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, const llvm::Type *ResType = ConvertType(E->getType()); // bool UseSubObject = TypeArg.getZExtValue() & 1; bool UseMinimum = TypeArg.getZExtValue() & 2; - return RValue::get(ConstantInt::get(ResType, UseMinimum ? 0 : -1LL)); + return RValue::get( + llvm::ConstantInt::get(ResType, UseMinimum ? 0 : -1LL)); } case Builtin::BI__builtin_prefetch: { Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); // FIXME: Technically these constants should of type 'int', yes? - RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) : - ConstantInt::get(llvm::Type::Int32Ty, 0); - Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : - ConstantInt::get(llvm::Type::Int32Ty, 3); + RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) : + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0); + Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 3); Value *F = CGM.getIntrinsic(Intrinsic::prefetch, 0, 0); return RValue::get(Builder.CreateCall3(F, Address, RW, Locality)); } @@ -221,7 +222,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *F = CGM.getIntrinsic(Intrinsic::trap, 0, 0); return RValue::get(Builder.CreateCall(F)); } - + case Builtin::BI__builtin_unreachable: { + Value *V = Builder.CreateUnreachable(); + Builder.ClearInsertionPoint(); + return RValue::get(V); + } + case Builtin::BI__builtin_powi: case Builtin::BI__builtin_powif: case Builtin::BI__builtin_powil: { @@ -240,9 +246,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_isunordered: { // Ordered comparisons: we know the arguments to these are matching scalar // floating point values. - Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *LHS = EmitScalarExpr(E->getArg(0)); Value *RHS = EmitScalarExpr(E->getArg(1)); - + switch (BuiltinID) { default: assert(0 && "Unknown ordered comparison"); case Builtin::BI__builtin_isgreater: @@ -260,7 +266,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_islessgreater: LHS = Builder.CreateFCmpONE(LHS, RHS, "cmp"); break; - case Builtin::BI__builtin_isunordered: + case Builtin::BI__builtin_isunordered: LHS = Builder.CreateFCmpUNO(LHS, RHS, "cmp"); break; } @@ -268,19 +274,24 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType()), "tmp")); } + case Builtin::BI__builtin_isnan: { + Value *V = EmitScalarExpr(E->getArg(0)); + V = Builder.CreateFCmpUNO(V, V, "cmp"); + return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp")); + } case Builtin::BIalloca: case Builtin::BI__builtin_alloca: { // FIXME: LLVM IR Should allow alloca with an i64 size! Value *Size = EmitScalarExpr(E->getArg(0)); - Size = Builder.CreateIntCast(Size, llvm::Type::Int32Ty, false, "tmp"); - return RValue::get(Builder.CreateAlloca(llvm::Type::Int8Ty, Size, "tmp")); + Size = Builder.CreateIntCast(Size, llvm::Type::getInt32Ty(VMContext), false, "tmp"); + return RValue::get(Builder.CreateAlloca(llvm::Type::getInt8Ty(VMContext), Size, "tmp")); } case Builtin::BI__builtin_bzero: { Value *Address = EmitScalarExpr(E->getArg(0)); Builder.CreateCall4(CGM.getMemSetFn(), Address, - llvm::ConstantInt::get(llvm::Type::Int8Ty, 0), + llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0), EmitScalarExpr(E->getArg(1)), - llvm::ConstantInt::get(llvm::Type::Int32Ty, 1)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); return RValue::get(Address); } case Builtin::BI__builtin_memcpy: { @@ -288,7 +299,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Builder.CreateCall4(CGM.getMemCpyFn(), Address, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), - llvm::ConstantInt::get(llvm::Type::Int32Ty, 1)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); return RValue::get(Address); } case Builtin::BI__builtin_memmove: { @@ -296,16 +307,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Builder.CreateCall4(CGM.getMemMoveFn(), Address, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)), - llvm::ConstantInt::get(llvm::Type::Int32Ty, 1)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); return RValue::get(Address); } case Builtin::BI__builtin_memset: { Value *Address = EmitScalarExpr(E->getArg(0)); Builder.CreateCall4(CGM.getMemSetFn(), Address, Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), - llvm::Type::Int8Ty), + llvm::Type::getInt8Ty(VMContext)), EmitScalarExpr(E->getArg(2)), - llvm::ConstantInt::get(llvm::Type::Int32Ty, 1)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); return RValue::get(Address); } case Builtin::BI__builtin_return_address: { @@ -332,20 +343,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *FrameAddrF = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0); Value *FrameAddr = Builder.CreateCall(FrameAddrF, - Constant::getNullValue(llvm::Type::Int32Ty)); + Constant::getNullValue(llvm::Type::getInt32Ty(VMContext))); Builder.CreateStore(FrameAddr, Buf); // Call the setjmp intrinsic Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp, 0, 0); - const llvm::Type *DestType = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext); Buf = Builder.CreateBitCast(Buf, DestType); return RValue::get(Builder.CreateCall(F, Buf)); } case Builtin::BI__builtin_longjmp: { Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_longjmp, 0, 0); Value *Buf = EmitScalarExpr(E->getArg(0)); - const llvm::Type *DestType = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext); Buf = Builder.CreateBitCast(Buf, DestType); return RValue::get(Builder.CreateCall(F, Buf)); } @@ -401,7 +410,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_fetch_and_nand_8: case Builtin::BI__sync_fetch_and_nand_16: return EmitBinaryAtomic(*this, Intrinsic::atomic_load_nand, E); - + // Clang extensions: not overloaded yet. case Builtin::BI__sync_fetch_and_min: return EmitBinaryAtomic(*this, Intrinsic::atomic_load_min, E); @@ -417,7 +426,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_add_and_fetch_4: case Builtin::BI__sync_add_and_fetch_8: case Builtin::BI__sync_add_and_fetch_16: - return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_add, E, + return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_add, E, llvm::Instruction::Add); case Builtin::BI__sync_sub_and_fetch_1: case Builtin::BI__sync_sub_and_fetch_2: @@ -454,7 +463,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_nand_and_fetch_16: return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_nand, E, llvm::Instruction::And); - + case Builtin::BI__sync_val_compare_and_swap_1: case Builtin::BI__sync_val_compare_and_swap_2: case Builtin::BI__sync_val_compare_and_swap_4: @@ -465,7 +474,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, ResType[0]= ConvertType(E->getType()); ResType[1] = ConvertType(E->getArg(0)->getType()); Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2); - return RValue::get(Builder.CreateCall3(AtomF, + return RValue::get(Builder.CreateCall3(AtomF, EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2)))); @@ -482,7 +491,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, ResType[1] = llvm::PointerType::getUnqual(ResType[0]); Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2); Value *OldVal = EmitScalarExpr(E->getArg(1)); - Value *PrevVal = Builder.CreateCall3(AtomF, + Value *PrevVal = Builder.CreateCall3(AtomF, EmitScalarExpr(E->getArg(0)), OldVal, EmitScalarExpr(E->getArg(2))); @@ -511,12 +520,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_synchronize: { Value *C[5]; - C[0] = C[1] = C[2] = C[3] = llvm::ConstantInt::get(llvm::Type::Int1Ty, 1); - C[4] = ConstantInt::get(llvm::Type::Int1Ty, 0); + C[0] = C[1] = C[2] = C[3] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 1); + C[4] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::memory_barrier), C, C + 5); return RValue::get(0); } - + // Library functions with special handling. case Builtin::BIsqrt: case Builtin::BIsqrtf: @@ -543,29 +552,31 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp")); } } - + // If this is an alias for a libm function (e.g. __builtin_sin) turn it into // that function. if (getContext().BuiltinInfo.isLibFunction(BuiltinID) || getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return EmitCall(CGM.getBuiltinLibFunction(BuiltinID), + return EmitCall(CGM.getBuiltinLibFunction(FD, BuiltinID), E->getCallee()->getType(), E->arg_begin(), E->arg_end()); - + // See if we have a target specific intrinsic. const char *Name = getContext().BuiltinInfo.GetName(BuiltinID); - Intrinsic::ID IntrinsicID = - Intrinsic::getIntrinsicForGCCBuiltin(Target.getTargetPrefix(), Name); - + Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic; + if (const char *Prefix = + llvm::Triple::getArchTypePrefix(Target.getTriple().getArch())) + IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name); + if (IntrinsicID != Intrinsic::not_intrinsic) { SmallVector<Value*, 16> Args; - + Function *F = CGM.getIntrinsic(IntrinsicID); const llvm::FunctionType *FTy = F->getFunctionType(); - + for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { Value *ArgValue = EmitScalarExpr(E->getArg(i)); - + // If the intrinsic arg type is different from the builtin arg type // we need to do a bit cast. const llvm::Type *PTy = FTy->getParamType(i); @@ -574,50 +585,54 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, "Must be able to losslessly bit cast to param"); ArgValue = Builder.CreateBitCast(ArgValue, PTy); } - + Args.push_back(ArgValue); } - + Value *V = Builder.CreateCall(F, Args.data(), Args.data() + Args.size()); QualType BuiltinRetType = E->getType(); - - const llvm::Type *RetTy = llvm::Type::VoidTy; + + const llvm::Type *RetTy = llvm::Type::getVoidTy(VMContext); if (!BuiltinRetType->isVoidType()) RetTy = ConvertType(BuiltinRetType); - + if (RetTy != V->getType()) { assert(V->getType()->canLosslesslyBitCastTo(RetTy) && "Must be able to losslessly bit cast result type"); V = Builder.CreateBitCast(V, RetTy); } - + return RValue::get(V); } - + // See if we have a target specific builtin that needs to be lowered. if (Value *V = EmitTargetBuiltinExpr(BuiltinID, E)) return RValue::get(V); - + ErrorUnsupported(E, "builtin function"); - + // Unknown builtin, for now just dump it out and return undef. if (hasAggregateLLVMType(E->getType())) return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType()))); - return RValue::get(UndefValue::get(ConvertType(E->getType()))); -} + return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); +} Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { - const char *TargetPrefix = Target.getTargetPrefix(); - if (strcmp(TargetPrefix, "x86") == 0) + switch (Target.getTriple().getArch()) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: return EmitX86BuiltinExpr(BuiltinID, E); - else if (strcmp(TargetPrefix, "ppc") == 0) + case llvm::Triple::ppc: + case llvm::Triple::ppc64: return EmitPPCBuiltinExpr(BuiltinID, E); - return 0; + default: + return 0; + } } -Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, +Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { - + llvm::SmallVector<Value*, 4> Ops; for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) @@ -625,23 +640,23 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, switch (BuiltinID) { default: return 0; - case X86::BI__builtin_ia32_pslldi128: + case X86::BI__builtin_ia32_pslldi128: case X86::BI__builtin_ia32_psllqi128: - case X86::BI__builtin_ia32_psllwi128: + case X86::BI__builtin_ia32_psllwi128: case X86::BI__builtin_ia32_psradi128: case X86::BI__builtin_ia32_psrawi128: case X86::BI__builtin_ia32_psrldi128: case X86::BI__builtin_ia32_psrlqi128: case X86::BI__builtin_ia32_psrlwi128: { - Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::Int64Ty, "zext"); - const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::Int64Ty, 2); - llvm::Value *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::getInt64Ty(VMContext), "zext"); + const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(VMContext), 2); + llvm::Value *Zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0); Ops[1] = Builder.CreateInsertElement(llvm::UndefValue::get(Ty), Ops[1], Zero, "insert"); Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType(), "bitcast"); const char *name = 0; Intrinsic::ID ID = Intrinsic::not_intrinsic; - + switch (BuiltinID) { default: assert(0 && "Unsupported shift intrinsic!"); case X86::BI__builtin_ia32_pslldi128: @@ -678,22 +693,22 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, break; } llvm::Function *F = CGM.getIntrinsic(ID); - return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); + return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); } - case X86::BI__builtin_ia32_pslldi: + case X86::BI__builtin_ia32_pslldi: case X86::BI__builtin_ia32_psllqi: - case X86::BI__builtin_ia32_psllwi: + case X86::BI__builtin_ia32_psllwi: case X86::BI__builtin_ia32_psradi: case X86::BI__builtin_ia32_psrawi: case X86::BI__builtin_ia32_psrldi: case X86::BI__builtin_ia32_psrlqi: case X86::BI__builtin_ia32_psrlwi: { - Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::Int64Ty, "zext"); - const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::Int64Ty, 1); + Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::getInt64Ty(VMContext), "zext"); + const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(VMContext), 1); Ops[1] = Builder.CreateBitCast(Ops[1], Ty, "bitcast"); const char *name = 0; Intrinsic::ID ID = Intrinsic::not_intrinsic; - + switch (BuiltinID) { default: assert(0 && "Unsupported shift intrinsic!"); case X86::BI__builtin_ia32_pslldi: @@ -730,7 +745,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, break; } llvm::Function *F = CGM.getIntrinsic(ID); - return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); + return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); } case X86::BI__builtin_ia32_cmpps: { llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ps); @@ -741,17 +756,17 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpss"); } case X86::BI__builtin_ia32_ldmxcsr: { - llvm::Type *PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - Value *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); - Value *Tmp = Builder.CreateAlloca(llvm::Type::Int32Ty, One, "tmp"); + const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); + Value *One = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1); + Value *Tmp = Builder.CreateAlloca(llvm::Type::getInt32Ty(VMContext), One, "tmp"); Builder.CreateStore(Ops[0], Tmp); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), Builder.CreateBitCast(Tmp, PtrTy)); } case X86::BI__builtin_ia32_stmxcsr: { - llvm::Type *PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - Value *One = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1); - Value *Tmp = Builder.CreateAlloca(llvm::Type::Int32Ty, One, "tmp"); + const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); + Value *One = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1); + Value *Tmp = Builder.CreateAlloca(llvm::Type::getInt32Ty(VMContext), One, "tmp"); One = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), Builder.CreateBitCast(Tmp, PtrTy)); return Builder.CreateLoad(Tmp, "stmxcsr"); @@ -766,16 +781,16 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } case X86::BI__builtin_ia32_storehps: case X86::BI__builtin_ia32_storelps: { - const llvm::Type *EltTy = llvm::Type::Int64Ty; + const llvm::Type *EltTy = llvm::Type::getInt64Ty(VMContext); llvm::Type *PtrTy = llvm::PointerType::getUnqual(EltTy); llvm::Type *VecTy = llvm::VectorType::get(EltTy, 2); - + // cast val v2i64 Ops[1] = Builder.CreateBitCast(Ops[1], VecTy, "cast"); - + // extract (0, 1) unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1; - llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, Index); + llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Index); Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract"); // cast pointer to i64 & store @@ -785,9 +800,9 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } } -Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, +Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { switch (BuiltinID) { default: return 0; } -} +} diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 5f3acea767d5c..3960cf51868f8 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -11,22 +11,123 @@ // //===----------------------------------------------------------------------===// -// We might split this into multiple files if it gets too unwieldy +// We might split this into multiple files if it gets too unwieldy #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "Mangle.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/StmtCXX.h" #include "llvm/ADT/StringExtras.h" using namespace clang; using namespace CodeGen; -void -CodeGenFunction::GenerateStaticCXXBlockVarDeclInit(const VarDecl &D, - llvm::GlobalVariable *GV) { +void +CodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor, + llvm::Constant *DeclPtr) { + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8Ty(VMContext)->getPointerTo(); + + std::vector<const llvm::Type *> Params; + Params.push_back(Int8PtrTy); + + // Get the destructor function type + const llvm::Type *DtorFnTy = + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); + DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); + + Params.clear(); + Params.push_back(DtorFnTy); + Params.push_back(Int8PtrTy); + Params.push_back(Int8PtrTy); + + // Get the __cxa_atexit function type + // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); + const llvm::FunctionType *AtExitFnTy = + llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); + + llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, + "__cxa_atexit"); + + llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, + "__dso_handle"); + + llvm::Constant *DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); + + llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy), + llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy), + llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) }; + Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); +} + +void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, + llvm::Constant *DeclPtr) { + assert(D.hasGlobalStorage() && + "VarDecl must have global storage!"); + + const Expr *Init = D.getInit(); + QualType T = D.getType(); + + if (T->isReferenceType()) { + ErrorUnsupported(Init, "global variable that binds to a reference"); + } else if (!hasAggregateLLVMType(T)) { + llvm::Value *V = EmitScalarExpr(Init); + EmitStoreOfScalar(V, DeclPtr, T.isVolatileQualified(), T); + } else if (T->isAnyComplexType()) { + EmitComplexExprIntoAddr(Init, DeclPtr, T.isVolatileQualified()); + } else { + EmitAggExpr(Init, DeclPtr, T.isVolatileQualified()); + + if (const RecordType *RT = T->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (!RD->hasTrivialDestructor()) + EmitCXXGlobalDtorRegistration(RD->getDestructor(getContext()), DeclPtr); + } + } +} + +void +CodeGenModule::EmitCXXGlobalInitFunc() { + if (CXXGlobalInits.empty()) + return; + + const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + false); + + // Create our global initialization function. + // FIXME: Should this be tweakable by targets? + llvm::Function *Fn = + llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, + "__cxx_global_initialization", &TheModule); + + CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, + &CXXGlobalInits[0], + CXXGlobalInits.size()); + AddGlobalCtor(Fn); +} + +void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, + const VarDecl **Decls, + unsigned NumDecls) { + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), + SourceLocation()); + + for (unsigned i = 0; i != NumDecls; ++i) { + const VarDecl *D = Decls[i]; + + llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); + EmitCXXGlobalVarDeclInit(*D, DeclPtr); + } + FinishFunction(); +} + +void +CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, + llvm::GlobalVariable *GV) { // FIXME: This should use __cxa_guard_{acquire,release}? assert(!getContext().getLangOptions().ThreadsafeStatics && @@ -34,46 +135,37 @@ CodeGenFunction::GenerateStaticCXXBlockVarDeclInit(const VarDecl &D, llvm::SmallString<256> GuardVName; llvm::raw_svector_ostream GuardVOut(GuardVName); - mangleGuardVariable(&D, getContext(), GuardVOut); - + mangleGuardVariable(CGM.getMangleContext(), &D, GuardVOut); + // Create the guard variable. - llvm::GlobalValue *GuardV = - new llvm::GlobalVariable(llvm::Type::Int64Ty, false, + llvm::GlobalValue *GuardV = + new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext), false, GV->getLinkage(), - llvm::Constant::getNullValue(llvm::Type::Int64Ty), - GuardVName.c_str(), - &CGM.getModule()); - + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)), + GuardVName.str()); + // Load the first byte of the guard variable. - const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0); - llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy), + const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); + 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 *nullValue = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)); llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool"); - + llvm::BasicBlock *InitBlock = createBasicBlock("init"); llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); // If the guard variable is 0, jump to the initializer code. Builder.CreateCondBr(ICmp, InitBlock, EndBlock); - + EmitBlock(InitBlock); - 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), + EmitCXXGlobalVarDeclInit(D, GV); + + Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1), Builder.CreateBitCast(GuardV, PtrTy)); - + EmitBlock(EndBlock); } @@ -82,336 +174,1399 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { - assert(MD->isInstance() && + assert(MD->isInstance() && "Trying to emit a member call expr on a static method!"); - const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); - + // A call to a trivial destructor requires no code generation. + if (const CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(MD)) + if (Destructor->isTrivial()) + return RValue::get(0); + + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + CallArgList Args; - + // Push the this ptr. Args.push_back(std::make_pair(RValue::get(This), MD->getThisType(getContext()))); - + // And the rest of the call args EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); - - QualType ResultType = MD->getType()->getAsFunctionType()->getResultType(); + + QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, Args, MD); } +/// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given +/// expr can be devirtualized. +static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) { + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { + // This is a record decl. We know the type and can devirtualize it. + return VD->getType()->isRecordType(); + } + + return false; + } + + // We can always devirtualize calls on temporary object expressions. + if (isa<CXXTemporaryObjectExpr>(Base)) + return true; + + // And calls on bound temporaries. + if (isa<CXXBindTemporaryExpr>(Base)) + return true; + + // Check if this is a call expr that returns a record type. + if (const CallExpr *CE = dyn_cast<CallExpr>(Base)) + return CE->getCallReturnType()->isRecordType(); + + // We can't devirtualize the call. + return false; +} + RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { + if (isa<BinaryOperator>(CE->getCallee())) + return EmitCXXMemberPointerCallExpr(CE); + const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()); const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); - const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); - const llvm::Type *Ty = - CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), - FPT->isVariadic()); - llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty); + if (MD->isStatic()) { + // The method is static, emit it as we would a regular call. + llvm::Value *Callee = CGM.GetAddrOfFunction(MD); + return EmitCall(Callee, getContext().getPointerType(MD->getType()), + CE->arg_begin(), CE->arg_end(), 0); + + } + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + + const llvm::Type *Ty = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); llvm::Value *This; - + if (ME->isArrow()) This = EmitScalarExpr(ME->getBase()); else { LValue BaseLV = EmitLValue(ME->getBase()); This = BaseLV.getAddress(); } - - return EmitCXXMemberCall(MD, Callee, This, + + // C++ [class.virtual]p12: + // Explicit qualification with the scope operator (5.1) suppresses the + // virtual call mechanism. + // + // We also don't emit a virtual call if the base expression has a record type + // because then we know what the type is. + llvm::Value *Callee; + if (MD->isVirtual() && !ME->hasQualifier() && + !canDevirtualizeMemberFunctionCalls(ME->getBase())) + Callee = BuildVirtualCall(MD, This, Ty); + else if (const CXXDestructorDecl *Destructor + = dyn_cast<CXXDestructorDecl>(MD)) + Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); + else + Callee = CGM.GetAddrOfFunction(MD, Ty); + + return EmitCXXMemberCall(MD, Callee, This, CE->arg_begin(), CE->arg_end()); } -RValue -CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, - const CXXMethodDecl *MD) { - assert(MD->isInstance() && - "Trying to emit a member call expr on a static method!"); +RValue +CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E) { + const BinaryOperator *BO = cast<BinaryOperator>(E->getCallee()); + const Expr *BaseExpr = BO->getLHS(); + const Expr *MemFnExpr = BO->getRHS(); + const MemberPointerType *MPT = + MemFnExpr->getType()->getAs<MemberPointerType>(); + const FunctionProtoType *FPT = + MPT->getPointeeType()->getAs<FunctionProtoType>(); + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(cast<RecordType>(MPT->getClass())->getDecl()); + + const llvm::FunctionType *FTy = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), + FPT->isVariadic()); + + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8Ty(VMContext)->getPointerTo(); + + // Get the member function pointer. + llvm::Value *MemFnPtr = + CreateTempAlloca(ConvertType(MemFnExpr->getType()), "mem.fn"); + EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false); + + // Emit the 'this' pointer. + llvm::Value *This; - const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); - const llvm::Type *Ty = - CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), - FPT->isVariadic()); - llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty); + if (BO->getOpcode() == BinaryOperator::PtrMemI) + This = EmitScalarExpr(BaseExpr); + else + This = EmitLValue(BaseExpr).getAddress(); - llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + // Adjust it. + llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1); + Adj = Builder.CreateLoad(Adj, "mem.fn.adj"); + + llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr"); + Ptr = Builder.CreateGEP(Ptr, Adj, "adj"); + + This = Builder.CreateBitCast(Ptr, This->getType(), "this"); + + llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr"); + const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); + + llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn"); + + // If the LSB in the function pointer is 1, the function pointer points to + // a virtual function. + llvm::Value *IsVirtual + = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1), + "and"); + + IsVirtual = Builder.CreateTrunc(IsVirtual, + llvm::Type::getInt1Ty(VMContext)); + + llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual"); + llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual"); + llvm::BasicBlock *FnEnd = createBasicBlock("fn.end"); + + Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); + EmitBlock(FnVirtual); + + const llvm::Type *VTableTy = + FTy->getPointerTo()->getPointerTo()->getPointerTo(); + + llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy); + VTable = Builder.CreateLoad(VTable); + + VTable = Builder.CreateGEP(VTable, FnAsInt, "fn"); + + // Since the function pointer is 1 plus the virtual table offset, we + // subtract 1 by using a GEP. + VTable = Builder.CreateConstGEP1_64(VTable, (uint64_t)-1); + + llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn"); + + EmitBranch(FnEnd); + EmitBlock(FnNonVirtual); + + // If the function is not virtual, just load the pointer. + llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn"); + NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo()); + + EmitBlock(FnEnd); + + llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo()); + Callee->reserveOperandSpace(2); + Callee->addIncoming(VirtualFn, FnVirtual); + Callee->addIncoming(NonVirtualFn, FnNonVirtual); + + CallArgList Args; + + QualType ThisType = + getContext().getPointerType(getContext().getTagDeclType(RD)); + + // Push the this ptr. + Args.push_back(std::make_pair(RValue::get(This), ThisType)); + + // And the rest of the call args + EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); + QualType ResultType = BO->getType()->getAs<FunctionType>()->getResultType(); + return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), + Callee, Args, 0); +} + +RValue +CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, + const CXXMethodDecl *MD) { + assert(MD->isInstance() && + "Trying to emit a member call expr on a static method!"); + + if (MD->isCopyAssignment()) { + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext()); + if (ClassDecl->hasTrivialCopyAssignment()) { + assert(!ClassDecl->hasUserDeclaredCopyAssignment() && + "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); + llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); + QualType Ty = E->getType(); + EmitAggregateCopy(This, Src, Ty); + return RValue::get(This); + } + } + + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::Type *Ty = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, Ty); + + llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + return EmitCXXMemberCall(MD, Callee, This, E->arg_begin() + 1, E->arg_end()); } llvm::Value *CodeGenFunction::LoadCXXThis() { - assert(isa<CXXMethodDecl>(CurFuncDecl) && + assert(isa<CXXMethodDecl>(CurFuncDecl) && "Must be in a C++ member function decl to load 'this'"); assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() && "Must be in a C++ member function decl to load 'this'"); - + // FIXME: What if we're inside a block? // ans: See how CodeGenFunction::LoadObjCSelf() uses // CodeGenFunction::BlockForwardSelf() for how to do this. return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); } +/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested) +/// for-loop to call the default constructor on individual members of the +/// array. +/// 'D' is the default constructor for elements of the array, 'ArrayTy' is the +/// array type and 'ArrayPtr' points to the beginning fo the array. +/// It is assumed that all relevant checks have been made by the caller. +void +CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, + const ConstantArrayType *ArrayTy, + llvm::Value *ArrayPtr) { + const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); + llvm::Value * NumElements = + llvm::ConstantInt::get(SizeTy, + getContext().getConstantArrayElementCount(ArrayTy)); + + EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr); +} + +void +CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, + llvm::Value *NumElements, + llvm::Value *ArrayPtr) { + const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); + + // Create a temporary for the loop index and initialize it with 0. + llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index"); + llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy); + Builder.CreateStore(Zero, IndexPtr, false); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + + // Generate: if (loop-index < number-of-elements fall to the loop body, + // otherwise, go to the block after the for-loop. + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + EmitBlock(ForBody); + + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter, + "arrayidx"); + EmitCXXConstructorCall(D, Ctor_Complete, Address, 0, 0); + + EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1); + Counter = Builder.CreateLoad(IndexPtr); + NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); + Builder.CreateStore(NextVal, IndexPtr, false); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + +/// EmitCXXAggrDestructorCall - calls the default destructor on array +/// elements in reverse order of construction. +void +CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, + const ArrayType *Array, + llvm::Value *This) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "Do we support VLA for destruction ?"); + llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + 1); + uint64_t ElementCount = getContext().getConstantArrayElementCount(CA); + // Create a temporary for the loop index and initialize it with count of + // array elements. + llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), + "loop.index"); + // Index = ElementCount; + llvm::Value* UpperCount = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount); + Builder.CreateStore(UpperCount, IndexPtr, false); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + + // Generate: if (loop-index != 0 fall to the loop body, + // otherwise, go to the block after the for-loop. + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant, + "isne"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsNE, ForBody, AfterFor); + + EmitBlock(ForBody); + + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + Counter = Builder.CreateSub(Counter, One); + llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx"); + EmitCXXDestructorCall(D, Dtor_Complete, Address); + + EmitBlock(ContinueBlock); + + // Emit the decrement of the loop counter. + Counter = Builder.CreateLoad(IndexPtr); + Counter = Builder.CreateSub(Counter, One, "dec"); + Builder.CreateStore(Counter, IndexPtr, false); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + void -CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, - CXXCtorType Type, +CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, + CXXCtorType Type, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { + if (D->isCopyConstructor(getContext())) { + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D->getDeclContext()); + if (ClassDecl->hasTrivialCopyConstructor()) { + assert(!ClassDecl->hasUserDeclaredCopyConstructor() && + "EmitCXXConstructorCall - user declared copy constructor"); + const Expr *E = (*ArgBeg); + QualType Ty = E->getType(); + llvm::Value *Src = EmitLValue(E).getAddress(); + EmitAggregateCopy(This, Src, Ty); + return; + } + } + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); EmitCXXMemberCall(D, Callee, This, ArgBeg, ArgEnd); } -void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D, +void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, llvm::Value *This) { llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(D, Type); - + EmitCXXMemberCall(D, Callee, This, 0, 0); } -void -CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, +void +CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, const CXXConstructExpr *E) { assert(Dest && "Must have a destination!"); - - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(E->getType()->getAsRecordType()->getDecl()); + + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); if (RD->hasTrivialConstructor()) return; - - // Call the constructor. - EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest, - E->arg_begin(), E->arg_end()); -} - -llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { - if (E->isArray()) { - ErrorUnsupported(E, "new[] expression"); - return llvm::UndefValue::get(ConvertType(E->getType())); - } - - QualType AllocType = E->getAllocatedType(); - FunctionDecl *NewFD = E->getOperatorNew(); - const FunctionProtoType *NewFTy = NewFD->getType()->getAsFunctionProtoType(); - - CallArgList NewArgs; - - // The allocation size is the first argument. - QualType SizeTy = getContext().getSizeType(); - llvm::Value *AllocSize = - llvm::ConstantInt::get(ConvertType(SizeTy), - getContext().getTypeSize(AllocType) / 8); - - NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); - - // Emit the rest of the arguments. - // FIXME: Ideally, this should just use EmitCallArgs. - CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); - - // First, use the types from the function type. - // We start at 1 here because the first argument (the allocation size) - // has already been emitted. - for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { - QualType ArgType = NewFTy->getArgType(i); - - assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). - getTypePtr() == - getContext().getCanonicalType(NewArg->getType()).getTypePtr() && - "type mismatch in call argument!"); - - NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), - ArgType)); - - } - - // Either we've emitted all the call args, or we have a call to a - // variadic function. - assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && - "Extra arguments in non-variadic function!"); - - // If we still have any arguments, emit them using the type of the argument. - for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); - NewArg != NewArgEnd; ++NewArg) { - QualType ArgType = NewArg->getType(); - NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), - ArgType)); - } - - // Emit the call to new. - RValue RV = - EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), - CGM.GetAddrOfFunction(GlobalDecl(NewFD)), - NewArgs, NewFD); - - // If an allocation function is declared with an empty exception specification - // it returns null to indicate failure to allocate storage. [expr.new]p13. - // (We don't need to check for null when there's no new initializer and - // we're allocating a POD type). - bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && - !(AllocType->isPODType() && !E->hasInitializer()); - - llvm::BasicBlock *NewNull = 0; - llvm::BasicBlock *NewNotNull = 0; - llvm::BasicBlock *NewEnd = 0; - - llvm::Value *NewPtr = RV.getScalarVal(); - - if (NullCheckResult) { - NewNull = createBasicBlock("new.null"); - NewNotNull = createBasicBlock("new.notnull"); - NewEnd = createBasicBlock("new.end"); - - llvm::Value *IsNull = - Builder.CreateICmpEQ(NewPtr, - llvm::Constant::getNullValue(NewPtr->getType()), - "isnull"); - - Builder.CreateCondBr(IsNull, NewNull, NewNotNull); - EmitBlock(NewNotNull); - } - - NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); - - if (AllocType->isPODType()) { - if (E->getNumConstructorArgs() > 0) { - assert(E->getNumConstructorArgs() == 1 && - "Can only have one argument to initializer of POD type."); - - const Expr *Init = E->getConstructorArg(0); - - if (!hasAggregateLLVMType(AllocType)) - Builder.CreateStore(EmitScalarExpr(Init), NewPtr); - else if (AllocType->isAnyComplexType()) - EmitComplexExprIntoAddr(Init, NewPtr, AllocType.isVolatileQualified()); - else - EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); - } - } else { - // Call the constructor. - CXXConstructorDecl *Ctor = E->getConstructor(); - - EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, - E->constructor_arg_begin(), - E->constructor_arg_end()); - } - - if (NullCheckResult) { - Builder.CreateBr(NewEnd); - EmitBlock(NewNull); - Builder.CreateBr(NewEnd); - EmitBlock(NewEnd); - - llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); - PHI->reserveOperandSpace(2); - PHI->addIncoming(NewPtr, NewNotNull); - PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull); - - NewPtr = PHI; - } - - return NewPtr; -} -static bool canGenerateCXXstructor(const CXXRecordDecl *RD, - ASTContext &Context) { - // The class has base classes - we don't support that right now. - if (RD->getNumBases() > 0) - return false; - - for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); - I != E; ++I) { - // We don't support ctors for fields that aren't POD. - if (!I->getType()->isPODType()) - return false; + // Code gen optimization to eliminate copy constructor and return + // its first argument instead. + if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { + CXXConstructExpr::const_arg_iterator i = E->arg_begin(); + EmitAggExpr((*i), Dest, false); + return; } - - return true; + // Call the constructor. + EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest, + E->arg_begin(), E->arg_end()); } void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { - if (!canGenerateCXXstructor(D->getParent(), getContext())) { - ErrorUnsupported(D, "C++ constructor", true); - return; - } - EmitGlobal(GlobalDecl(D, Ctor_Complete)); EmitGlobal(GlobalDecl(D, Ctor_Base)); } -void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, +void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type) { - + llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type); - - CodeGenFunction(*this).GenerateCode(D, Fn); - + + CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); + SetFunctionDefinitionAttributes(D, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); } llvm::Function * -CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, +CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type) { const llvm::FunctionType *FTy = getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); - + const char *Name = getMangledCXXCtorName(D, Type); return cast<llvm::Function>( GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); } -const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D, +const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D, CXXCtorType Type) { llvm::SmallString<256> Name; llvm::raw_svector_ostream Out(Name); - mangleCXXCtor(D, Type, Context, Out); - + mangleCXXCtor(getMangleContext(), D, Type, Out); + Name += '\0'; return UniqueMangledName(Name.begin(), Name.end()); } void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) { - if (!canGenerateCXXstructor(D->getParent(), getContext())) { - ErrorUnsupported(D, "C++ destructor", true); - return; - } - EmitCXXDestructor(D, Dtor_Complete); EmitCXXDestructor(D, Dtor_Base); } -void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, +void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type) { llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type); - - CodeGenFunction(*this).GenerateCode(D, Fn); - + + CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); + SetFunctionDefinitionAttributes(D, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); } llvm::Function * -CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, +CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type) { const llvm::FunctionType *FTy = getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); - + const char *Name = getMangledCXXDtorName(D, Type); return cast<llvm::Function>( GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); } -const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, +const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, CXXDtorType Type) { llvm::SmallString<256> Name; llvm::raw_svector_ostream Out(Name); - mangleCXXDtor(D, Type, Context, Out); - + mangleCXXDtor(getMangleContext(), D, Type, Out); + Name += '\0'; return UniqueMangledName(Name.begin(), Name.end()); } + +llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn, + const CXXMethodDecl *MD, + bool Extern, int64_t nv, + int64_t v) { + QualType R = MD->getType()->getAs<FunctionType>()->getResultType(); + + FunctionArgList Args; + ImplicitParamDecl *ThisDecl = + ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + MD->getThisType(getContext())); + Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); + for (FunctionDecl::param_const_iterator i = MD->param_begin(), + e = MD->param_end(); + i != e; ++i) { + ParmVarDecl *D = *i; + Args.push_back(std::make_pair(D, D->getType())); + } + IdentifierInfo *II + = &CGM.getContext().Idents.get("__thunk_named_foo_"); + FunctionDecl *FD = FunctionDecl::Create(getContext(), + getContext().getTranslationUnitDecl(), + SourceLocation(), II, R, 0, + Extern + ? FunctionDecl::Extern + : FunctionDecl::Static, + false, true); + StartFunction(FD, R, Fn, Args, SourceLocation()); + // FIXME: generate body + FinishFunction(); + return Fn; +} + +llvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, + const CXXMethodDecl *MD, + bool Extern, + int64_t nv_t, + int64_t v_t, + int64_t nv_r, + int64_t v_r) { + QualType R = MD->getType()->getAs<FunctionType>()->getResultType(); + + FunctionArgList Args; + ImplicitParamDecl *ThisDecl = + ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + MD->getThisType(getContext())); + Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); + for (FunctionDecl::param_const_iterator i = MD->param_begin(), + e = MD->param_end(); + i != e; ++i) { + ParmVarDecl *D = *i; + Args.push_back(std::make_pair(D, D->getType())); + } + IdentifierInfo *II + = &CGM.getContext().Idents.get("__thunk_named_foo_"); + FunctionDecl *FD = FunctionDecl::Create(getContext(), + getContext().getTranslationUnitDecl(), + SourceLocation(), II, R, 0, + Extern + ? FunctionDecl::Extern + : FunctionDecl::Static, + false, true); + StartFunction(FD, R, Fn, Args, SourceLocation()); + // FIXME: generate body + FinishFunction(); + return Fn; +} + +llvm::Constant *CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern, + int64_t nv, int64_t v) { + llvm::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + mangleThunk(getMangleContext(), MD, nv, v, Out); + llvm::GlobalVariable::LinkageTypes linktype; + linktype = llvm::GlobalValue::WeakAnyLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; + llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::FunctionType *FTy = + getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + + llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(), + &getModule()); + CodeGenFunction(*this).GenerateThunk(Fn, MD, Extern, nv, v); + // Fn = Builder.CreateBitCast(Fn, Ptr8Ty); + llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); + return m; +} + +llvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, + bool Extern, int64_t nv_t, + int64_t v_t, int64_t nv_r, + int64_t v_r) { + llvm::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + mangleCovariantThunk(getMangleContext(), MD, nv_t, v_t, nv_r, v_r, Out); + llvm::GlobalVariable::LinkageTypes linktype; + linktype = llvm::GlobalValue::WeakAnyLinkage; + if (!Extern) + linktype = llvm::GlobalValue::InternalLinkage; + llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::FunctionType *FTy = + getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + + llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(), + &getModule()); + CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r, + v_r); + // Fn = Builder.CreateBitCast(Fn, Ptr8Ty); + llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); + return m; +} + +llvm::Value * +CodeGenFunction::GetVirtualCXXBaseClassOffset(llvm::Value *This, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl) { + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8Ty(VMContext)->getPointerTo(); + + llvm::Value *VTablePtr = Builder.CreateBitCast(This, + Int8PtrTy->getPointerTo()); + VTablePtr = Builder.CreateLoad(VTablePtr, "vtable"); + + int64_t VBaseOffsetIndex = + CGM.getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl); + + llvm::Value *VBaseOffsetPtr = + Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "vbase.offset.ptr"); + const llvm::Type *PtrDiffTy = + ConvertType(getContext().getPointerDiffType()); + + VBaseOffsetPtr = Builder.CreateBitCast(VBaseOffsetPtr, + PtrDiffTy->getPointerTo()); + + llvm::Value *VBaseOffset = Builder.CreateLoad(VBaseOffsetPtr, "vbase.offset"); + + return VBaseOffset; +} + +llvm::Value * +CodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This, + const llvm::Type *Ty) { + int64_t Index = CGM.getVtableInfo().getMethodVtableIndex(MD); + + Ty = llvm::PointerType::get(Ty, 0); + Ty = llvm::PointerType::get(Ty, 0); + Ty = llvm::PointerType::get(Ty, 0); + llvm::Value *vtbl = Builder.CreateBitCast(This, Ty); + vtbl = Builder.CreateLoad(vtbl); + llvm::Value *vfn = Builder.CreateConstInBoundsGEP1_64(vtbl, + Index, "vfn"); + vfn = Builder.CreateLoad(vfn); + return vfn; +} + +/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class +/// array of objects from SrcValue to DestValue. Copying can be either a bitwise +/// copy or via a copy constructor call. +// FIXME. Consolidate this with EmitCXXAggrConstructorCall. +void CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest, + llvm::Value *Src, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "VLA cannot be copied over"); + bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor(); + + // Create a temporary for the loop index and initialize it with 0. + llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), + "loop.index"); + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); + Builder.CreateStore(zeroConstant, IndexPtr, false); + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + // Generate: if (loop-index < number-of-elements fall to the loop body, + // otherwise, go to the block after the for-loop. + uint64_t NumElements = getContext().getConstantArrayElementCount(CA); + llvm::Value * NumElementsPtr = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, + "isless"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + EmitBlock(ForBody); + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); + Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); + if (BitwiseCopy) + EmitAggregateCopy(Dest, Src, Ty); + else if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(getContext(), 0)) { + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, + Ctor_Complete); + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + BaseCopyCtor->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + BaseCopyCtor->getParamDecl(0)->getType())); + QualType ResultType = + BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, CallArgs, BaseCopyCtor); + } + EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); + Counter = Builder.CreateLoad(IndexPtr); + NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); + Builder.CreateStore(NextVal, IndexPtr, false); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + +/// EmitClassAggrCopyAssignment - This routine generates code to assign a class +/// array of objects from SrcValue to DestValue. Assignment can be either a +/// bitwise assignment or via a copy assignment operator function call. +/// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy +void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest, + llvm::Value *Src, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "VLA cannot be asssigned"); + bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment(); + + // Create a temporary for the loop index and initialize it with 0. + llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), + "loop.index"); + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); + Builder.CreateStore(zeroConstant, IndexPtr, false); + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + // Generate: if (loop-index < number-of-elements fall to the loop body, + // otherwise, go to the block after the for-loop. + uint64_t NumElements = getContext().getConstantArrayElementCount(CA); + llvm::Value * NumElementsPtr = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, + "isless"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + EmitBlock(ForBody); + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the assignment operator call on array element. + Counter = Builder.CreateLoad(IndexPtr); + Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); + Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); + const CXXMethodDecl *MD = 0; + if (BitwiseAssign) + EmitAggregateCopy(Dest, Src, Ty); + else { + bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(), + MD); + assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign"); + (void)hasCopyAssign; + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::Type *LTy = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); + + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + MD->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + MD->getParamDecl(0)->getType())); + QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, CallArgs, MD); + } + EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); + Counter = Builder.CreateLoad(IndexPtr); + NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); + Builder.CreateStore(NextVal, IndexPtr, false); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + +/// EmitClassMemberwiseCopy - This routine generates code to copy a class +/// object from SrcValue to DestValue. Copying can be either a bitwise copy +/// or via a copy constructor call. +void CodeGenFunction::EmitClassMemberwiseCopy( + llvm::Value *Dest, llvm::Value *Src, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, QualType Ty) { + if (ClassDecl) { + Dest = GetAddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + Src = GetAddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + } + if (BaseClassDecl->hasTrivialCopyConstructor()) { + EmitAggregateCopy(Dest, Src, Ty); + return; + } + + if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(getContext(), 0)) { + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, + Ctor_Complete); + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + BaseCopyCtor->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + BaseCopyCtor->getParamDecl(0)->getType())); + QualType ResultType = + BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, CallArgs, BaseCopyCtor); + } +} + +/// EmitClassCopyAssignment - This routine generates code to copy assign a class +/// object from SrcValue to DestValue. Assignment can be either a bitwise +/// assignment of via an assignment operator call. +// FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot. +void CodeGenFunction::EmitClassCopyAssignment( + llvm::Value *Dest, llvm::Value *Src, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, + QualType Ty) { + if (ClassDecl) { + Dest = GetAddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + Src = GetAddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + } + if (BaseClassDecl->hasTrivialCopyAssignment()) { + EmitAggregateCopy(Dest, Src, Ty); + return; + } + + const CXXMethodDecl *MD = 0; + bool ConstCopyAssignOp = BaseClassDecl->hasConstCopyAssignment(getContext(), + MD); + assert(ConstCopyAssignOp && "EmitClassCopyAssignment - missing copy assign"); + (void)ConstCopyAssignOp; + + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::Type *LTy = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); + + CallArgList CallArgs; + // Push the this (Dest) ptr. + CallArgs.push_back(std::make_pair(RValue::get(Dest), + MD->getThisType(getContext()))); + + // Push the Src ptr. + CallArgs.push_back(std::make_pair(RValue::get(Src), + MD->getParamDecl(0)->getType())); + QualType ResultType = + MD->getType()->getAs<FunctionType>()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), + Callee, CallArgs, MD); +} + +/// SynthesizeDefaultConstructor - synthesize a default constructor +void +CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor, + CXXCtorType Type, + llvm::Function *Fn, + const FunctionArgList &Args) { + StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, + SourceLocation()); + EmitCtorPrologue(Ctor, Type); + FinishFunction(); +} + +/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a copy +/// constructor, in accordance with section 12.8 (p7 and p8) of C++03 +/// The implicitly-defined copy constructor for class X performs a memberwise +/// copy of its subobjects. The order of copying is the same as the order +/// of initialization of bases and members in a user-defined constructor +/// Each subobject is copied in the manner appropriate to its type: +/// if the subobject is of class type, the copy constructor for the class is +/// used; +/// if the subobject is an array, each element is copied, in the manner +/// appropriate to the element type; +/// if the subobject is of scalar type, the built-in assignment operator is +/// used. +/// Virtual base class subobjects shall be copied only once by the +/// implicitly-defined copy constructor + +void +CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, + CXXCtorType Type, + llvm::Function *Fn, + const FunctionArgList &Args) { + const CXXRecordDecl *ClassDecl = Ctor->getParent(); + assert(!ClassDecl->hasUserDeclaredCopyConstructor() && + "SynthesizeCXXCopyConstructor - copy constructor has definition already"); + StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, + SourceLocation()); + + FunctionArgList::const_iterator i = Args.begin(); + const VarDecl *ThisArg = i->first; + llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); + llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); + const VarDecl *SrcArg = (i+1)->first; + llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); + llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); + + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy constrution of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, + Base->getType()); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = getContext().getCanonicalType((*Field)->getType()); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *DestBaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + llvm::Value *SrcBaseAddrPtr = + Builder.CreateBitCast(RHS.getAddress(), BasePtr); + EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array, + FieldClassDecl, FieldType); + } + else + EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), + 0 /*ClassDecl*/, FieldClassDecl, FieldType); + continue; + } + // Do a built-in assignment of scalar data members. + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + RValue RVRHS = EmitLoadOfLValue(RHS, FieldType); + EmitStoreThroughLValue(RVRHS, LHS, FieldType); + } + FinishFunction(); +} + +/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. +/// Before the implicitly-declared copy assignment operator for a class is +/// implicitly defined, all implicitly- declared copy assignment operators for +/// its direct base classes and its nonstatic data members shall have been +/// implicitly defined. [12.8-p12] +/// The implicitly-defined copy assignment operator for class X performs +/// memberwise assignment of its subob- jects. The direct base classes of X are +/// assigned first, in the order of their declaration in +/// the base-specifier-list, and then the immediate nonstatic data members of X +/// are assigned, in the order in which they were declared in the class +/// definition.Each subobject is assigned in the manner appropriate to its type: +/// if the subobject is of class type, the copy assignment operator for the +/// class is used (as if by explicit qualification; that is, ignoring any +/// possible virtual overriding functions in more derived classes); +/// +/// if the subobject is an array, each element is assigned, in the manner +/// appropriate to the element type; +/// +/// if the subobject is of scalar type, the built-in assignment operator is +/// used. +void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, + llvm::Function *Fn, + const FunctionArgList &Args) { + + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); + assert(!ClassDecl->hasUserDeclaredCopyAssignment() && + "SynthesizeCXXCopyAssignment - copy assignment has user declaration"); + StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation()); + + FunctionArgList::const_iterator i = Args.begin(); + const VarDecl *ThisArg = i->first; + llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); + llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); + const VarDecl *SrcArg = (i+1)->first; + llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); + llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); + + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy assignment of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, + Base->getType()); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = getContext().getCanonicalType((*Field)->getType()); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *DestBaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + llvm::Value *SrcBaseAddrPtr = + Builder.CreateBitCast(RHS.getAddress(), BasePtr); + EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array, + FieldClassDecl, FieldType); + } + else + EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(), + 0 /*ClassDecl*/, FieldClassDecl, FieldType); + continue; + } + // Do a built-in assignment of scalar data members. + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); + RValue RVRHS = EmitLoadOfLValue(RHS, FieldType); + EmitStoreThroughLValue(RVRHS, LHS, FieldType); + } + + // return *this; + Builder.CreateStore(LoadOfThis, ReturnValue); + + FinishFunction(); +} + +/// EmitCtorPrologue - This routine generates necessary code to initialize +/// base classes and non-static data members belonging to this constructor. +/// FIXME: This needs to take a CXXCtorType. +void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, + CXXCtorType CtorType) { + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); + // FIXME: Add vbase initialization + llvm::Value *LoadOfThis = 0; + + for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), + E = CD->init_end(); + B != E; ++B) { + CXXBaseOrMemberInitializer *Member = (*B); + if (Member->isBaseInitializer()) { + LoadOfThis = LoadCXXThis(); + Type *BaseType = Member->getBaseClass(); + CXXRecordDecl *BaseClassDecl = + cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); + llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl, + BaseClassDecl, + /*NullCheckValue=*/false); + EmitCXXConstructorCall(Member->getConstructor(), + CtorType, V, + Member->const_arg_begin(), + Member->const_arg_end()); + } else { + // non-static data member initilaizers. + FieldDecl *Field = Member->getMember(); + QualType FieldType = getContext().getCanonicalType((Field)->getType()); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + + LoadOfThis = LoadCXXThis(); + LValue LHS; + if (FieldType->isReferenceType()) { + // FIXME: This is really ugly; should be refactored somehow + unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); + llvm::Value *V = Builder.CreateStructGEP(LoadOfThis, idx, "tmp"); + assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs"); + LHS = LValue::MakeAddr(V, MakeQualifiers(FieldType)); + } else { + LHS = EmitLValueForField(LoadOfThis, Field, false, 0); + } + if (FieldType->getAs<RecordType>()) { + if (!Field->isAnonymousStructOrUnion()) { + assert(Member->getConstructor() && + "EmitCtorPrologue - no constructor to initialize member"); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + EmitCXXAggrConstructorCall(Member->getConstructor(), + Array, BaseAddrPtr); + } + else + EmitCXXConstructorCall(Member->getConstructor(), + Ctor_Complete, LHS.getAddress(), + Member->const_arg_begin(), + Member->const_arg_end()); + continue; + } + else { + // Initializing an anonymous union data member. + FieldDecl *anonMember = Member->getAnonUnionMember(); + LHS = EmitLValueForField(LHS.getAddress(), anonMember, + /*IsUnion=*/true, 0); + FieldType = anonMember->getType(); + } + } + + assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only"); + Expr *RhsExpr = *Member->arg_begin(); + RValue RHS; + if (FieldType->isReferenceType()) + RHS = EmitReferenceBindingToExpr(RhsExpr, FieldType, + /*IsInitializer=*/true); + else + RHS = RValue::get(EmitScalarExpr(RhsExpr, true)); + EmitStoreThroughLValue(RHS, LHS, FieldType); + } + } + + if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) { + // Nontrivial default constructor with no initializer list. It may still + // have bases classes and/or contain non-static data members which require + // construction. + for (CXXRecordDecl::base_class_const_iterator Base = + ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy assignment of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialConstructor()) + continue; + if (CXXConstructorDecl *BaseCX = + BaseClassDecl->getDefaultConstructor(getContext())) { + LoadOfThis = LoadCXXThis(); + llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl, + BaseClassDecl, + /*NullCheckValue=*/false); + EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0); + } + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = getContext().getCanonicalType((*Field)->getType()); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion()) + continue; + const RecordType *ClassRec = FieldType->getAs<RecordType>(); + CXXRecordDecl *MemberClassDecl = + dyn_cast<CXXRecordDecl>(ClassRec->getDecl()); + if (!MemberClassDecl || MemberClassDecl->hasTrivialConstructor()) + continue; + if (CXXConstructorDecl *MamberCX = + MemberClassDecl->getDefaultConstructor(getContext())) { + LoadOfThis = LoadCXXThis(); + LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + EmitCXXAggrConstructorCall(MamberCX, Array, BaseAddrPtr); + } + else + EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), + 0, 0); + } + } + } + + // Initialize the vtable pointer + if (ClassDecl->isDynamicClass()) { + if (!LoadOfThis) + LoadOfThis = LoadCXXThis(); + llvm::Value *VtableField; + llvm::Type *Ptr8Ty, *PtrPtr8Ty; + Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); + PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0); + VtableField = Builder.CreateBitCast(LoadOfThis, PtrPtr8Ty); + llvm::Value *vtable = GenerateVtable(ClassDecl); + Builder.CreateStore(vtable, VtableField); + } +} + +/// EmitDtorEpilogue - Emit all code that comes at the end of class's +/// destructor. This is to call destructors on members and base classes +/// in reverse order of their construction. +/// FIXME: This needs to take a CXXDtorType. +void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD, + CXXDtorType DtorType) { + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext()); + assert(!ClassDecl->getNumVBases() && + "FIXME: Destruction of virtual bases not supported"); + (void)ClassDecl; // prevent warning. + + for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(), + *E = DD->destr_end(); B != E; ++B) { + uintptr_t BaseOrMember = (*B); + if (DD->isMemberToDestroy(BaseOrMember)) { + FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember); + QualType FieldType = getContext().getCanonicalType((FD)->getType()); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + const RecordType *RT = FieldType->getAs<RecordType>(); + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) + continue; + llvm::Value *LoadOfThis = LoadCXXThis(); + LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), + Array, BaseAddrPtr); + } + else + EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), + Dtor_Complete, LHS.getAddress()); + } else { + const RecordType *RT = + DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs<RecordType>(); + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(), + ClassDecl, BaseClassDecl, + /*NullCheckValue=*/false); + EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), + DtorType, V); + } + } + if (DD->getNumBaseOrMemberDestructions() || DD->isTrivial()) + return; + // Case of destructor synthesis with fields and base classes + // which have non-trivial destructors. They must be destructed in + // reverse order of their construction. + llvm::SmallVector<FieldDecl *, 16> DestructedFields; + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = getContext().getCanonicalType((*Field)->getType()); + if (getContext().getAsConstantArrayType(FieldType)) + FieldType = getContext().getBaseElementType(FieldType); + if (const RecordType *RT = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) + continue; + DestructedFields.push_back(*Field); + } + } + if (!DestructedFields.empty()) + for (int i = DestructedFields.size() -1; i >= 0; --i) { + FieldDecl *Field = DestructedFields[i]; + QualType FieldType = Field->getType(); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + const RecordType *RT = FieldType->getAs<RecordType>(); + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + llvm::Value *LoadOfThis = LoadCXXThis(); + LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), + Array, BaseAddrPtr); + } + else + EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), + Dtor_Complete, LHS.getAddress()); + } + + llvm::SmallVector<CXXRecordDecl*, 4> DestructedBases; + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + // FIXME. copy assignment of virtual base NYI + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (BaseClassDecl->hasTrivialDestructor()) + continue; + DestructedBases.push_back(BaseClassDecl); + } + if (DestructedBases.empty()) + return; + for (int i = DestructedBases.size() -1; i >= 0; --i) { + CXXRecordDecl *BaseClassDecl = DestructedBases[i]; + llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(), + ClassDecl,BaseClassDecl, + /*NullCheckValue=*/false); + EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), + Dtor_Complete, V); + } +} + +void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, + CXXDtorType DtorType, + llvm::Function *Fn, + const FunctionArgList &Args) { + + const CXXRecordDecl *ClassDecl = Dtor->getParent(); + assert(!ClassDecl->hasUserDeclaredDestructor() && + "SynthesizeDefaultDestructor - destructor has user declaration"); + (void) ClassDecl; + + StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args, + SourceLocation()); + EmitDtorEpilogue(Dtor, DtorType); + FinishFunction(); +} + +// FIXME: Move this to CGCXXStmt.cpp +void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { + // FIXME: We need to do more here. + EmitStmt(S.getTryBlock()); +} diff --git a/lib/CodeGen/CGCXX.h b/lib/CodeGen/CGCXX.h index 6051d9133c026..1e6adb05a0d92 100644 --- a/lib/CodeGen/CGCXX.h +++ b/lib/CodeGen/CGCXX.h @@ -30,7 +30,7 @@ enum CXXDtorType { Dtor_Complete, // Complete object dtor Dtor_Base // Base object dtor }; - + } // end namespace clang #endif // CLANG_CODEGEN_CGCXX_H diff --git a/lib/CodeGen/CGCXXClass.cpp b/lib/CodeGen/CGCXXClass.cpp new file mode 100644 index 0000000000000..56a28fc9a007a --- /dev/null +++ b/lib/CodeGen/CGCXXClass.cpp @@ -0,0 +1,176 @@ +//===--- CGCXXClass.cpp - Emit LLVM Code for C++ classes ------------------===// +// +// 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 of classes +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/RecordLayout.h" + +using namespace clang; +using namespace CodeGen; + +static uint64_t +ComputeNonVirtualBaseClassOffset(ASTContext &Context, CXXBasePaths &Paths, + unsigned Start) { + uint64_t Offset = 0; + + const CXXBasePath &Path = Paths.front(); + for (unsigned i = Start, e = Path.size(); i != e; ++i) { + const CXXBasePathElement& Element = Path[i]; + + // Get the layout. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class); + + const CXXBaseSpecifier *BS = Element.Base; + assert(!BS->isVirtual() && "Should not see virtual bases here!"); + + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(BS->getType()->getAs<RecordType>()->getDecl()); + + // Add the offset. + Offset += Layout.getBaseClassOffset(Base) / 8; + } + + return Offset; +} + +llvm::Constant * +CodeGenModule::GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl) { + if (ClassDecl == BaseClassDecl) + return 0; + + CXXBasePaths Paths(/*FindAmbiguities=*/false, + /*RecordPaths=*/true, /*DetectVirtual=*/false); + if (!const_cast<CXXRecordDecl *>(ClassDecl)-> + isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) { + assert(false && "Class must be derived from the passed in base class!"); + return 0; + } + + uint64_t Offset = ComputeNonVirtualBaseClassOffset(getContext(), Paths, 0); + if (!Offset) + return 0; + + const llvm::Type *PtrDiffTy = + Types.ConvertType(getContext().getPointerDiffType()); + + return llvm::ConstantInt::get(PtrDiffTy, Offset); +} + +static llvm::Value *GetCXXBaseClassOffset(CodeGenFunction &CGF, + llvm::Value *BaseValue, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl) { + CXXBasePaths Paths(/*FindAmbiguities=*/false, + /*RecordPaths=*/true, /*DetectVirtual=*/true); + if (!const_cast<CXXRecordDecl *>(ClassDecl)-> + isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) { + assert(false && "Class must be derived from the passed in base class!"); + return 0; + } + + unsigned Start = 0; + llvm::Value *VirtualOffset = 0; + if (const RecordType *RT = Paths.getDetectedVirtual()) { + const CXXRecordDecl *VBase = cast<CXXRecordDecl>(RT->getDecl()); + + VirtualOffset = + CGF.GetVirtualCXXBaseClassOffset(BaseValue, ClassDecl, VBase); + + const CXXBasePath &Path = Paths.front(); + unsigned e = Path.size(); + for (Start = 0; Start != e; ++Start) { + const CXXBasePathElement& Element = Path[Start]; + + if (Element.Class == VBase) + break; + } + } + + uint64_t Offset = + ComputeNonVirtualBaseClassOffset(CGF.getContext(), Paths, Start); + + if (!Offset) + return VirtualOffset; + + const llvm::Type *PtrDiffTy = + CGF.ConvertType(CGF.getContext().getPointerDiffType()); + llvm::Value *NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, Offset); + + if (VirtualOffset) + return CGF.Builder.CreateAdd(VirtualOffset, NonVirtualOffset); + + return NonVirtualOffset; +} + +llvm::Value * +CodeGenFunction::GetAddressCXXOfBaseClass(llvm::Value *BaseValue, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, + bool NullCheckValue) { + QualType BTy = + getContext().getCanonicalType( + getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClassDecl))); + const llvm::Type *BasePtrTy = llvm::PointerType::getUnqual(ConvertType(BTy)); + + if (ClassDecl == BaseClassDecl) { + // Just cast back. + return Builder.CreateBitCast(BaseValue, BasePtrTy); + } + + llvm::BasicBlock *CastNull = 0; + llvm::BasicBlock *CastNotNull = 0; + llvm::BasicBlock *CastEnd = 0; + + if (NullCheckValue) { + CastNull = createBasicBlock("cast.null"); + CastNotNull = createBasicBlock("cast.notnull"); + CastEnd = createBasicBlock("cast.end"); + + llvm::Value *IsNull = + Builder.CreateICmpEQ(BaseValue, + llvm::Constant::getNullValue(BaseValue->getType())); + Builder.CreateCondBr(IsNull, CastNull, CastNotNull); + EmitBlock(CastNotNull); + } + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + + llvm::Value *Offset = + GetCXXBaseClassOffset(*this, BaseValue, ClassDecl, BaseClassDecl); + + if (Offset) { + // Apply the offset. + BaseValue = Builder.CreateBitCast(BaseValue, Int8PtrTy); + BaseValue = Builder.CreateGEP(BaseValue, Offset, "add.ptr"); + } + + // Cast back. + BaseValue = Builder.CreateBitCast(BaseValue, BasePtrTy); + + if (NullCheckValue) { + Builder.CreateBr(CastEnd); + EmitBlock(CastNull); + Builder.CreateBr(CastEnd); + EmitBlock(CastEnd); + + llvm::PHINode *PHI = Builder.CreatePHI(BaseValue->getType()); + PHI->reserveOperandSpace(2); + PHI->addIncoming(BaseValue, CastNotNull); + PHI->addIncoming(llvm::Constant::getNullValue(BaseValue->getType()), + CastNull); + BaseValue = PHI; + } + + return BaseValue; +} diff --git a/lib/CodeGen/CGCXXExpr.cpp b/lib/CodeGen/CGCXXExpr.cpp new file mode 100644 index 0000000000000..2d62df6c58a44 --- /dev/null +++ b/lib/CodeGen/CGCXXExpr.cpp @@ -0,0 +1,304 @@ +//===--- CGCXXExpr.cpp - Emit LLVM Code for C++ expressions ---------------===// +// +// 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 code generation of C++ expressions +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +using namespace clang; +using namespace CodeGen; + +static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) { + if (!E->isArray()) + return 0; + + QualType T = E->getAllocatedType(); + + const RecordType *RT = T->getAs<RecordType>(); + if (!RT) + return 0; + + const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); + if (!RD) + return 0; + + // Check if the class has a trivial destructor. + if (RD->hasTrivialDestructor()) { + // FIXME: Check for a two-argument delete. + return 0; + } + + // Padding is the maximum of sizeof(size_t) and alignof(T) + return std::max(Ctx.getTypeSize(Ctx.getSizeType()), + static_cast<uint64_t>(Ctx.getTypeAlign(T))) / 8; +} + +static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, + const CXXNewExpr *E, + llvm::Value *& NumElements) { + QualType Type = E->getAllocatedType(); + uint64_t TypeSizeInBytes = CGF.getContext().getTypeSize(Type) / 8; + const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); + + if (!E->isArray()) + return llvm::ConstantInt::get(SizeTy, TypeSizeInBytes); + + uint64_t CookiePadding = CalculateCookiePadding(CGF.getContext(), E); + + Expr::EvalResult Result; + if (E->getArraySize()->Evaluate(Result, CGF.getContext()) && + !Result.HasSideEffects && Result.Val.isInt()) { + + uint64_t AllocSize = + Result.Val.getInt().getZExtValue() * TypeSizeInBytes + CookiePadding; + + NumElements = + llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue()); + + return llvm::ConstantInt::get(SizeTy, AllocSize); + } + + // Emit the array size expression. + NumElements = CGF.EmitScalarExpr(E->getArraySize()); + + // Multiply with the type size. + llvm::Value *V = + CGF.Builder.CreateMul(NumElements, + llvm::ConstantInt::get(SizeTy, TypeSizeInBytes)); + + // And add the cookie padding if necessary. + if (CookiePadding) + V = CGF.Builder.CreateAdd(V, llvm::ConstantInt::get(SizeTy, CookiePadding)); + + return V; +} + +static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, + llvm::Value *NewPtr, + llvm::Value *NumElements) { + QualType AllocType = E->getAllocatedType(); + + if (!E->isArray()) { + if (CXXConstructorDecl *Ctor = E->getConstructor()) { + CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, + E->constructor_arg_begin(), + E->constructor_arg_end()); + + return; + } + + // We have a POD type. + if (E->getNumConstructorArgs() == 0) + return; + + assert(E->getNumConstructorArgs() == 1 && + "Can only have one argument to initializer of POD type."); + + const Expr *Init = E->getConstructorArg(0); + + if (!CGF.hasAggregateLLVMType(AllocType)) + CGF.Builder.CreateStore(CGF.EmitScalarExpr(Init), NewPtr); + else if (AllocType->isAnyComplexType()) + CGF.EmitComplexExprIntoAddr(Init, NewPtr, + AllocType.isVolatileQualified()); + else + CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); + return; + } + + if (CXXConstructorDecl *Ctor = E->getConstructor()) + CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr); +} + +llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { + QualType AllocType = E->getAllocatedType(); + FunctionDecl *NewFD = E->getOperatorNew(); + const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>(); + + CallArgList NewArgs; + + // The allocation size is the first argument. + QualType SizeTy = getContext().getSizeType(); + + llvm::Value *NumElements = 0; + llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements); + + NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); + + // Emit the rest of the arguments. + // FIXME: Ideally, this should just use EmitCallArgs. + CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); + + // First, use the types from the function type. + // We start at 1 here because the first argument (the allocation size) + // has already been emitted. + for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { + QualType ArgType = NewFTy->getArgType(i); + + assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). + getTypePtr() == + getContext().getCanonicalType(NewArg->getType()).getTypePtr() && + "type mismatch in call argument!"); + + NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), + ArgType)); + + } + + // Either we've emitted all the call args, or we have a call to a + // variadic function. + assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && + "Extra arguments in non-variadic function!"); + + // If we still have any arguments, emit them using the type of the argument. + for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); + NewArg != NewArgEnd; ++NewArg) { + QualType ArgType = NewArg->getType(); + NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), + ArgType)); + } + + // Emit the call to new. + RValue RV = + EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), + CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD); + + // If an allocation function is declared with an empty exception specification + // it returns null to indicate failure to allocate storage. [expr.new]p13. + // (We don't need to check for null when there's no new initializer and + // we're allocating a POD type). + bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && + !(AllocType->isPODType() && !E->hasInitializer()); + + llvm::BasicBlock *NewNull = 0; + llvm::BasicBlock *NewNotNull = 0; + llvm::BasicBlock *NewEnd = 0; + + llvm::Value *NewPtr = RV.getScalarVal(); + + if (NullCheckResult) { + NewNull = createBasicBlock("new.null"); + NewNotNull = createBasicBlock("new.notnull"); + NewEnd = createBasicBlock("new.end"); + + llvm::Value *IsNull = + Builder.CreateICmpEQ(NewPtr, + llvm::Constant::getNullValue(NewPtr->getType()), + "isnull"); + + Builder.CreateCondBr(IsNull, NewNull, NewNotNull); + EmitBlock(NewNotNull); + } + + if (uint64_t CookiePadding = CalculateCookiePadding(getContext(), E)) { + uint64_t CookieOffset = + CookiePadding - getContext().getTypeSize(SizeTy) / 8; + + llvm::Value *NumElementsPtr = + Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset); + + NumElementsPtr = Builder.CreateBitCast(NumElementsPtr, + ConvertType(SizeTy)->getPointerTo()); + Builder.CreateStore(NumElements, NumElementsPtr); + + // Now add the padding to the new ptr. + NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr, CookiePadding); + } + + NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); + + EmitNewInitializer(*this, E, NewPtr, NumElements); + + if (NullCheckResult) { + Builder.CreateBr(NewEnd); + EmitBlock(NewNull); + Builder.CreateBr(NewEnd); + EmitBlock(NewEnd); + + llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); + PHI->reserveOperandSpace(2); + PHI->addIncoming(NewPtr, NewNotNull); + PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull); + + NewPtr = PHI; + } + + return NewPtr; +} + +void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { + if (E->isArrayForm()) { + ErrorUnsupported(E, "delete[] expression"); + return; + }; + + // Get at the argument before we performed the implicit conversion + // to void*. + const Expr *Arg = E->getArgument(); + while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { + if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion && + ICE->getType()->isVoidPointerType()) + Arg = ICE->getSubExpr(); + else + break; + } + + QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType(); + + llvm::Value *Ptr = EmitScalarExpr(Arg); + + // Null check the pointer. + llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); + llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); + + llvm::Value *IsNull = + Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()), + "isnull"); + + Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); + EmitBlock(DeleteNotNull); + + // Call the destructor if necessary. + if (const RecordType *RT = DeleteTy->getAs<RecordType>()) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (!RD->hasTrivialDestructor()) { + const CXXDestructorDecl *Dtor = RD->getDestructor(getContext()); + if (Dtor->isVirtual()) { + const llvm::Type *Ty = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor), + /*isVariadic=*/false); + + llvm::Value *Callee = BuildVirtualCall(Dtor, Ptr, Ty); + EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0); + } else + EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr); + } + } + } + + // Call delete. + FunctionDecl *DeleteFD = E->getOperatorDelete(); + const FunctionProtoType *DeleteFTy = + DeleteFD->getType()->getAs<FunctionProtoType>(); + + CallArgList DeleteArgs; + + QualType ArgTy = DeleteFTy->getArgType(0); + llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); + DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); + + // Emit the call to delete. + EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), + DeleteArgs), + CGM.GetAddrOfFunction(DeleteFD), + DeleteArgs, DeleteFD); + + EmitBlock(DeleteEnd); +} diff --git a/lib/CodeGen/CGCXXTemp.cpp b/lib/CodeGen/CGCXXTemp.cpp index a6e6d11505b63..4768556f6bcac 100644 --- a/lib/CodeGen/CGCXXTemp.cpp +++ b/lib/CodeGen/CGCXXTemp.cpp @@ -15,29 +15,29 @@ using namespace clang; using namespace CodeGen; -void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, +void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, llvm::Value *Ptr) { llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor"); - + llvm::Value *CondPtr = 0; - - // Check if temporaries need to be conditional. If so, we'll create a - // condition boolean, initialize it to 0 and + + // Check if temporaries need to be conditional. If so, we'll create a + // condition boolean, initialize it to 0 and if (!ConditionalTempDestructionStack.empty()) { - CondPtr = CreateTempAlloca(llvm::Type::Int1Ty, "cond"); - + CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond"); + // Initialize it to false. This initialization takes place right after // the alloca insert point. - llvm::StoreInst *SI = - new llvm::StoreInst(llvm::ConstantInt::getFalse(), CondPtr); + llvm::StoreInst *SI = + new llvm::StoreInst(llvm::ConstantInt::getFalse(VMContext), CondPtr); llvm::BasicBlock *Block = AllocaInsertPt->getParent(); Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI); // Now set it to true. - Builder.CreateStore(llvm::ConstantInt::getTrue(), CondPtr); + Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr); } - - LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock, + + LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock, CondPtr)); PushCleanupBlock(DtorBlock); @@ -45,16 +45,22 @@ void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary, void CodeGenFunction::PopCXXTemporary() { const CXXLiveTemporaryInfo& Info = LiveTemporaries.back(); - + CleanupBlockInfo CleanupInfo = PopCleanupBlock(); - assert(CleanupInfo.CleanupBlock == Info.DtorBlock && + assert(CleanupInfo.CleanupBlock == Info.DtorBlock && "Cleanup block mismatch!"); - assert(!CleanupInfo.SwitchBlock && + assert(!CleanupInfo.SwitchBlock && "Should not have a switch block for temporary cleanup!"); - assert(!CleanupInfo.EndBlock && + assert(!CleanupInfo.EndBlock && "Should not have an end block for temporary cleanup!"); - - EmitBlock(Info.DtorBlock); + + llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); + if (CurBB && !CurBB->getTerminator() && + Info.DtorBlock->getNumUses() == 0) { + CurBB->getInstList().splice(CurBB->end(), Info.DtorBlock->getInstList()); + delete Info.DtorBlock; + } else + EmitBlock(Info.DtorBlock); llvm::BasicBlock *CondEnd = 0; @@ -63,52 +69,80 @@ void CodeGenFunction::PopCXXTemporary() { if (Info.CondPtr) { llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call"); CondEnd = createBasicBlock("cond.dtor.end"); - + llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr); Builder.CreateCondBr(Cond, CondBlock, CondEnd); EmitBlock(CondBlock); } - + EmitCXXDestructorCall(Info.Temporary->getDestructor(), Dtor_Complete, Info.ThisPtr); if (CondEnd) { // Reset the condition. to false. - Builder.CreateStore(llvm::ConstantInt::getFalse(), Info.CondPtr); + Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr); EmitBlock(CondEnd); } - + LiveTemporaries.pop_back(); } RValue CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, llvm::Value *AggLoc, - bool isAggLocVolatile) { + bool IsAggLocVolatile, + bool IsInitializer) { // If we shouldn't destroy the temporaries, just emit the // child expression. if (!E->shouldDestroyTemporaries()) - return EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile); + return EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, + /*IgnoreResult=*/false, IsInitializer); // Keep track of the current cleanup stack depth. size_t CleanupStackDepth = CleanupEntries.size(); (void) CleanupStackDepth; unsigned OldNumLiveTemporaries = LiveTemporaries.size(); - - RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile); - + + RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, + /*IgnoreResult=*/false, IsInitializer); + // Pop temporaries. while (LiveTemporaries.size() > OldNumLiveTemporaries) PopCXXTemporary(); - + assert(CleanupEntries.size() == CleanupStackDepth && "Cleanup size mismatch!"); - + return RV; } -void +LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue( + const CXXExprWithTemporaries *E) { + // If we shouldn't destroy the temporaries, just emit the + // child expression. + if (!E->shouldDestroyTemporaries()) + return EmitLValue(E->getSubExpr()); + + // Keep track of the current cleanup stack depth. + size_t CleanupStackDepth = CleanupEntries.size(); + (void) CleanupStackDepth; + + unsigned OldNumLiveTemporaries = LiveTemporaries.size(); + + LValue LV = EmitLValue(E->getSubExpr()); + + // Pop temporaries. + while (LiveTemporaries.size() > OldNumLiveTemporaries) + PopCXXTemporary(); + + assert(CleanupEntries.size() == CleanupStackDepth && + "Cleanup size mismatch!"); + + return LV; +} + +void CodeGenFunction::PushConditionalTempDestruction() { // Store the current number of live temporaries. ConditionalTempDestructionStack.push_back(LiveTemporaries.size()); @@ -117,13 +151,13 @@ CodeGenFunction::PushConditionalTempDestruction() { void CodeGenFunction::PopConditionalTempDestruction() { size_t NumLiveTemporaries = ConditionalTempDestructionStack.back(); ConditionalTempDestructionStack.pop_back(); - + // Pop temporaries. while (LiveTemporaries.size() > NumLiveTemporaries) { - assert(LiveTemporaries.back().CondPtr && + assert(LiveTemporaries.back().CondPtr && "Conditional temporary must have a cond ptr!"); PopCXXTemporary(); - } + } } - + diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 97391bc620be7..bad166f01ef5d 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -33,19 +33,49 @@ using namespace CodeGen; // FIXME: Use iterator and sidestep silly type array creation. -const +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionNoProtoType *FTNP) { - return getFunctionInfo(FTNP->getResultType(), - llvm::SmallVector<QualType, 16>()); + // FIXME: Set calling convention correctly, it needs to be associated with the + // type somehow. + return getFunctionInfo(FTNP->getResultType(), + llvm::SmallVector<QualType, 16>(), 0); } -const +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionProtoType *FTP) { llvm::SmallVector<QualType, 16> ArgTys; // FIXME: Kill copy. for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) ArgTys.push_back(FTP->getArgType(i)); - return getFunctionInfo(FTP->getResultType(), ArgTys); + // FIXME: Set calling convention correctly, it needs to be associated with the + // type somehow. + return getFunctionInfo(FTP->getResultType(), ArgTys, 0); +} + +static unsigned getCallingConventionForDecl(const Decl *D) { + // Set the appropriate calling convention for the Function. + if (D->hasAttr<StdCallAttr>()) + return llvm::CallingConv::X86_StdCall; + + if (D->hasAttr<FastCallAttr>()) + return llvm::CallingConv::X86_FastCall; + + return llvm::CallingConv::C; +} + +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD, + const FunctionProtoType *FTP) { + llvm::SmallVector<QualType, 16> ArgTys; + + // Add the 'this' pointer. + ArgTys.push_back(Context.getPointerType(Context.getTagDeclType(RD))); + + for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) + ArgTys.push_back(FTP->getArgType(i)); + + // FIXME: Set calling convention correctly, it needs to be associated with the + // type somehow. + return getFunctionInfo(FTP->getResultType(), ArgTys, 0); } const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) { @@ -53,22 +83,32 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) { // Add the 'this' pointer unless this is a static method. if (MD->isInstance()) ArgTys.push_back(MD->getThisType(Context)); - - const FunctionProtoType *FTP = MD->getType()->getAsFunctionProtoType(); + + const FunctionProtoType *FTP = MD->getType()->getAs<FunctionProtoType>(); for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) ArgTys.push_back(FTP->getArgType(i)); - return getFunctionInfo(FTP->getResultType(), ArgTys); + return getFunctionInfo(FTP->getResultType(), ArgTys, + getCallingConventionForDecl(MD)); } const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) { if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) if (MD->isInstance()) return getFunctionInfo(MD); + + unsigned CallingConvention = getCallingConventionForDecl(FD); + const FunctionType *FTy = FD->getType()->getAs<FunctionType>(); + if (const FunctionNoProtoType *FNTP = dyn_cast<FunctionNoProtoType>(FTy)) + return getFunctionInfo(FNTP->getResultType(), + llvm::SmallVector<QualType, 16>(), + CallingConvention); - const FunctionType *FTy = FD->getType()->getAsFunctionType(); - if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FTy)) - return getFunctionInfo(FTP); - return getFunctionInfo(cast<FunctionNoProtoType>(FTy)); + const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy); + llvm::SmallVector<QualType, 16> ArgTys; + // FIXME: Kill copy. + for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i) + ArgTys.push_back(FPT->getArgType(i)); + return getFunctionInfo(FPT->getResultType(), ArgTys, CallingConvention); } const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) { @@ -79,34 +119,39 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) { for (ObjCMethodDecl::param_iterator i = MD->param_begin(), e = MD->param_end(); i != e; ++i) ArgTys.push_back((*i)->getType()); - return getFunctionInfo(MD->getResultType(), ArgTys); + return getFunctionInfo(MD->getResultType(), ArgTys, + getCallingConventionForDecl(MD)); } -const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, - const CallArgList &Args) { +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, + const CallArgList &Args, + unsigned CallingConvention){ // FIXME: Kill copy. llvm::SmallVector<QualType, 16> ArgTys; - for (CallArgList::const_iterator i = Args.begin(), e = Args.end(); + for (CallArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i) ArgTys.push_back(i->second); - return getFunctionInfo(ResTy, ArgTys); + return getFunctionInfo(ResTy, ArgTys, CallingConvention); } -const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, - const FunctionArgList &Args) { +const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, + const FunctionArgList &Args, + unsigned CallingConvention){ // FIXME: Kill copy. llvm::SmallVector<QualType, 16> ArgTys; - for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); + for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i) ArgTys.push_back(i->second); - return getFunctionInfo(ResTy, ArgTys); + return getFunctionInfo(ResTy, ArgTys, CallingConvention); } const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, - const llvm::SmallVector<QualType, 16> &ArgTys) { + const llvm::SmallVector<QualType, 16> &ArgTys, + unsigned CallingConvention){ // Lookup or create unique function info. llvm::FoldingSetNodeID ID; - CGFunctionInfo::Profile(ID, ResTy, ArgTys.begin(), ArgTys.end()); + CGFunctionInfo::Profile(ID, CallingConvention, ResTy, + ArgTys.begin(), ArgTys.end()); void *InsertPos = 0; CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, InsertPos); @@ -114,17 +159,21 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(QualType ResTy, return *FI; // Construct the function info. - FI = new CGFunctionInfo(ResTy, ArgTys); + FI = new CGFunctionInfo(CallingConvention, ResTy, ArgTys); FunctionInfos.InsertNode(FI, InsertPos); // Compute ABI information. - getABIInfo().computeInfo(*FI, getContext()); + getABIInfo().computeInfo(*FI, getContext(), TheModule.getContext()); return *FI; } -CGFunctionInfo::CGFunctionInfo(QualType ResTy, - const llvm::SmallVector<QualType, 16> &ArgTys) { +CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention, + QualType ResTy, + const llvm::SmallVector<QualType, 16> &ArgTys) + : CallingConvention(_CallingConvention), + EffectiveCallingConvention(_CallingConvention) +{ NumArgs = ArgTys.size(); Args = new ArgInfo[1 + NumArgs]; Args[0].type = ResTy; @@ -134,20 +183,20 @@ CGFunctionInfo::CGFunctionInfo(QualType ResTy, /***/ -void CodeGenTypes::GetExpandedTypes(QualType Ty, +void CodeGenTypes::GetExpandedTypes(QualType Ty, std::vector<const llvm::Type*> &ArgTys) { const RecordType *RT = Ty->getAsStructureType(); assert(RT && "Can only expand structure types."); const RecordDecl *RD = RT->getDecl(); - assert(!RD->hasFlexibleArrayMember() && + assert(!RD->hasFlexibleArrayMember() && "Cannot expand structure with flexible array."); - + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { const FieldDecl *FD = *i; - assert(!FD->isBitField() && + assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); - + QualType FT = FD->getType(); if (CodeGenFunction::hasAggregateLLVMType(FT)) { GetExpandedTypes(FT, ArgTys); @@ -157,19 +206,19 @@ void CodeGenTypes::GetExpandedTypes(QualType Ty, } } -llvm::Function::arg_iterator +llvm::Function::arg_iterator CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, llvm::Function::arg_iterator AI) { const RecordType *RT = Ty->getAsStructureType(); assert(RT && "Can only expand structure types."); RecordDecl *RD = RT->getDecl(); - assert(LV.isSimple() && - "Unexpected non-simple lvalue during struct expansion."); + assert(LV.isSimple() && + "Unexpected non-simple lvalue during struct expansion."); llvm::Value *Addr = LV.getAddress(); for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { - FieldDecl *FD = *i; + FieldDecl *FD = *i; QualType FT = FD->getType(); // FIXME: What are the right qualifiers here? @@ -185,8 +234,8 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, return AI; } -void -CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, +void +CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, llvm::SmallVector<llvm::Value*, 16> &Args) { const RecordType *RT = Ty->getAsStructureType(); assert(RT && "Can only expand structure types."); @@ -196,16 +245,16 @@ CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, llvm::Value *Addr = RV.getAggregateAddr(); for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) { - FieldDecl *FD = *i; + FieldDecl *FD = *i; QualType FT = FD->getType(); - + // FIXME: What are the right qualifiers here? LValue LV = EmitLValueForField(Addr, FD, false, 0); if (CodeGenFunction::hasAggregateLLVMType(FT)) { ExpandTypeToArgs(FT, RValue::getAggregate(LV.getAddress()), Args); } else { RValue RV = EmitLoadOfLValue(LV, FT); - assert(RV.isScalar() && + assert(RV.isScalar() && "Unexpected non-scalar rvalue during struct expansion."); Args.push_back(RV.getScalarVal()); } @@ -221,7 +270,7 @@ CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, const llvm::Type *Ty, CodeGenFunction &CGF) { - const llvm::Type *SrcTy = + const llvm::Type *SrcTy = cast<llvm::PointerType>(SrcPtr->getType())->getElementType(); uint64_t SrcSize = CGF.CGM.getTargetData().getTypeAllocSize(SrcTy); uint64_t DstSize = CGF.CGM.getTargetData().getTypeAllocSize(Ty); @@ -244,9 +293,9 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr, // Otherwise do coercion through memory. This is stupid, but // simple. llvm::Value *Tmp = CGF.CreateTempAlloca(Ty); - llvm::Value *Casted = + llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(SrcTy)); - llvm::StoreInst *Store = + llvm::StoreInst *Store = CGF.Builder.CreateStore(CGF.Builder.CreateLoad(SrcPtr), Casted); // FIXME: Use better alignment / avoid requiring aligned store. Store->setAlignment(1); @@ -263,7 +312,7 @@ static void CreateCoercedStore(llvm::Value *Src, llvm::Value *DstPtr, CodeGenFunction &CGF) { const llvm::Type *SrcTy = Src->getType(); - const llvm::Type *DstTy = + const llvm::Type *DstTy = cast<llvm::PointerType>(DstPtr->getType())->getElementType(); uint64_t SrcSize = CGF.CGM.getTargetData().getTypeAllocSize(SrcTy); @@ -287,7 +336,7 @@ static void CreateCoercedStore(llvm::Value *Src, // to that information. llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy); CGF.Builder.CreateStore(Src, Tmp); - llvm::Value *Casted = + llvm::Value *Casted = CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(DstTy)); llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted); // FIXME: Use better alignment / avoid requiring aligned load. @@ -321,25 +370,25 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) { case ABIArgInfo::Indirect: { assert(!RetAI.getIndirectAlign() && "Align unused on indirect return."); - ResultType = llvm::Type::VoidTy; + ResultType = llvm::Type::getVoidTy(getLLVMContext()); const llvm::Type *STy = ConvertType(RetTy); ArgTys.push_back(llvm::PointerType::get(STy, RetTy.getAddressSpace())); break; } case ABIArgInfo::Ignore: - ResultType = llvm::Type::VoidTy; + ResultType = llvm::Type::getVoidTy(getLLVMContext()); break; case ABIArgInfo::Coerce: ResultType = RetAI.getCoerceToType(); break; } - - for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), + + for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) { const ABIArgInfo &AI = it->info; - + switch (AI.getKind()) { case ABIArgInfo::Ignore: break; @@ -359,7 +408,7 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) { case ABIArgInfo::Direct: ArgTys.push_back(ConvertType(it->type)); break; - + case ABIArgInfo::Expand: GetExpandedTypes(it->type, ArgTys); break; @@ -371,10 +420,13 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic) { void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, const Decl *TargetDecl, - AttributeListType &PAL) { + AttributeListType &PAL, + unsigned &CallingConv) { unsigned FuncAttrs = 0; unsigned RetAttrs = 0; + CallingConv = FI.getEffectiveCallingConvention(); + // FIXME: handle sseregparm someday... if (TargetDecl) { if (TargetDecl->hasAttr<NoThrowAttr>()) @@ -385,6 +437,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, FuncAttrs |= llvm::Attribute::ReadNone; else if (TargetDecl->hasAttr<PureAttr>()) FuncAttrs |= llvm::Attribute::ReadOnly; + if (TargetDecl->hasAttr<MallocAttr>()) + RetAttrs |= llvm::Attribute::NoAlias; } if (CompileOpts.DisableRedZone) @@ -412,7 +466,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, break; case ABIArgInfo::Indirect: - PAL.push_back(llvm::AttributeWithIndex::get(Index, + PAL.push_back(llvm::AttributeWithIndex::get(Index, llvm::Attribute::StructRet | llvm::Attribute::NoAlias)); ++Index; @@ -426,7 +480,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, break; case ABIArgInfo::Expand: - assert(0 && "Invalid ABI kind for return argument"); + assert(0 && "Invalid ABI kind for return argument"); } if (RetAttrs) @@ -437,12 +491,12 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // register variable. signed RegParm = 0; if (TargetDecl) - if (const RegparmAttr *RegParmAttr + if (const RegparmAttr *RegParmAttr = TargetDecl->getAttr<RegparmAttr>()) RegParm = RegParmAttr->getNumParams(); unsigned PointerWidth = getContext().Target.getPointerWidth(0); - for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), + for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) { QualType ParamType = it->type; const ABIArgInfo &AI = it->info; @@ -453,7 +507,9 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, break; case ABIArgInfo::Indirect: - Attributes |= llvm::Attribute::ByVal; + if (AI.getIndirectByVal()) + Attributes |= llvm::Attribute::ByVal; + Attributes |= llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign()); // byval disables readnone and readonly. @@ -481,10 +537,10 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: // Skip increment, no matching LLVM parameter. - continue; + continue; case ABIArgInfo::Expand: { - std::vector<const llvm::Type*> Tys; + std::vector<const llvm::Type*> Tys; // FIXME: This is rather inefficient. Do we ever actually need to do // anything here? The result should be just reconstructed on the other // side, so extension should be a non-issue. @@ -493,7 +549,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, continue; } } - + if (Attributes) PAL.push_back(llvm::AttributeWithIndex::get(Index, Attributes)); ++Index; @@ -505,18 +561,31 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Function *Fn, const FunctionArgList &Args) { + // If this is an implicit-return-zero function, go ahead and + // initialize the return value. TODO: it might be nice to have + // a more general mechanism for this that didn't require synthesized + // return statements. + if (const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) { + if (FD->hasImplicitReturnZero()) { + QualType RetTy = FD->getResultType().getUnqualifiedType(); + const llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy); + llvm::Constant* Zero = llvm::Constant::getNullValue(LLVMTy); + Builder.CreateStore(Zero, ReturnValue); + } + } + // FIXME: We no longer need the types from FunctionArgList; lift up and // simplify. // Emit allocs for param decls. Give the LLVM Argument nodes names. llvm::Function::arg_iterator AI = Fn->arg_begin(); - + // Name the struct return argument. if (CGM.ReturnTypeUsesSret(FI)) { AI->setName("agg.result"); ++AI; } - + assert(FI.arg_size() == Args.size() && "Mismatch between function signature & arguments."); CGFunctionInfo::const_arg_iterator info_it = FI.arg_begin(); @@ -541,7 +610,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, V = EmitScalarConversion(V, Ty, Arg->getType()); } } - EmitParmDecl(*Arg, V); + EmitParmDecl(*Arg, V); break; } @@ -565,36 +634,36 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, EmitParmDecl(*Arg, V); break; } - + case ABIArgInfo::Expand: { // If this structure was expanded into multiple arguments then // we need to create a temporary and reconstruct it from the // arguments. std::string Name = Arg->getNameAsString(); - llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(Ty), + llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(Ty), (Name + ".addr").c_str()); // FIXME: What are the right qualifiers here? - llvm::Function::arg_iterator End = - ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp,0), AI); + llvm::Function::arg_iterator End = + ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI); EmitParmDecl(*Arg, Temp); // Name the arguments used in expansion and increment AI. unsigned Index = 0; for (; AI != End; ++AI, ++Index) - AI->setName(Name + "." + llvm::utostr(Index)); + AI->setName(Name + "." + llvm::Twine(Index)); continue; } case ABIArgInfo::Ignore: // Initialize the local variable appropriately. - if (hasAggregateLLVMType(Ty)) { + if (hasAggregateLLVMType(Ty)) { EmitParmDecl(*Arg, CreateTempAlloca(ConvertTypeForMem(Ty))); } else { EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType()))); } - + // Skip increment, no matching LLVM parameter. - continue; + continue; case ABIArgInfo::Coerce: { assert(AI != Fn->arg_end() && "Argument mismatch!"); @@ -653,16 +722,16 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: break; - + case ABIArgInfo::Coerce: RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this); break; case ABIArgInfo::Expand: - assert(0 && "Invalid ABI kind for return argument"); + assert(0 && "Invalid ABI kind for return argument"); } } - + if (RV) { Builder.CreateRet(RV); } else { @@ -673,12 +742,12 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) { if (ArgType->isReferenceType()) return EmitReferenceBindingToExpr(E, ArgType); - + return EmitAnyExprToTemp(E); } RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, - llvm::Value *Callee, + llvm::Value *Callee, const CallArgList &CallArgs, const Decl *TargetDecl) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. @@ -688,17 +757,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // location that we would like to return into. QualType RetTy = CallInfo.getReturnType(); const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); - - + + // If the call returns a temporary with struct return, create a temporary // alloca to hold the result. if (CGM.ReturnTypeUsesSret(CallInfo)) Args.push_back(CreateTempAlloca(ConvertTypeForMem(RetTy))); - + assert(CallInfo.arg_size() == CallArgs.size() && "Mismatch between function signature & arguments."); CGFunctionInfo::const_arg_iterator info_it = CallInfo.arg_begin(); - for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); + for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); I != E; ++I, ++info_it) { const ABIArgInfo &ArgInfo = info_it->info; RValue RV = I->first; @@ -711,7 +780,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (RV.isScalar()) EmitStoreOfScalar(RV.getScalarVal(), Args.back(), false, I->second); else - StoreComplexToAddr(RV.getComplexVal(), Args.back(), false); + StoreComplexToAddr(RV.getComplexVal(), Args.back(), false); } else { Args.push_back(RV.getAggregateAddr()); } @@ -730,7 +799,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Args.push_back(Builder.CreateLoad(RV.getAggregateAddr())); } break; - + case ABIArgInfo::Ignore: break; @@ -743,9 +812,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else if (RV.isComplex()) { SrcPtr = CreateTempAlloca(ConvertTypeForMem(I->second), "coerce"); StoreComplexToAddr(RV.getComplexVal(), SrcPtr, false); - } else + } else SrcPtr = RV.getAggregateAddr(); - Args.push_back(CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(), + Args.push_back(CreateCoercedLoad(SrcPtr, ArgInfo.getCoerceToType(), *this)); break; } @@ -755,7 +824,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, break; } } - + // If the callee is a bitcast of a function to a varargs pointer to function // type, check to see if we can remove the bitcast. This handles some cases // with unprototyped functions. @@ -765,7 +834,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, const llvm::FunctionType *CurFT = cast<llvm::FunctionType>(CurPT->getElementType()); const llvm::FunctionType *ActualFT = CalleeF->getFunctionType(); - + if (CE->getOpcode() == llvm::Instruction::BitCast && ActualFT->getReturnType() == CurFT->getReturnType() && ActualFT->getNumParams() == CurFT->getNumParams() && @@ -776,7 +845,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, ArgsMatch = false; break; } - + // Strip the cast if we can get away with it. This is a nice cleanup, // but also allows us to inline the function at -O0 if it is marked // always_inline. @@ -784,28 +853,27 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Callee = CalleeF; } } - + llvm::BasicBlock *InvokeDest = getInvokeDest(); + unsigned CallingConv; CodeGen::AttributeListType AttributeList; - CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList); + CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList, CallingConv); llvm::AttrListPtr Attrs = llvm::AttrListPtr::get(AttributeList.begin(), AttributeList.end()); - + llvm::CallSite CS; if (!InvokeDest || (Attrs.getFnAttributes() & llvm::Attribute::NoUnwind)) { CS = Builder.CreateCall(Callee, Args.data(), Args.data()+Args.size()); } else { llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); - CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, + CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, Args.data(), Args.data()+Args.size()); EmitBlock(Cont); } CS.setAttributes(Attrs); - if (const llvm::Function *F = - dyn_cast<llvm::Function>(Callee->stripPointerCasts())) - CS.setCallingConv(F->getCallingConv()); + CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); // If the call doesn't return, finish the basic block and clear the // insertion point; this allows the rest of IRgen to discard @@ -813,18 +881,18 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (CS.doesNotReturn()) { Builder.CreateUnreachable(); Builder.ClearInsertionPoint(); - + // FIXME: For now, emit a dummy basic block because expr emitters in // generally are not ready to handle emitting expressions at unreachable // points. EnsureInsertPoint(); - + // Return a reasonable RValue. return GetUndefRValue(RetTy); - } + } llvm::Instruction *CI = CS.getInstruction(); - if (Builder.isNamePreserving() && CI->getType() != llvm::Type::VoidTy) + if (Builder.isNamePreserving() && !CI->getType()->isVoidTy()) CI->setName("call"); switch (RetAI.getKind()) { @@ -866,7 +934,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } case ABIArgInfo::Expand: - assert(0 && "Invalid ABI kind for return argument"); + assert(0 && "Invalid ABI kind for return argument"); } assert(0 && "Unhandled ABIArgInfo::Kind"); diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h index daf6f00045012..ebf801dcaad1e 100644 --- a/lib/CodeGen/CGCall.h +++ b/lib/CodeGen/CGCall.h @@ -49,9 +49,9 @@ namespace CodeGen { /// FunctionArgList - Type for representing both the decl and type /// of parameters to a function. The decl must be either a /// ParmVarDecl or ImplicitParamDecl. - typedef llvm::SmallVector<std::pair<const VarDecl*, QualType>, + typedef llvm::SmallVector<std::pair<const VarDecl*, QualType>, 16> FunctionArgList; - + /// CGFunctionInfo - Class to encapsulate the information about a /// function definition. class CGFunctionInfo : public llvm::FoldingSetNode { @@ -60,6 +60,14 @@ namespace CodeGen { ABIArgInfo info; }; + /// The LLVM::CallingConv to use for this function (as specified by the + /// user). + unsigned CallingConvention; + + /// The LLVM::CallingConv to actually use for this function, which may + /// depend on the ABI. + unsigned EffectiveCallingConvention; + unsigned NumArgs; ArgInfo *Args; @@ -67,7 +75,8 @@ namespace CodeGen { typedef const ArgInfo *const_arg_iterator; typedef ArgInfo *arg_iterator; - CGFunctionInfo(QualType ResTy, + CGFunctionInfo(unsigned CallingConvention, + QualType ResTy, const llvm::SmallVector<QualType, 16> &ArgTys); ~CGFunctionInfo() { delete[] Args; } @@ -78,21 +87,37 @@ namespace CodeGen { unsigned arg_size() const { return NumArgs; } + /// getCallingConvention - Return the user specified calling + /// convention. + unsigned getCallingConvention() const { return CallingConvention; } + + /// getEffectiveCallingConvention - Return the actual calling convention to + /// use, which may depend on the ABI. + unsigned getEffectiveCallingConvention() const { + return EffectiveCallingConvention; + } + void setEffectiveCallingConvention(unsigned Value) { + EffectiveCallingConvention = Value; + } + QualType getReturnType() const { return Args[0].type; } ABIArgInfo &getReturnInfo() { return Args[0].info; } const ABIArgInfo &getReturnInfo() const { return Args[0].info; } void Profile(llvm::FoldingSetNodeID &ID) { + ID.AddInteger(getCallingConvention()); getReturnType().Profile(ID); for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it) it->type.Profile(ID); } template<class Iterator> - static void Profile(llvm::FoldingSetNodeID &ID, + static void Profile(llvm::FoldingSetNodeID &ID, + unsigned CallingConvention, QualType ResTy, Iterator begin, Iterator end) { + ID.AddInteger(CallingConvention); ResTy.Profile(ID); for (; begin != end; ++begin) begin->Profile(ID); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 2bf8a222a2531..4c624205b4cac 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CGDebugInfo.h" +#include "CodeGenFunction.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -19,6 +20,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/Version.h" #include "clang/Frontend/CompileOptions.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -47,6 +49,22 @@ void CGDebugInfo::setLocation(SourceLocation Loc) { CurLoc = M->getContext().getSourceManager().getInstantiationLoc(Loc); } +/// getContext - Get context info for the decl. +llvm::DIDescriptor CGDebugInfo::getContext(const VarDecl *Decl, + llvm::DIDescriptor &CompileUnit) { + if (Decl->isFileVarDecl()) + return CompileUnit; + if (Decl->getDeclContext()->isFunctionOrMethod()) { + // Find the last subprogram in region stack. + for (unsigned RI = RegionStack.size(), RE = 0; RI != RE; --RI) { + llvm::DIDescriptor R = RegionStack[RI - 1]; + if (R.isSubprogram()) + return R; + } + } + return CompileUnit; +} + /// getOrCreateCompileUnit - Get the compile unit from the cache or create a new /// one if necessary. This returns null for invalid source locations. llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { @@ -59,7 +77,7 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { FileName = PLoc.getFilename(); FID = PLoc.getIncludeLoc().getRawEncoding(); } - + // See if this compile unit has been used before. llvm::DICompileUnit &Unit = CompileUnitCache[FID]; if (!Unit.isNull()) return Unit; @@ -104,7 +122,11 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { LangTag = llvm::dwarf::DW_LANG_C89; } - std::string Producer = "clang 1.0";// FIXME: clang version. + std::string Producer = +#ifdef CLANG_VENDOR + CLANG_VENDOR +#endif + "clang " CLANG_VERSION_STRING; bool isOptimized = LO.Optimize; const char *Flags = ""; // FIXME: Encode command line options. @@ -112,10 +134,10 @@ llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) { unsigned RuntimeVers = 0; if (LO.ObjC1) RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1; - + // Create new compile unit. return Unit = DebugFactory.CreateCompileUnit(LangTag, AbsFileName.getLast(), - AbsFileName.getDirname(), + AbsFileName.getDirname(), Producer, isMain, isOptimized, Flags, RuntimeVers); } @@ -143,14 +165,15 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break; case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break; case BuiltinType::Float: + case BuiltinType::LongDouble: case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break; - } + } // Bit size, align and offset of the type. uint64_t Size = M->getContext().getTypeSize(BT); uint64_t Align = M->getContext().getTypeAlign(BT); uint64_t Offset = 0; - - return DebugFactory.CreateBasicType(Unit, + + return DebugFactory.CreateBasicType(Unit, BT->getName(M->getContext().getLangOptions()), Unit, 0, Size, Align, Offset, /*flags*/ 0, Encoding); @@ -162,52 +185,72 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty, unsigned Encoding = llvm::dwarf::DW_ATE_complex_float; if (Ty->isComplexIntegerType()) Encoding = llvm::dwarf::DW_ATE_lo_user; - + uint64_t Size = M->getContext().getTypeSize(Ty); uint64_t Align = M->getContext().getTypeAlign(Ty); uint64_t Offset = 0; - + return DebugFactory.CreateBasicType(Unit, "complex", Unit, 0, Size, Align, Offset, /*flags*/ 0, Encoding); } -/// getOrCreateCVRType - Get the CVR qualified type from the cache or create +/// CreateCVRType - Get the qualified type from the cache or create /// a new one if necessary. -llvm::DIType CGDebugInfo::CreateCVRType(QualType Ty, llvm::DICompileUnit Unit) { +llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit Unit) { + QualifierCollector Qc; + const Type *T = Qc.strip(Ty); + + // Ignore these qualifiers for now. + Qc.removeObjCGCAttr(); + Qc.removeAddressSpace(); + // We will create one Derived type for one qualifier and recurse to handle any // additional ones. - llvm::DIType FromTy; unsigned Tag; - if (Ty.isConstQualified()) { + if (Qc.hasConst()) { Tag = llvm::dwarf::DW_TAG_const_type; - Ty.removeConst(); - FromTy = getOrCreateType(Ty, Unit); - } else if (Ty.isVolatileQualified()) { + Qc.removeConst(); + } else if (Qc.hasVolatile()) { Tag = llvm::dwarf::DW_TAG_volatile_type; - Ty.removeVolatile(); - FromTy = getOrCreateType(Ty, Unit); - } else { - assert(Ty.isRestrictQualified() && "Unknown type qualifier for debug info"); + Qc.removeVolatile(); + } else if (Qc.hasRestrict()) { Tag = llvm::dwarf::DW_TAG_restrict_type; - Ty.removeRestrict(); - FromTy = getOrCreateType(Ty, Unit); + Qc.removeRestrict(); + } else { + assert(Qc.empty() && "Unknown type qualifier for debug info"); + return getOrCreateType(QualType(T, 0), Unit); } - + + llvm::DIType FromTy = getOrCreateType(Qc.apply(T), Unit); + // No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types. return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(), 0, 0, 0, 0, 0, FromTy); } +llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, + llvm::DICompileUnit Unit) { + llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit); + + // Bit size, align and offset of the type. + uint64_t Size = M->getContext().getTypeSize(Ty); + uint64_t Align = M->getContext().getTypeAlign(Ty); + + return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, + "", llvm::DICompileUnit(), + 0, Size, Align, 0, 0, EltTy); +} + llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, llvm::DICompileUnit Unit) { llvm::DIType EltTy = getOrCreateType(Ty->getPointeeType(), Unit); - + // Bit size, align and offset of the type. uint64_t Size = M->getContext().getTypeSize(Ty); uint64_t Align = M->getContext().getTypeAlign(Ty); - + return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, "", llvm::DICompileUnit(), 0, Size, Align, 0, 0, EltTy); @@ -258,14 +301,16 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); EltTys.clear(); + unsigned Flags = llvm::DIType::FlagAppleBlock; + EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_descriptor", - DefUnit, 0, FieldOffset, 0, 0, 0, + DefUnit, 0, FieldOffset, 0, 0, Flags, llvm::DIType(), Elements); - + // Bit size, align and offset of the type. uint64_t Size = M->getContext().getTypeSize(Ty); uint64_t Align = M->getContext().getTypeAlign(Ty); - + DescTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, "", llvm::DICompileUnit(), 0, Size, Align, 0, 0, EltTy); @@ -329,9 +374,9 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_literal_generic", - DefUnit, 0, FieldOffset, 0, 0, 0, + DefUnit, 0, FieldOffset, 0, 0, Flags, llvm::DIType(), Elements); - + BlockLiteralGenericSet = true; BlockLiteralGeneric = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, @@ -345,7 +390,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, // Typedefs are derived from some other type. If we have a typedef of a // typedef, make sure to emit the whole chain. llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit); - + // We don't set size information, but do specify where the typedef was // declared. std::string TyName = Ty->getDecl()->getNameAsString(); @@ -366,7 +411,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, // Add the result type at least. EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit)); - + // Set up remainder of arguments if there is a prototype. // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'! if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) { @@ -378,7 +423,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIArray EltTypeArray = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); - + return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, Unit, "", llvm::DICompileUnit(), 0, 0, 0, 0, 0, @@ -389,7 +434,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, llvm::DICompileUnit Unit) { RecordDecl *Decl = Ty->getDecl(); - + unsigned Tag; if (Decl->isStruct()) Tag = llvm::dwarf::DW_TAG_structure_type; @@ -412,24 +457,24 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, DefUnit = getOrCreateCompileUnit(Decl->getLocation()); Line = PLoc.getLine(); } - + // Records and classes and unions can all be recursive. To handle them, we // first generate a debug descriptor for the struct as a forward declaration. // Then (if it is a definition) we go through and get debug info for all of // its members. Finally, we create a descriptor for the complete type (which // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. - llvm::DIType FwdDecl = + llvm::DICompositeType FwdDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0, llvm::DIType(), llvm::DIArray()); - + // If this is just a forward declaration, return it. if (!Decl->getDefinition(M->getContext())) return FwdDecl; // Otherwise, insert it into the TypeCache so that recursive uses will find // it. - TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode(); // Convert all the elements. llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; @@ -438,7 +483,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, unsigned FieldNo = 0; for (RecordDecl::field_iterator I = Decl->field_begin(), - E = Decl->field_end(); + E = Decl->field_end(); I != E; ++I, ++FieldNo) { FieldDecl *Field = *I; llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); @@ -454,7 +499,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc); llvm::DICompileUnit FieldDefUnit; unsigned FieldLine = 0; - + if (!PLoc.isInvalid()) { FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc); FieldLine = PLoc.getLine(); @@ -464,18 +509,18 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, uint64_t FieldSize = 0; unsigned FieldAlign = 0; if (!FType->isIncompleteArrayType()) { - + // Bit size, align and offset of the type. FieldSize = M->getContext().getTypeSize(FType); Expr *BitWidth = Field->getBitWidth(); if (BitWidth) FieldSize = BitWidth->EvaluateAsInt(M->getContext()).getZExtValue(); - + FieldAlign = M->getContext().getTypeAlign(FType); } - uint64_t FieldOffset = RL.getFieldOffset(FieldNo); - + uint64_t FieldOffset = RL.getFieldOffset(FieldNo); + // Create a DW_TAG_member node to remember the offset of this field in the // struct. FIXME: This is an absolutely insane way to capture this // information. When we gut debug info, this should be fixed. @@ -485,23 +530,25 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); } - + llvm::DIArray Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); // Bit size, align and offset of the type. uint64_t Size = M->getContext().getTypeSize(Ty); uint64_t Align = M->getContext().getTypeAlign(Ty); - - llvm::DIType RealDecl = + + llvm::DICompositeType RealDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), Elements); + // Update TypeCache. + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl.getNode(); + // Now that we have a real decl for the struct, replace anything using the // old decl with the new one. This will recursively update the debug info. - FwdDecl.getGV()->replaceAllUsesWith(RealDecl.getGV()); - FwdDecl.getGV()->eraseFromParent(); - + FwdDecl.replaceAllUsesWith(RealDecl); + return RealDecl; } @@ -509,7 +556,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DICompileUnit Unit) { ObjCInterfaceDecl *Decl = Ty->getDecl(); - + unsigned Tag = llvm::dwarf::DW_TAG_structure_type; SourceManager &SM = M->getContext().getSourceManager(); @@ -520,7 +567,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation()); unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); - + unsigned RuntimeLang = DefUnit.getLanguage(); // To handle recursive interface, we @@ -529,27 +576,27 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // its members. Finally, we create a descriptor for the complete type (which // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. - llvm::DIType FwdDecl = + llvm::DICompositeType FwdDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0, llvm::DIType(), llvm::DIArray(), RuntimeLang); - + // If this is just a forward declaration, return it. if (Decl->isForwardDecl()) return FwdDecl; // Otherwise, insert it into the TypeCache so that recursive uses will find // it. - TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl.getNode(); // Convert all the elements. llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; ObjCInterfaceDecl *SClass = Decl->getSuperClass(); if (SClass) { - llvm::DIType SClassTy = + llvm::DIType SClassTy = getOrCreateType(M->getContext().getObjCInterfaceType(SClass), Unit); - llvm::DIType InhTag = + llvm::DIType InhTag = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance, Unit, "", llvm::DICompileUnit(), 0, 0, 0, 0 /* offset */, 0, SClassTy); @@ -576,13 +623,13 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, PresumedLoc PLoc = SM.getPresumedLoc(FieldDefLoc); unsigned FieldLine = PLoc.isInvalid() ? 0 : PLoc.getLine(); - + QualType FType = Field->getType(); uint64_t FieldSize = 0; unsigned FieldAlign = 0; if (!FType->isIncompleteArrayType()) { - + // Bit size, align and offset of the type. FieldSize = M->getContext().getTypeSize(FType); Expr *BitWidth = Field->getBitWidth(); @@ -592,14 +639,14 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, FieldAlign = M->getContext().getTypeAlign(FType); } - uint64_t FieldOffset = RL.getFieldOffset(FieldNo); - + uint64_t FieldOffset = RL.getFieldOffset(FieldNo); + unsigned Flags = 0; if (Field->getAccessControl() == ObjCIvarDecl::Protected) Flags = llvm::DIType::FlagProtected; else if (Field->getAccessControl() == ObjCIvarDecl::Private) Flags = llvm::DIType::FlagPrivate; - + // Create a DW_TAG_member node to remember the offset of this field in the // struct. FIXME: This is an absolutely insane way to capture this // information. When we gut debug info, this should be fixed. @@ -609,24 +656,26 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, FieldOffset, Flags, FieldTy); EltTys.push_back(FieldTy); } - + llvm::DIArray Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); // Bit size, align and offset of the type. uint64_t Size = M->getContext().getTypeSize(Ty); uint64_t Align = M->getContext().getTypeAlign(Ty); - - llvm::DIType RealDecl = + + llvm::DICompositeType RealDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), Elements, RuntimeLang); + // Update TypeCache. + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl.getNode(); + // Now that we have a real decl for the struct, replace anything using the // old decl with the new one. This will recursively update the debug info. - FwdDecl.getGV()->replaceAllUsesWith(RealDecl.getGV()); - FwdDecl.getGV()->eraseFromParent(); - + FwdDecl.replaceAllUsesWith(RealDecl); + return RealDecl; } @@ -637,13 +686,13 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators; // Create DIEnumerator elements for each enumerator. - for (EnumDecl::enumerator_iterator + for (EnumDecl::enumerator_iterator Enum = Decl->enumerator_begin(), EnumEnd = Decl->enumerator_end(); Enum != EnumEnd; ++Enum) { Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(), Enum->getInitVal().getZExtValue())); } - + // Return a CompositeType for the enum itself. llvm::DIArray EltArray = DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size()); @@ -655,7 +704,7 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, PresumedLoc PLoc = SM.getPresumedLoc(DefLoc); unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); - + // Size and align of the type. uint64_t Size = 0; unsigned Align = 0; @@ -663,7 +712,7 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, Size = M->getContext().getTypeSize(Ty); Align = M->getContext().getTypeAlign(Ty); } - + return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type, Unit, EnumName, DefUnit, Line, Size, Align, 0, 0, @@ -676,7 +725,7 @@ llvm::DIType CGDebugInfo::CreateType(const TagType *Ty, return CreateType(RT, Unit); else if (const EnumType *ET = dyn_cast<EnumType>(Ty)) return CreateType(ET, Unit); - + return llvm::DIType(); } @@ -684,8 +733,8 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DICompileUnit Unit) { uint64_t Size; uint64_t Align; - - + + // FIXME: make getTypeAlign() aware of VLAs and incomplete array types if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) { Size = 0; @@ -699,7 +748,7 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, Size = M->getContext().getTypeSize(Ty); Align = M->getContext().getTypeAlign(Ty); } - + // Add the dimensions of the array. FIXME: This loses CV qualifiers from // interior arrays, do we care? Why aren't nested arrays represented the // obvious/recursive way? @@ -708,12 +757,13 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, while ((Ty = dyn_cast<ArrayType>(EltTy))) { uint64_t Upper = 0; if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) - Upper = CAT->getSize().getZExtValue() - 1; + if (CAT->getSize().getZExtValue()) + Upper = CAT->getSize().getZExtValue() - 1; // FIXME: Verify this is right for VLAs. Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, Upper)); EltTy = Ty->getElementType(); } - + llvm::DIArray SubscriptArray = DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size()); @@ -731,14 +781,29 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DICompileUnit Unit) { if (Ty.isNull()) return llvm::DIType(); - - // Check to see if the compile unit already has created this type. - llvm::DIType &Slot = TypeCache[Ty.getAsOpaquePtr()]; - if (!Slot.isNull()) return Slot; - // Handle CVR qualifiers, which recursively handles what they refer to. - if (Ty.getCVRQualifiers()) - return Slot = CreateCVRType(Ty, Unit); + // Check for existing entry. + std::map<void *, llvm::WeakVH>::iterator it = + TypeCache.find(Ty.getAsOpaquePtr()); + if (it != TypeCache.end()) { + // Verify that the debug info still exists. + if (&*it->second) + return llvm::DIType(cast<llvm::MDNode>(it->second)); + } + + // Otherwise create the type. + llvm::DIType Res = CreateTypeNode(Ty, Unit); + TypeCache.insert(std::make_pair(Ty.getAsOpaquePtr(), Res.getNode())); + return Res; +} + +/// getOrCreateTypeNode - Get the type metadata node from the cache or create a +/// new one if necessary. +llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, + llvm::DICompileUnit Unit) { + // Handle qualifiers, which recursively handles what they refer to. + if (Ty.hasQualifiers()) + return CreateQualifiedType(Ty, Unit); // Work out details of type. switch (Ty->getTypeClass()) { @@ -748,53 +813,52 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" assert(false && "Dependent types cannot show up in debug information"); - + + default: case Type::LValueReference: case Type::RValueReference: case Type::Vector: case Type::ExtVector: - case Type::ExtQual: case Type::FixedWidthInt: case Type::MemberPointer: case Type::TemplateSpecialization: case Type::QualifiedName: // Unsupported types return llvm::DIType(); - case Type::ObjCObjectPointer: // Encode id<p> in debug info just like id. - return Slot = getOrCreateType(M->getContext().getObjCIdType(), Unit); - - case Type::ObjCQualifiedInterface: // Drop protocols from interface. - case Type::ObjCInterface: - return Slot = CreateType(cast<ObjCInterfaceType>(Ty), Unit); - case Type::Builtin: return Slot = CreateType(cast<BuiltinType>(Ty), Unit); - case Type::Complex: return Slot = CreateType(cast<ComplexType>(Ty), Unit); - case Type::Pointer: return Slot = CreateType(cast<PointerType>(Ty), Unit); + case Type::ObjCObjectPointer: + return CreateType(cast<ObjCObjectPointerType>(Ty), Unit); + case Type::ObjCInterface: + return CreateType(cast<ObjCInterfaceType>(Ty), Unit); + case Type::Builtin: return CreateType(cast<BuiltinType>(Ty), Unit); + case Type::Complex: return CreateType(cast<ComplexType>(Ty), Unit); + case Type::Pointer: return CreateType(cast<PointerType>(Ty), Unit); case Type::BlockPointer: - return Slot = CreateType(cast<BlockPointerType>(Ty), Unit); - case Type::Typedef: return Slot = CreateType(cast<TypedefType>(Ty), Unit); + return CreateType(cast<BlockPointerType>(Ty), Unit); + case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit); case Type::Record: case Type::Enum: - return Slot = CreateType(cast<TagType>(Ty), Unit); + return CreateType(cast<TagType>(Ty), Unit); case Type::FunctionProto: case Type::FunctionNoProto: - return Slot = CreateType(cast<FunctionType>(Ty), Unit); - + return CreateType(cast<FunctionType>(Ty), Unit); + case Type::Elaborated: + return getOrCreateType(cast<ElaboratedType>(Ty)->getUnderlyingType(), + Unit); + case Type::ConstantArray: + case Type::ConstantArrayWithExpr: + case Type::ConstantArrayWithoutExpr: case Type::VariableArray: case Type::IncompleteArray: - return Slot = CreateType(cast<ArrayType>(Ty), Unit); + return CreateType(cast<ArrayType>(Ty), Unit); case Type::TypeOfExpr: - return Slot = getOrCreateType(cast<TypeOfExprType>(Ty)->getUnderlyingExpr() - ->getType(), Unit); + return getOrCreateType(cast<TypeOfExprType>(Ty)->getUnderlyingExpr() + ->getType(), Unit); case Type::TypeOf: - return Slot = getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(), - Unit); + return getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(), Unit); case Type::Decltype: - return Slot = getOrCreateType(cast<DecltypeType>(Ty)->getUnderlyingExpr() - ->getType(), Unit); + return getOrCreateType(cast<DecltypeType>(Ty)->getUnderlyingType(), Unit); } - - return Slot; } /// EmitFunctionStart - Constructs the debug code for entering a function - @@ -803,25 +867,27 @@ void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType, llvm::Function *Fn, CGBuilderTy &Builder) { const char *LinkageName = Name; - + // Skip the asm prefix if it exists. // // FIXME: This should probably be the unmangled name? if (Name[0] == '\01') ++Name; - + // FIXME: Why is this using CurLoc??? llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc); SourceManager &SM = M->getContext().getSourceManager(); unsigned LineNo = SM.getPresumedLoc(CurLoc).getLine(); - + llvm::DISubprogram SP = DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo, getOrCreateType(ReturnType, Unit), Fn->hasInternalLinkage(), true/*definition*/); - + +#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN DebugFactory.InsertSubprogramStart(SP, Builder.GetInsertBlock()); - +#endif + // Push function on region stack. RegionStack.push_back(SP); } @@ -829,10 +895,10 @@ void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType, void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) { if (CurLoc.isInvalid() || CurLoc.isMacroID()) return; - + // Don't bother if things are the same as last time. SourceManager &SM = M->getContext().getSourceManager(); - if (CurLoc == PrevLoc + if (CurLoc == PrevLoc || (SM.getInstantiationLineNumber(CurLoc) == SM.getInstantiationLineNumber(PrevLoc) && SM.isFromSameFile(CurLoc, PrevLoc))) @@ -844,8 +910,19 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) { // Get the appropriate compile unit. llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc); PresumedLoc PLoc = SM.getPresumedLoc(CurLoc); + +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + llvm::DIDescriptor DR = RegionStack.back(); + llvm::DIScope DS = llvm::DIScope(DR.getNode()); + llvm::DILocation DO(NULL); + llvm::DILocation DL = + DebugFactory.CreateLocation(PLoc.getLine(), PLoc.getColumn(), + DS, DO); + Builder.SetCurrentDebugLocation(DL.getNode()); +#else DebugFactory.InsertStopPoint(Unit, PLoc.getLine(), PLoc.getColumn(), - Builder.GetInsertBlock()); + Builder.GetInsertBlock()); +#endif } /// EmitRegionStart- Constructs the debug code for entering a declarative @@ -854,9 +931,11 @@ void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) { llvm::DIDescriptor D; if (!RegionStack.empty()) D = RegionStack.back(); - D = DebugFactory.CreateBlock(D); + D = DebugFactory.CreateLexicalBlock(D); RegionStack.push_back(D); +#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN DebugFactory.InsertRegionStart(D, Builder.GetInsertBlock()); +#endif } /// EmitRegionEnd - Constructs the debug code for exiting a declarative @@ -866,8 +945,10 @@ void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder) { // Provide an region stop point. EmitStopPoint(Fn, Builder); - + +#ifndef ATTACH_DEBUG_INFO_TO_AN_INSN DebugFactory.InsertRegionEnd(RegionStack.back(), Builder.GetInsertBlock()); +#endif RegionStack.pop_back(); } @@ -884,7 +965,139 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag, return; llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); - llvm::DIType Ty = getOrCreateType(Decl->getType(), Unit); + QualType Type = Decl->getType(); + llvm::DIType Ty = getOrCreateType(Type, Unit); + if (Decl->hasAttr<BlocksAttr>()) { + llvm::DICompileUnit DefUnit; + unsigned Tag = llvm::dwarf::DW_TAG_structure_type; + + llvm::SmallVector<llvm::DIDescriptor, 5> EltTys; + + llvm::DIType FieldTy; + + QualType FType; + uint64_t FieldSize, FieldOffset; + unsigned FieldAlign; + + llvm::DIArray Elements; + llvm::DIType EltTy; + + // Build up structure for the byref. See BuildByRefType. + FieldOffset = 0; + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__isa", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__forwarding", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty; + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__flags", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty; + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__size", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + bool HasCopyAndDispose = M->BlockRequiresCopying(Type); + if (HasCopyAndDispose) { + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__copy_helper", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__destroy_helper", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + } + + unsigned Align = M->getContext().getDeclAlignInBytes(Decl); + if (Align > M->getContext().Target.getPointerAlign(0) / 8) { + unsigned AlignedOffsetInBytes + = llvm::RoundUpToAlignment(FieldOffset/8, Align); + unsigned NumPaddingBytes + = AlignedOffsetInBytes - FieldOffset/8; + + if (NumPaddingBytes > 0) { + llvm::APInt pad(32, NumPaddingBytes); + FType = M->getContext().getConstantArrayType(M->getContext().CharTy, + pad, ArrayType::Normal, 0); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, + Unit, "", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + } + } + + FType = Type; + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = Align*8; + std::string Name = Decl->getNameAsString(); + + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + Name, DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + + unsigned Flags = llvm::DIType::FlagBlockByrefStruct; + + Ty = DebugFactory.CreateCompositeType(Tag, Unit, "", + llvm::DICompileUnit(), + 0, FieldOffset, 0, 0, Flags, + llvm::DIType(), Elements); + } // Get location information. SourceManager &SM = M->getContext().getSourceManager(); @@ -895,21 +1108,222 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag, else Unit = llvm::DICompileUnit(); - + // Create the descriptor for the variable. - llvm::DIVariable D = + llvm::DIVariable D = DebugFactory.CreateVariable(Tag, RegionStack.back(),Decl->getNameAsString(), Unit, Line, Ty); // Insert an llvm.dbg.declare into the current block. DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock()); } +/// EmitDeclare - Emit local variable declaration debug info. +void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, + llvm::Value *Storage, CGBuilderTy &Builder, + CodeGenFunction *CGF) { + const ValueDecl *Decl = BDRE->getDecl(); + assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); + + // Do not emit variable debug information while generating optimized code. + // The llvm optimizer and code generator are not yet ready to support + // optimized code debugging. + const CompileOptions &CO = M->getCompileOpts(); + if (CO.OptimizationLevel || Builder.GetInsertBlock() == 0) + return; + + uint64_t XOffset = 0; + llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); + QualType Type = Decl->getType(); + llvm::DIType Ty = getOrCreateType(Type, Unit); + if (Decl->hasAttr<BlocksAttr>()) { + llvm::DICompileUnit DefUnit; + unsigned Tag = llvm::dwarf::DW_TAG_structure_type; + + llvm::SmallVector<llvm::DIDescriptor, 5> EltTys; + + llvm::DIType FieldTy; + + QualType FType; + uint64_t FieldSize, FieldOffset; + unsigned FieldAlign; + + llvm::DIArray Elements; + llvm::DIType EltTy; + + // Build up structure for the byref. See BuildByRefType. + FieldOffset = 0; + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__isa", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__forwarding", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty; + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__flags", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty; + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__size", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + bool HasCopyAndDispose = M->BlockRequiresCopying(Type); + if (HasCopyAndDispose) { + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__copy_helper", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + FType = M->getContext().getPointerType(M->getContext().VoidTy); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + "__destroy_helper", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + } + + unsigned Align = M->getContext().getDeclAlignInBytes(Decl); + if (Align > M->getContext().Target.getPointerAlign(0) / 8) { + unsigned AlignedOffsetInBytes + = llvm::RoundUpToAlignment(FieldOffset/8, Align); + unsigned NumPaddingBytes + = AlignedOffsetInBytes - FieldOffset/8; + + if (NumPaddingBytes > 0) { + llvm::APInt pad(32, NumPaddingBytes); + FType = M->getContext().getConstantArrayType(M->getContext().CharTy, + pad, ArrayType::Normal, 0); + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = M->getContext().getTypeAlign(FType); + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, + Unit, "", DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + } + } + + FType = Type; + FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); + FieldSize = M->getContext().getTypeSize(FType); + FieldAlign = Align*8; + std::string Name = Decl->getNameAsString(); + + XOffset = FieldOffset; + FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, + Name, DefUnit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); + EltTys.push_back(FieldTy); + FieldOffset += FieldSize; + + Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + + unsigned Flags = llvm::DIType::FlagBlockByrefStruct; + + Ty = DebugFactory.CreateCompositeType(Tag, Unit, "", + llvm::DICompileUnit(), + 0, FieldOffset, 0, 0, Flags, + llvm::DIType(), Elements); + } + + // Get location information. + SourceManager &SM = M->getContext().getSourceManager(); + PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation()); + unsigned Line = 0; + if (!PLoc.isInvalid()) + Line = PLoc.getLine(); + else + Unit = llvm::DICompileUnit(); + + uint64_t offset = CGF->BlockDecls[Decl]; + llvm::SmallVector<llvm::Value *, 9> addr; + llvm::LLVMContext &VMContext = M->getLLVMContext(); + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::DIFactory::OpDeref)); + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::DIFactory::OpPlus)); + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + offset)); + if (BDRE->isByRef()) { + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::DIFactory::OpDeref)); + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::DIFactory::OpPlus)); + offset = CGF->LLVMPointerWidth/8; // offset of __forwarding field + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + offset)); + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::DIFactory::OpDeref)); + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::DIFactory::OpPlus)); + offset = XOffset/8; // offset of x field + addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + offset)); + } + + // Create the descriptor for the variable. + llvm::DIVariable D = + DebugFactory.CreateComplexVariable(Tag, RegionStack.back(), + Decl->getNameAsString(), Unit, Line, Ty, + addr); + // Insert an llvm.dbg.declare into the current block. + DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertPoint()); +} + void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *Storage, CGBuilderTy &Builder) { EmitDeclare(Decl, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder); } +void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( + const BlockDeclRefExpr *BDRE, llvm::Value *Storage, CGBuilderTy &Builder, + CodeGenFunction *CGF) { + EmitDeclare(BDRE, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder, CGF); +} + /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument /// variable declaration. void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, @@ -920,7 +1334,7 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, /// EmitGlobalVariable - Emit information about a global variable. -void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, +void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *Decl) { // Do not emit variable debug information while generating optimized code. @@ -936,29 +1350,30 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation()); unsigned LineNo = PLoc.isInvalid() ? 0 : PLoc.getLine(); - std::string Name = Decl->getNameAsString(); + std::string Name = Var->getName(); QualType T = Decl->getType(); if (T->isIncompleteArrayType()) { - + // CodeGen turns int[] into int[1] so we'll do the same here. llvm::APSInt ConstVal(32); - + ConstVal = 1; QualType ET = M->getContext().getAsArrayType(T)->getElementType(); - - T = M->getContext().getConstantArrayType(ET, ConstVal, + + T = M->getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, 0); } - DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo, + DebugFactory.CreateGlobalVariable(getContext(Decl, Unit), + Name, Name, "", Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), true/*definition*/, Var); } /// EmitGlobalVariable - Emit information about an objective-c interface. -void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, +void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ObjCInterfaceDecl *Decl) { // Create global variable debug descriptor. llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation()); @@ -970,14 +1385,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, QualType T = M->getContext().getObjCInterfaceType(Decl); if (T->isIncompleteArrayType()) { - + // CodeGen turns int[] into int[1] so we'll do the same here. llvm::APSInt ConstVal(32); - + ConstVal = 1; QualType ET = M->getContext().getAsArrayType(T)->getElementType(); - - T = M->getContext().getConstantArrayType(ET, ConstVal, + + T = M->getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal, 0); } @@ -986,4 +1401,3 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, Var->hasInternalLinkage(), true/*definition*/, Var); } - diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index de655800fa080..0a617b999240e 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This is the source level debug info generator for llvm translation. +// This is the source level debug info generator for llvm translation. // //===----------------------------------------------------------------------===// @@ -15,28 +15,35 @@ #define CLANG_CODEGEN_CGDEBUGINFO_H #include "clang/AST/Type.h" +#include "clang/AST/Expr.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/DebugInfo.h" +#include "llvm/Support/ValueHandle.h" #include <map> #include "CGBuilder.h" +namespace llvm { + class MDNode; +} + namespace clang { class VarDecl; class ObjCInterfaceDecl; namespace CodeGen { class CodeGenModule; + class CodeGenFunction; -/// CGDebugInfo - This class gathers all debug information during compilation -/// and is responsible for emitting to llvm globals or pass directly to +/// CGDebugInfo - This class gathers all debug information during compilation +/// and is responsible for emitting to llvm globals or pass directly to /// the backend. class CGDebugInfo { CodeGenModule *M; bool isMainCompileUnitCreated; llvm::DIFactory DebugFactory; - + SourceLocation CurLoc, PrevLoc; /// CompileUnitCache - Cache of previously constructed CompileUnits. @@ -44,8 +51,8 @@ class CGDebugInfo { /// TypeCache - Cache of previously constructed Types. // FIXME: Eliminate this map. Be careful of iterator invalidation. - std::map<void *, llvm::DIType> TypeCache; - + std::map<void *, llvm::WeakVH> TypeCache; + bool BlockLiteralGenericSet; llvm::DIType BlockLiteralGeneric; @@ -54,8 +61,10 @@ class CGDebugInfo { /// Helper functions for getOrCreateType. llvm::DIType CreateType(const BuiltinType *Ty, llvm::DICompileUnit U); llvm::DIType CreateType(const ComplexType *Ty, llvm::DICompileUnit U); - llvm::DIType CreateCVRType(QualType Ty, llvm::DICompileUnit U); + llvm::DIType CreateQualifiedType(QualType Ty, llvm::DICompileUnit U); llvm::DIType CreateType(const TypedefType *Ty, llvm::DICompileUnit U); + llvm::DIType CreateType(const ObjCObjectPointerType *Ty, + llvm::DICompileUnit Unit); llvm::DIType CreateType(const PointerType *Ty, llvm::DICompileUnit U); llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DICompileUnit U); llvm::DIType CreateType(const FunctionType *Ty, llvm::DICompileUnit U); @@ -81,12 +90,12 @@ public: /// start of a new function. void EmitFunctionStart(const char *Name, QualType ReturnType, llvm::Function *Fn, CGBuilderTy &Builder); - + /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start - /// of a new block. + /// of a new block. void EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder); - - /// EmitRegionEnd - Emit call to llvm.dbg.region.end to indicate end of a + + /// EmitRegionEnd - Emit call to llvm.dbg.region.end to indicate end of a /// block. void EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder); @@ -95,23 +104,36 @@ public: void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI, CGBuilderTy &Builder); + /// EmitDeclareOfBlockDeclRefVariable - Emit call to llvm.dbg.declare for an + /// imported variable declaration in a block. + void EmitDeclareOfBlockDeclRefVariable(const BlockDeclRefExpr *BDRE, + llvm::Value *AI, + CGBuilderTy &Builder, + CodeGenFunction *CGF); + /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument /// variable declaration. void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, CGBuilderTy &Builder); - + /// EmitGlobalVariable - Emit information about a global variable. void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); /// EmitGlobalVariable - Emit information about an objective-c interface. void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl); - + private: /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI, CGBuilderTy &Builder); - - + + /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration. + void EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, llvm::Value *AI, + CGBuilderTy &Builder, CodeGenFunction *CGF); + + /// getContext - Get context info for the decl. + llvm::DIDescriptor getContext(const VarDecl *Decl,llvm::DIDescriptor &CU); + /// getOrCreateCompileUnit - Get the compile unit from the cache or create a /// new one if necessary. llvm::DICompileUnit getOrCreateCompileUnit(SourceLocation Loc); @@ -119,8 +141,12 @@ private: /// getOrCreateType - Get the type from the cache or create a new type if /// necessary. llvm::DIType getOrCreateType(QualType Ty, llvm::DICompileUnit Unit); + + /// CreateTypeNode - Create type metadata for a source language type. + llvm::DIType CreateTypeNode(QualType Ty, llvm::DICompileUnit Unit); }; } // namespace CodeGen } // namespace clang + #endif diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 2ae7e225ebbf0..7feff83dee6bb 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -35,22 +35,22 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Function: // void X(); case Decl::Record: // struct/union/class X; case Decl::Enum: // enum X; - case Decl::EnumConstant: // enum ? { X = ? } + case Decl::EnumConstant: // enum ? { X = ? } case Decl::CXXRecord: // struct/union/class X; [C++] // None of these decls require codegen support. return; - + case Decl::Var: { const VarDecl &VD = cast<VarDecl>(D); - assert(VD.isBlockVarDecl() && + assert(VD.isBlockVarDecl() && "Should not see file-scope variables inside a function!"); return EmitBlockVarDecl(VD); } - + case Decl::Typedef: { // typedef int X; const TypedefDecl &TD = cast<TypedefDecl>(D); QualType Ty = TD.getUnderlyingType(); - + if (Ty->isVariablyModifiedType()) EmitVLASize(Ty); } @@ -62,7 +62,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) { if (D.hasAttr<AsmLabelAttr>()) CGM.ErrorUnsupported(&D, "__asm__"); - + switch (D.getStorageClass()) { case VarDecl::None: case VarDecl::Auto: @@ -95,27 +95,28 @@ CodeGenFunction::CreateStaticBlockVarDecl(const VarDecl &D, if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) ContextName = CGM.getMangledName(FD); else if (isa<ObjCMethodDecl>(CurFuncDecl)) - ContextName = std::string(CurFn->getNameStart(), - CurFn->getNameStart() + CurFn->getNameLen()); + ContextName = CurFn->getName(); else assert(0 && "Unknown context for block var decl"); - + Name = ContextName + Separator + D.getNameAsString(); } const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty); - return new llvm::GlobalVariable(LTy, Ty.isConstant(getContext()), Linkage, - llvm::Constant::getNullValue(LTy), Name, - &CGM.getModule(), D.isThreadSpecified(), - Ty.getAddressSpace()); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), LTy, + Ty.isConstant(getContext()), Linkage, + CGM.EmitNullConstant(D.getType()), Name, 0, + D.isThreadSpecified(), Ty.getAddressSpace()); + GV->setAlignment(getContext().getDeclAlignInBytes(&D)); + return GV; } -void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { - +void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); - - llvm::GlobalVariable *GV = + + llvm::GlobalVariable *GV = CreateStaticBlockVarDecl(D, ".", llvm::GlobalValue::InternalLinkage); // Store into LocalDeclMap before generating initializer to handle @@ -123,14 +124,11 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { DMEntry = GV; // Make sure to evaluate VLA bounds now so that we have them for later. + // + // FIXME: Can this happen? if (D.getType()->isVariablyModifiedType()) EmitVLASize(D.getType()); - if (D.getType()->isReferenceType()) { - CGM.ErrorUnsupported(&D, "static declaration with reference type"); - return; - } - if (D.getInit()) { llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this); @@ -140,7 +138,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { if (!getContext().getLangOptions().CPlusPlus) CGM.ErrorUnsupported(D.getInit(), "constant l-value expression"); else - GenerateStaticCXXBlockVarDeclInit(D, GV); + EmitStaticCXXBlockVarDeclInit(D, GV); } else { // The initializer may differ in type from the global. Rewrite // the global to match the initializer. (We have to do this @@ -148,23 +146,24 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { // in the LLVM type system.) if (GV->getType() != Init->getType()) { llvm::GlobalVariable *OldGV = GV; - - GV = new llvm::GlobalVariable(Init->getType(), OldGV->isConstant(), + + GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), + OldGV->isConstant(), OldGV->getLinkage(), Init, "", - &CGM.getModule(), D.isThreadSpecified(), + 0, D.isThreadSpecified(), D.getType().getAddressSpace()); // Steal the name of the old global GV->takeName(OldGV); // Replace all uses of the old global with the new global - llvm::Constant *NewPtrForOldDecl = + llvm::Constant *NewPtrForOldDecl = llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); OldGV->replaceAllUsesWith(NewPtrForOldDecl); // Erase the old global, since it is no longer used. OldGV->eraseFromParent(); - } + } GV->setInitializer(Init); } @@ -174,14 +173,14 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) { SourceManager &SM = CGM.getContext().getSourceManager(); llvm::Constant *Ann = - CGM.EmitAnnotateAttr(GV, AA, + CGM.EmitAnnotateAttr(GV, AA, SM.getInstantiationLineNumber(D.getLocation())); CGM.AddAnnotation(Ann); } if (const SectionAttr *SA = D.getAttr<SectionAttr>()) GV->setSection(SA->getName()); - + if (D.hasAttr<UsedAttr>()) CGM.AddUsedGlobal(GV); @@ -202,7 +201,13 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(GV), &D); } } + +unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { + assert(ByRefValueInfo.count(VD) && "Did not find value!"); + return ByRefValueInfo.find(VD)->second.second; +} + /// BuildByRefType - This routine changes a __block variable declared as T x /// into: /// @@ -211,32 +216,91 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { /// void *__forwarding; /// int32_t __flags; /// int32_t __size; -/// void *__copy_helper; -/// void *__destroy_helper; +/// void *__copy_helper; // only if needed +/// void *__destroy_helper; // only if needed +/// char padding[X]; // only if needed /// T x; /// } x /// -/// Align is the alignment needed in bytes for x. -const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty, - uint64_t Align) { - const llvm::Type *LTy = ConvertType(Ty); - bool needsCopyDispose = BlockRequiresCopying(Ty); - std::vector<const llvm::Type *> Types(needsCopyDispose*2+5); - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - Types[0] = PtrToInt8Ty; - Types[1] = PtrToInt8Ty; - Types[2] = llvm::Type::Int32Ty; - Types[3] = llvm::Type::Int32Ty; - if (needsCopyDispose) { - Types[4] = PtrToInt8Ty; - Types[5] = PtrToInt8Ty; +const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) { + std::pair<const llvm::Type *, unsigned> &Info = ByRefValueInfo[D]; + if (Info.first) + return Info.first; + + QualType Ty = D->getType(); + + std::vector<const llvm::Type *> Types; + + const llvm::PointerType *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + + llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(VMContext); + + // void *__isa; + Types.push_back(Int8PtrTy); + + // void *__forwarding; + Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder)); + + // int32_t __flags; + Types.push_back(llvm::Type::getInt32Ty(VMContext)); + + // int32_t __size; + Types.push_back(llvm::Type::getInt32Ty(VMContext)); + + bool HasCopyAndDispose = BlockRequiresCopying(Ty); + if (HasCopyAndDispose) { + /// void *__copy_helper; + Types.push_back(Int8PtrTy); + + /// void *__destroy_helper; + Types.push_back(Int8PtrTy); } - // FIXME: Align this on at least an Align boundary, assert if we can't. - assert((Align <= unsigned(Target.getPointerAlign(0))/8) - && "Can't align more than pointer yet"); - Types[needsCopyDispose*2 + 4] = LTy; - return llvm::StructType::get(Types, false); + + bool Packed = false; + unsigned Align = getContext().getDeclAlignInBytes(D); + if (Align > Target.getPointerAlign(0) / 8) { + // We have to insert padding. + + // The struct above has 2 32-bit integers. + unsigned CurrentOffsetInBytes = 4 * 2; + + // And either 2 or 4 pointers. + CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * + CGM.getTargetData().getTypeAllocSize(Int8PtrTy); + + // Align the offset. + unsigned AlignedOffsetInBytes = + llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align); + + unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; + if (NumPaddingBytes > 0) { + const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext); + // FIXME: We need a sema error for alignment larger than the minimum of the + // maximal stack alignmint and the alignment of malloc on the system. + if (NumPaddingBytes > 1) + Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); + + Types.push_back(Ty); + + // We want a packed struct. + Packed = true; + } + } + + // T x; + Types.push_back(ConvertType(Ty)); + + const llvm::Type *T = llvm::StructType::get(VMContext, Types, Packed); + + cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T); + CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), + ByRefTypeHolder.get()); + + Info.first = ByRefTypeHolder.get(); + + Info.second = Types.size() - 1; + + return Info.first; } /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a @@ -255,10 +319,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { const llvm::Type *LTy = ConvertTypeForMem(Ty); Align = getContext().getDeclAlignInBytes(&D); if (isByRef) - LTy = BuildByRefType(Ty, Align); + LTy = BuildByRefType(&D); llvm::AllocaInst *Alloc = CreateTempAlloca(LTy); Alloc->setName(D.getNameAsString().c_str()); - + if (isByRef) Align = std::max(Align, unsigned(Target.getPointerAlign(0) / 8)); Alloc->setAlignment(Align); @@ -267,48 +331,55 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { // Targets that don't support recursion emit locals as globals. const char *Class = D.getStorageClass() == VarDecl::Register ? ".reg." : ".auto."; - DeclPtr = CreateStaticBlockVarDecl(D, Class, + DeclPtr = CreateStaticBlockVarDecl(D, Class, llvm::GlobalValue ::InternalLinkage); } - + + // FIXME: Can this happen? if (Ty->isVariablyModifiedType()) EmitVLASize(Ty); } else { + EnsureInsertPoint(); + if (!DidCallStackSave) { // Save the stack. - const llvm::Type *LTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *LTy = llvm::Type::getInt8PtrTy(VMContext); llvm::Value *Stack = CreateTempAlloca(LTy, "saved_stack"); - + llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stacksave); llvm::Value *V = Builder.CreateCall(F); - + Builder.CreateStore(V, Stack); DidCallStackSave = true; - + { // Push a cleanup block and restore the stack there. CleanupScope scope(*this); - + V = Builder.CreateLoad(Stack, "tmp"); llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore); Builder.CreateCall(F, V); } } - + // Get the element type. - const llvm::Type *LElemTy = ConvertTypeForMem(Ty); + const llvm::Type *LElemTy = ConvertTypeForMem(Ty); const llvm::Type *LElemPtrTy = llvm::PointerType::get(LElemTy, D.getType().getAddressSpace()); llvm::Value *VLASize = EmitVLASize(Ty); // Downcast the VLA size expression - VLASize = Builder.CreateIntCast(VLASize, llvm::Type::Int32Ty, false, "tmp"); - + VLASize = Builder.CreateIntCast(VLASize, llvm::Type::getInt32Ty(VMContext), + false, "tmp"); + // Allocate memory for the array. - llvm::Value *VLA = Builder.CreateAlloca(llvm::Type::Int8Ty, VLASize, "vla"); + llvm::AllocaInst *VLA = + Builder.CreateAlloca(llvm::Type::getInt8Ty(VMContext), VLASize, "vla"); + VLA->setAlignment(getContext().getDeclAlignInBytes(&D)); + DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp"); } @@ -318,35 +389,39 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { // Emit debug info for local var declaration. if (CGDebugInfo *DI = getDebugInfo()) { + assert(HaveInsertPoint() && "Unexpected unreachable point!"); + DI->setLocation(D.getLocation()); if (Target.useGlobalsForAutomaticVariables()) { DI->EmitGlobalVariable(static_cast<llvm::GlobalVariable *>(DeclPtr), &D); - } - else if (isByRef) { - llvm::Value *Loc; - bool needsCopyDispose = BlockRequiresCopying(Ty); - Loc = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); - Loc = Builder.CreateLoad(Loc, false); - Loc = Builder.CreateBitCast(Loc, DeclPtr->getType()); - Loc = Builder.CreateStructGEP(Loc, needsCopyDispose*2+4, "x"); - DI->EmitDeclareOfAutoVariable(&D, Loc, Builder); } else DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder); } // If this local has an initializer, emit it now. - if (const Expr *Init = D.getInit()) { + const Expr *Init = D.getInit(); + + // If we are at an unreachable point, we don't need to emit the initializer + // unless it contains a label. + if (!HaveInsertPoint()) { + if (!ContainsLabel(Init)) + Init = 0; + else + EnsureInsertPoint(); + } + + if (Init) { llvm::Value *Loc = DeclPtr; - if (isByRef) { - bool needsCopyDispose = BlockRequiresCopying(Ty); - Loc = Builder.CreateStructGEP(DeclPtr, needsCopyDispose*2+4, "x"); - } + if (isByRef) + Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), + D.getNameAsString()); + if (Ty->isReferenceType()) { - llvm::Value *V = EmitReferenceBindingToExpr(Init, Ty).getScalarVal(); - EmitStoreOfScalar(V, Loc, false, Ty); + RValue RV = EmitReferenceBindingToExpr(Init, Ty, /*IsInitializer=*/true); + EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty); } else if (!hasAggregateLLVMType(Init->getType())) { llvm::Value *V = EmitScalarExpr(Init); - EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(), + EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(), D.getType()); } else if (Init->getType()->isAnyComplexType()) { EmitComplexExprIntoAddr(Init, Loc, D.getType().isVolatileQualified()); @@ -354,10 +429,11 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { EmitAggExpr(Init, Loc, D.getType().isVolatileQualified()); } } + if (isByRef) { - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::PointerType *PtrToInt8Ty = llvm::Type::getInt8PtrTy(VMContext); + EnsureInsertPoint(); llvm::Value *isa_field = Builder.CreateStructGEP(DeclPtr, 0); llvm::Value *forwarding_field = Builder.CreateStructGEP(DeclPtr, 1); llvm::Value *flags_field = Builder.CreateStructGEP(DeclPtr, 2); @@ -383,19 +459,18 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { int isa = 0; if (flag&BLOCK_FIELD_IS_WEAK) isa = 1; - V = llvm::ConstantInt::get(llvm::Type::Int32Ty, isa); + V = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), isa); V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "isa"); Builder.CreateStore(V, isa_field); - V = Builder.CreateBitCast(DeclPtr, PtrToInt8Ty, "forwarding"); - Builder.CreateStore(V, forwarding_field); + Builder.CreateStore(DeclPtr, forwarding_field); - V = llvm::ConstantInt::get(llvm::Type::Int32Ty, flags); + V = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags); Builder.CreateStore(V, flags_field); const llvm::Type *V1; V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType(); - V = llvm::ConstantInt::get(llvm::Type::Int32Ty, + V = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), (CGM.getTargetData().getTypeStoreSizeInBits(V1) / 8)); Builder.CreateStore(V, size_field); @@ -413,13 +488,29 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { } } + // Handle CXX destruction of variables. + QualType DtorTy(Ty); + if (const ArrayType *Array = DtorTy->getAs<ArrayType>()) + DtorTy = Array->getElementType(); + if (const RecordType *RT = DtorTy->getAs<RecordType>()) + if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (!ClassDecl->hasTrivialDestructor()) { + const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext()); + assert(D && "EmitLocalBlockVarDecl - destructor is nul"); + assert(!Ty->getAs<ArrayType>() && "FIXME - destruction of arrays NYI"); + + CleanupScope scope(*this); + EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr); + } + } + // Handle the cleanup attribute if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) { const FunctionDecl *FD = CA->getFunctionDecl(); - - llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD)); + + llvm::Constant* F = CGM.GetAddrOfFunction(FD); assert(F && "Could not find function!"); - + CleanupScope scope(*this); const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD); @@ -428,15 +519,15 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { // the type of the pointer. An example of this is // void f(void* arg); // __attribute__((cleanup(f))) void *g; - // + // // To fix this we insert a bitcast here. QualType ArgTy = Info.arg_begin()->type; DeclPtr = Builder.CreateBitCast(DeclPtr, ConvertType(ArgTy)); - + CallArgList Args; - Args.push_back(std::make_pair(RValue::get(DeclPtr), + Args.push_back(std::make_pair(RValue::get(DeclPtr), getContext().getPointerType(D.getType()))); - + EmitCall(Info, F, Args); } @@ -448,14 +539,14 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { } } -/// Emit an alloca (or GlobalValue depending on target) +/// Emit an alloca (or GlobalValue depending on target) /// for the specified parameter and set up LocalDeclMap. void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) && "Invalid argument to EmitParmDecl"); QualType Ty = D.getType(); - + llvm::Value *DeclPtr; if (!Ty->isConstantSizeType()) { // Variable sized values always are passed by-reference. @@ -469,7 +560,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { Name += ".addr"; DeclPtr = CreateTempAlloca(LTy); DeclPtr->setName(Name.c_str()); - + // Store the initial value into the alloca. EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(), Ty); } else { diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 0951019f01087..2834dfeb780a6 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -46,33 +46,38 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { /// EmitAnyExpr - Emit code to compute the specified expression which can have /// any type. The result is returned as an RValue struct. If this is an -/// aggregate expression, the aggloc/agglocvolatile arguments indicate where -/// the result should be returned. -RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, - bool isAggLocVolatile, bool IgnoreResult) { +/// aggregate expression, the aggloc/agglocvolatile arguments indicate where the +/// result should be returned. +RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, + bool IsAggLocVolatile, bool IgnoreResult, + bool IsInitializer) { if (!hasAggregateLLVMType(E->getType())) return RValue::get(EmitScalarExpr(E, IgnoreResult)); else if (E->getType()->isAnyComplexType()) return RValue::getComplex(EmitComplexExpr(E, false, false, IgnoreResult, IgnoreResult)); - - EmitAggExpr(E, AggLoc, isAggLocVolatile, IgnoreResult); - return RValue::getAggregate(AggLoc, isAggLocVolatile); + + EmitAggExpr(E, AggLoc, IsAggLocVolatile, IgnoreResult, IsInitializer); + return RValue::getAggregate(AggLoc, IsAggLocVolatile); } -/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result -/// will always be accessible even if no aggregate location is -/// provided. -RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, llvm::Value *AggLoc, - bool isAggLocVolatile) { - if (!AggLoc && hasAggregateLLVMType(E->getType()) && +/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will +/// always be accessible even if no aggregate location is provided. +RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, + bool IsAggLocVolatile, + bool IsInitializer) { + llvm::Value *AggLoc = 0; + + if (hasAggregateLLVMType(E->getType()) && !E->getType()->isAnyComplexType()) AggLoc = CreateTempAlloca(ConvertType(E->getType()), "agg.tmp"); - return EmitAnyExpr(E, AggLoc, isAggLocVolatile); + return EmitAnyExpr(E, AggLoc, IsAggLocVolatile, /*IgnoreResult=*/false, + IsInitializer); } RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, - QualType DestType) { + QualType DestType, + bool IsInitializer) { RValue Val; if (E->isLvalue(getContext()) == Expr::LV_Valid) { // Emit the expr as an lvalue. @@ -81,14 +86,33 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, return RValue::get(LV.getAddress()); Val = EmitLoadOfLValue(LV, E->getType()); } else { - Val = EmitAnyExprToTemp(E); + // FIXME: Initializers don't work with casts yet. For example + // const A& a = B(); + // if B inherits from A. + Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false, + IsInitializer); + + if (IsInitializer) { + // We might have to destroy the temporary variable. + if (const RecordType *RT = E->getType()->getAs<RecordType>()) { + if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (!ClassDecl->hasTrivialDestructor()) { + const CXXDestructorDecl *Dtor = + ClassDecl->getDestructor(getContext()); + + CleanupScope scope(*this); + EmitCXXDestructorCall(Dtor, Dtor_Complete, Val.getAggregateAddr()); + } + } + } + } } if (Val.isAggregate()) { Val = RValue::get(Val.getAggregateAddr()); } else { // Create a temporary variable that we can bind the reference to. - llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), + llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "reftmp"); if (Val.isScalar()) EmitStoreOfScalar(Val.getScalarVal(), Temp, false, E->getType()); @@ -101,13 +125,13 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, } -/// getAccessedFieldNo - Given an encoded value and a result number, return -/// the input field number being accessed. -unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx, +/// getAccessedFieldNo - Given an encoded value and a result number, return the +/// input field number being accessed. +unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts) { if (isa<llvm::ConstantAggregateZero>(Elts)) return 0; - + return cast<llvm::ConstantInt>(Elts->getOperand(Idx))->getZExtValue(); } @@ -119,7 +143,7 @@ unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx, RValue CodeGenFunction::GetUndefRValue(QualType Ty) { if (Ty->isVoidType()) { return RValue::get(0); - } else if (const ComplexType *CTy = Ty->getAsComplexType()) { + } else if (const ComplexType *CTy = Ty->getAs<ComplexType>()) { const llvm::Type *EltTy = ConvertType(CTy->getElementType()); llvm::Value *U = llvm::UndefValue::get(EltTy); return RValue::getComplex(std::make_pair(U, U)); @@ -142,38 +166,37 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E, ErrorUnsupported(E, Name); llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType())); return LValue::MakeAddr(llvm::UndefValue::get(Ty), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + MakeQualifiers(E->getType())); } /// EmitLValue - Emit code to compute a designator that specifies the location /// of the expression. /// -/// This can return one of two things: a simple address or a bitfield -/// reference. In either case, the LLVM Value* in the LValue structure is -/// guaranteed to be an LLVM pointer type. +/// This can return one of two things: a simple address or a bitfield reference. +/// In either case, the LLVM Value* in the LValue structure is guaranteed to be +/// an LLVM pointer type. /// -/// If this returns a bitfield reference, nothing about the pointee type of -/// the LLVM value is known: For example, it may not be a pointer to an -/// integer. +/// If this returns a bitfield reference, nothing about the pointee type of the +/// LLVM value is known: For example, it may not be a pointer to an integer. /// -/// If this returns a normal address, and if the lvalue's C type is fixed -/// size, this method guarantees that the returned pointer type will point to -/// an LLVM type of the same size of the lvalue's type. If the lvalue has a -/// variable length type, this is not possible. +/// If this returns a normal address, and if the lvalue's C type is fixed size, +/// this method guarantees that the returned pointer type will point to an LLVM +/// type of the same size of the lvalue's type. If the lvalue has a variable +/// length type, this is not possible. /// LValue CodeGenFunction::EmitLValue(const Expr *E) { switch (E->getStmtClass()) { default: return EmitUnsupportedLValue(E, "l-value expression"); - case Expr::BinaryOperatorClass: + case Expr::BinaryOperatorClass: return EmitBinaryOperatorLValue(cast<BinaryOperator>(E)); - case Expr::CallExprClass: + case Expr::CallExprClass: + case Expr::CXXMemberCallExprClass: case Expr::CXXOperatorCallExprClass: return EmitCallExprLValue(cast<CallExpr>(E)); case Expr::VAArgExprClass: return EmitVAArgExprLValue(cast<VAArgExpr>(E)); - case Expr::DeclRefExprClass: + case Expr::DeclRefExprClass: case Expr::QualifiedDeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E)); case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr()); @@ -184,7 +207,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::ObjCEncodeExprClass: return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E)); - case Expr::BlockDeclRefExprClass: + case Expr::BlockDeclRefExprClass: return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E)); case Expr::CXXConditionDeclExprClass: @@ -194,31 +217,34 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitCXXConstructLValue(cast<CXXConstructExpr>(E)); case Expr::CXXBindTemporaryExprClass: return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E)); + case Expr::CXXExprWithTemporariesClass: + return EmitCXXExprWithTemporariesLValue(cast<CXXExprWithTemporaries>(E)); case Expr::ObjCMessageExprClass: return EmitObjCMessageExprLValue(cast<ObjCMessageExpr>(E)); - case Expr::ObjCIvarRefExprClass: + case Expr::ObjCIvarRefExprClass: return EmitObjCIvarRefLValue(cast<ObjCIvarRefExpr>(E)); case Expr::ObjCPropertyRefExprClass: return EmitObjCPropertyRefLValue(cast<ObjCPropertyRefExpr>(E)); - case Expr::ObjCKVCRefExprClass: - return EmitObjCKVCRefLValue(cast<ObjCKVCRefExpr>(E)); + case Expr::ObjCImplicitSetterGetterRefExprClass: + return EmitObjCKVCRefLValue(cast<ObjCImplicitSetterGetterRefExpr>(E)); case Expr::ObjCSuperExprClass: return EmitObjCSuperExprLValue(cast<ObjCSuperExpr>(E)); case Expr::StmtExprClass: return EmitStmtExprLValue(cast<StmtExpr>(E)); - case Expr::UnaryOperatorClass: + case Expr::UnaryOperatorClass: return EmitUnaryOpLValue(cast<UnaryOperator>(E)); case Expr::ArraySubscriptExprClass: return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); case Expr::ExtVectorElementExprClass: return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E)); - case Expr::MemberExprClass: return EmitMemberExpr(cast<MemberExpr>(E)); + case Expr::MemberExprClass: + return EmitMemberExpr(cast<MemberExpr>(E)); case Expr::CompoundLiteralExprClass: return EmitCompoundLiteralLValue(cast<CompoundLiteralExpr>(E)); case Expr::ConditionalOperatorClass: - return EmitConditionalOperator(cast<ConditionalOperator>(E)); + return EmitConditionalOperatorLValue(cast<ConditionalOperator>(E)); case Expr::ChooseExprClass: return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext())); case Expr::ImplicitCastExprClass: @@ -238,55 +264,54 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, // Bool can have different representation in memory than in registers. if (Ty->isBooleanType()) - if (V->getType() != llvm::Type::Int1Ty) - V = Builder.CreateTrunc(V, llvm::Type::Int1Ty, "tobool"); - + if (V->getType() != llvm::Type::getInt1Ty(VMContext)) + V = Builder.CreateTrunc(V, llvm::Type::getInt1Ty(VMContext), "tobool"); + return V; } void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, QualType Ty) { - + if (Ty->isBooleanType()) { // Bool can have different representation in memory than in registers. const llvm::Type *SrcTy = Value->getType(); const llvm::PointerType *DstPtr = cast<llvm::PointerType>(Addr->getType()); if (DstPtr->getElementType() != SrcTy) { - const llvm::Type *MemTy = + const llvm::Type *MemTy = llvm::PointerType::get(SrcTy, DstPtr->getAddressSpace()); Addr = Builder.CreateBitCast(Addr, MemTy, "storetmp"); } } - - Builder.CreateStore(Value, Addr, Volatile); + Builder.CreateStore(Value, Addr, Volatile); } -/// EmitLoadOfLValue - Given an expression that represents a value lvalue, -/// this method emits the address of the lvalue, then loads the result as an -/// rvalue, returning the rvalue. +/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this +/// method emits the address of the lvalue, then loads the result as an rvalue, +/// returning the rvalue. RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) { if (LV.isObjCWeak()) { - // load of a __weak object. + // load of a __weak object. llvm::Value *AddrWeakObj = LV.getAddress(); - llvm::Value *read_weak = CGM.getObjCRuntime().EmitObjCWeakRead(*this, + llvm::Value *read_weak = CGM.getObjCRuntime().EmitObjCWeakRead(*this, AddrWeakObj); return RValue::get(read_weak); } - + if (LV.isSimple()) { llvm::Value *Ptr = LV.getAddress(); const llvm::Type *EltTy = cast<llvm::PointerType>(Ptr->getType())->getElementType(); - + // Simple scalar l-value. if (EltTy->isSingleValueType()) - return RValue::get(EmitLoadOfScalar(Ptr, LV.isVolatileQualified(), + return RValue::get(EmitLoadOfScalar(Ptr, LV.isVolatileQualified(), ExprType)); - + assert(ExprType->isFunctionType() && "Unknown scalar value"); return RValue::get(Ptr); } - + if (LV.isVectorElt()) { llvm::Value *Vec = Builder.CreateLoad(LV.getVectorAddr(), LV.isVolatileQualified(), "tmp"); @@ -315,59 +340,58 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV, unsigned BitfieldSize = LV.getBitfieldSize(); llvm::Value *Ptr = LV.getBitfieldAddr(); - const llvm::Type *EltTy = + const llvm::Type *EltTy = cast<llvm::PointerType>(Ptr->getType())->getElementType(); unsigned EltTySize = CGM.getTargetData().getTypeSizeInBits(EltTy); - // In some cases the bitfield may straddle two memory locations. - // Currently we load the entire bitfield, then do the magic to - // sign-extend it if necessary. This results in somewhat more code - // than necessary for the common case (one load), since two shifts - // accomplish both the masking and sign extension. + // In some cases the bitfield may straddle two memory locations. Currently we + // load the entire bitfield, then do the magic to sign-extend it if + // necessary. This results in somewhat more code than necessary for the common + // case (one load), since two shifts accomplish both the masking and sign + // extension. unsigned LowBits = std::min(BitfieldSize, EltTySize - StartBit); llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), "tmp"); - + // Shift to proper location. if (StartBit) - Val = Builder.CreateLShr(Val, llvm::ConstantInt::get(EltTy, StartBit), + Val = Builder.CreateLShr(Val, llvm::ConstantInt::get(EltTy, StartBit), "bf.lo"); - + // Mask off unused bits. - llvm::Constant *LowMask = - llvm::ConstantInt::get(llvm::APInt::getLowBitsSet(EltTySize, LowBits)); + llvm::Constant *LowMask = llvm::ConstantInt::get(VMContext, + llvm::APInt::getLowBitsSet(EltTySize, LowBits)); Val = Builder.CreateAnd(Val, LowMask, "bf.lo.cleared"); - + // Fetch the high bits if necessary. if (LowBits < BitfieldSize) { unsigned HighBits = BitfieldSize - LowBits; - llvm::Value *HighPtr = - Builder.CreateGEP(Ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, 1), - "bf.ptr.hi"); - llvm::Value *HighVal = Builder.CreateLoad(HighPtr, + llvm::Value *HighPtr = Builder.CreateGEP(Ptr, llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), 1), "bf.ptr.hi"); + llvm::Value *HighVal = Builder.CreateLoad(HighPtr, LV.isVolatileQualified(), "tmp"); - + // Mask off unused bits. - llvm::Constant *HighMask = - llvm::ConstantInt::get(llvm::APInt::getLowBitsSet(EltTySize, HighBits)); + llvm::Constant *HighMask = llvm::ConstantInt::get(VMContext, + llvm::APInt::getLowBitsSet(EltTySize, HighBits)); HighVal = Builder.CreateAnd(HighVal, HighMask, "bf.lo.cleared"); // Shift to proper location and or in to bitfield value. - HighVal = Builder.CreateShl(HighVal, + HighVal = Builder.CreateShl(HighVal, llvm::ConstantInt::get(EltTy, LowBits)); Val = Builder.CreateOr(Val, HighVal, "bf.val"); } // Sign extend if necessary. if (LV.isBitfieldSigned()) { - llvm::Value *ExtraBits = llvm::ConstantInt::get(EltTy, + llvm::Value *ExtraBits = llvm::ConstantInt::get(EltTy, EltTySize - BitfieldSize); - Val = Builder.CreateAShr(Builder.CreateShl(Val, ExtraBits), + Val = Builder.CreateAShr(Builder.CreateShl(Val, ExtraBits), ExtraBits, "bf.val.sext"); } - // The bitfield type and the normal type differ when the storage sizes - // differ (currently just _Bool). + // The bitfield type and the normal type differ when the storage sizes differ + // (currently just _Bool). Val = Builder.CreateIntCast(Val, ConvertType(ExprType), false, "tmp"); return RValue::get(Val); @@ -389,27 +413,29 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV, QualType ExprType) { llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddr(), LV.isVolatileQualified(), "tmp"); - + const llvm::Constant *Elts = LV.getExtVectorElts(); - - // If the result of the expression is a non-vector type, we must be - // extracting a single element. Just codegen as an extractelement. - const VectorType *ExprVT = ExprType->getAsVectorType(); + + // If the result of the expression is a non-vector type, we must be extracting + // a single element. Just codegen as an extractelement. + const VectorType *ExprVT = ExprType->getAs<VectorType>(); if (!ExprVT) { unsigned InIdx = getAccessedFieldNo(0, Elts); - llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + llvm::Value *Elt = llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), InIdx); return RValue::get(Builder.CreateExtractElement(Vec, Elt, "tmp")); } // Always use shuffle vector to try to retain the original program structure unsigned NumResultElts = ExprVT->getNumElements(); - + llvm::SmallVector<llvm::Constant*, 4> Mask; for (unsigned i = 0; i != NumResultElts; ++i) { unsigned InIdx = getAccessedFieldNo(i, Elts); - Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx)); + Mask.push_back(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), InIdx)); } - + llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size()); Vec = Builder.CreateShuffleVector(Vec, llvm::UndefValue::get(Vec->getType()), @@ -422,7 +448,7 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV, /// EmitStoreThroughLValue - Store the specified rvalue into the specified /// lvalue, where both are guaranteed to the have the same type, and that type /// is 'Ty'. -void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, +void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, QualType Ty) { if (!Dst.isSimple()) { if (Dst.isVectorElt()) { @@ -434,7 +460,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, Builder.CreateStore(Vec, Dst.getVectorAddr(),Dst.isVolatileQualified()); return; } - + // If this is an update of extended vector elements, insert them as // appropriate. if (Dst.isExtVectorElt()) @@ -451,58 +477,60 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, assert(0 && "Unknown LValue type"); } - + if (Dst.isObjCWeak() && !Dst.isNonGC()) { - // load of a __weak object. + // load of a __weak object. llvm::Value *LvalueDst = Dst.getAddress(); llvm::Value *src = Src.getScalarVal(); CGM.getObjCRuntime().EmitObjCWeakAssign(*this, src, LvalueDst); return; } - + if (Dst.isObjCStrong() && !Dst.isNonGC()) { - // load of a __strong object. + // load of a __strong object. llvm::Value *LvalueDst = Dst.getAddress(); llvm::Value *src = Src.getScalarVal(); -#if 0 - // FIXME. We cannot positively determine if we have an 'ivar' assignment, - // object assignment or an unknown assignment. For now, generate call to - // objc_assign_strongCast assignment which is a safe, but consevative - // assumption. - if (Dst.isObjCIvar()) - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, LvalueDst); - else - CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst); -#endif - if (Dst.isGlobalObjCRef()) + if (Dst.isObjCIvar()) { + assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); + const llvm::Type *ResultType = ConvertType(getContext().LongTy); + llvm::Value *RHS = EmitScalarExpr(Dst.getBaseIvarExp()); + llvm::Value *dst = RHS; + RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); + llvm::Value *LHS = + Builder.CreatePtrToInt(LvalueDst, ResultType, "sub.ptr.lhs.cast"); + llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); + CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, + BytesBetween); + } + else if (Dst.isGlobalObjCRef()) CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst); else CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst); return; } - + assert(Src.isScalar() && "Can't emit an agg store with this method"); EmitStoreOfScalar(Src.getScalarVal(), Dst.getAddress(), Dst.isVolatileQualified(), Ty); } void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, - QualType Ty, + QualType Ty, llvm::Value **Result) { unsigned StartBit = Dst.getBitfieldStartBit(); unsigned BitfieldSize = Dst.getBitfieldSize(); llvm::Value *Ptr = Dst.getBitfieldAddr(); - const llvm::Type *EltTy = + const llvm::Type *EltTy = cast<llvm::PointerType>(Ptr->getType())->getElementType(); unsigned EltTySize = CGM.getTargetData().getTypeSizeInBits(EltTy); - // Get the new value, cast to the appropriate type and masked to - // exactly the size of the bit-field. + // Get the new value, cast to the appropriate type and masked to exactly the + // size of the bit-field. llvm::Value *SrcVal = Src.getScalarVal(); llvm::Value *NewVal = Builder.CreateIntCast(SrcVal, EltTy, false, "tmp"); - llvm::Constant *Mask = - llvm::ConstantInt::get(llvm::APInt::getLowBitsSet(EltTySize, BitfieldSize)); + llvm::Constant *Mask = llvm::ConstantInt::get(VMContext, + llvm::APInt::getLowBitsSet(EltTySize, BitfieldSize)); NewVal = Builder.CreateAnd(NewVal, Mask, "bf.value"); // Return the new value of the bit-field, if requested. @@ -517,61 +545,60 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, unsigned SrcTySize = CGM.getTargetData().getTypeSizeInBits(SrcTy); llvm::Value *ExtraBits = llvm::ConstantInt::get(SrcTy, SrcTySize - BitfieldSize); - SrcTrunc = Builder.CreateAShr(Builder.CreateShl(SrcTrunc, ExtraBits), + SrcTrunc = Builder.CreateAShr(Builder.CreateShl(SrcTrunc, ExtraBits), ExtraBits, "bf.reload.sext"); } *Result = SrcTrunc; } - // In some cases the bitfield may straddle two memory locations. - // Emit the low part first and check to see if the high needs to be - // done. + // In some cases the bitfield may straddle two memory locations. Emit the low + // part first and check to see if the high needs to be done. unsigned LowBits = std::min(BitfieldSize, EltTySize - StartBit); llvm::Value *LowVal = Builder.CreateLoad(Ptr, Dst.isVolatileQualified(), "bf.prev.low"); // Compute the mask for zero-ing the low part of this bitfield. - llvm::Constant *InvMask = - llvm::ConstantInt::get(~llvm::APInt::getBitsSet(EltTySize, StartBit, - StartBit + LowBits)); - + llvm::Constant *InvMask = + llvm::ConstantInt::get(VMContext, + ~llvm::APInt::getBitsSet(EltTySize, StartBit, StartBit + LowBits)); + // Compute the new low part as // LowVal = (LowVal & InvMask) | (NewVal << StartBit), // with the shift of NewVal implicitly stripping the high bits. - llvm::Value *NewLowVal = - Builder.CreateShl(NewVal, llvm::ConstantInt::get(EltTy, StartBit), - "bf.value.lo"); + llvm::Value *NewLowVal = + Builder.CreateShl(NewVal, llvm::ConstantInt::get(EltTy, StartBit), + "bf.value.lo"); LowVal = Builder.CreateAnd(LowVal, InvMask, "bf.prev.lo.cleared"); LowVal = Builder.CreateOr(LowVal, NewLowVal, "bf.new.lo"); - + // Write back. Builder.CreateStore(LowVal, Ptr, Dst.isVolatileQualified()); // If the low part doesn't cover the bitfield emit a high part. if (LowBits < BitfieldSize) { unsigned HighBits = BitfieldSize - LowBits; - llvm::Value *HighPtr = - Builder.CreateGEP(Ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, 1), - "bf.ptr.hi"); - llvm::Value *HighVal = Builder.CreateLoad(HighPtr, + llvm::Value *HighPtr = Builder.CreateGEP(Ptr, llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), 1), "bf.ptr.hi"); + llvm::Value *HighVal = Builder.CreateLoad(HighPtr, Dst.isVolatileQualified(), "bf.prev.hi"); - + // Compute the mask for zero-ing the high part of this bitfield. - llvm::Constant *InvMask = - llvm::ConstantInt::get(~llvm::APInt::getLowBitsSet(EltTySize, HighBits)); - + llvm::Constant *InvMask = + llvm::ConstantInt::get(VMContext, ~llvm::APInt::getLowBitsSet(EltTySize, + HighBits)); + // Compute the new high part as // HighVal = (HighVal & InvMask) | (NewVal lshr LowBits), // where the high bits of NewVal have already been cleared and the // shift stripping the low bits. - llvm::Value *NewHighVal = - Builder.CreateLShr(NewVal, llvm::ConstantInt::get(EltTy, LowBits), - "bf.value.high"); + llvm::Value *NewHighVal = + Builder.CreateLShr(NewVal, llvm::ConstantInt::get(EltTy, LowBits), + "bf.value.high"); HighVal = Builder.CreateAnd(HighVal, InvMask, "bf.prev.hi.cleared"); HighVal = Builder.CreateOr(HighVal, NewHighVal, "bf.new.hi"); - + // Write back. Builder.CreateStore(HighVal, HighPtr, Dst.isVolatileQualified()); } @@ -597,29 +624,29 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddr(), Dst.isVolatileQualified(), "tmp"); const llvm::Constant *Elts = Dst.getExtVectorElts(); - + llvm::Value *SrcVal = Src.getScalarVal(); - - if (const VectorType *VTy = Ty->getAsVectorType()) { + + if (const VectorType *VTy = Ty->getAs<VectorType>()) { unsigned NumSrcElts = VTy->getNumElements(); unsigned NumDstElts = cast<llvm::VectorType>(Vec->getType())->getNumElements(); if (NumDstElts == NumSrcElts) { - // Use shuffle vector is the src and destination are the same number - // of elements and restore the vector mask since it is on the side - // it will be stored. + // Use shuffle vector is the src and destination are the same number of + // elements and restore the vector mask since it is on the side it will be + // stored. llvm::SmallVector<llvm::Constant*, 4> Mask(NumDstElts); for (unsigned i = 0; i != NumSrcElts; ++i) { unsigned InIdx = getAccessedFieldNo(i, Elts); - Mask[InIdx] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Mask[InIdx] = llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), i); } - + llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size()); Vec = Builder.CreateShuffleVector(SrcVal, llvm::UndefValue::get(Vec->getType()), MaskV, "tmp"); - } - else if (NumDstElts > NumSrcElts) { + } else if (NumDstElts > NumSrcElts) { // Extended the source vector to the same length and then shuffle it // into the destination. // FIXME: since we're shuffling with undef, can we just use the indices @@ -627,96 +654,153 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src, llvm::SmallVector<llvm::Constant*, 4> ExtMask; unsigned i; for (i = 0; i != NumSrcElts; ++i) - ExtMask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i)); + ExtMask.push_back(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), i)); for (; i != NumDstElts; ++i) - ExtMask.push_back(llvm::UndefValue::get(llvm::Type::Int32Ty)); + ExtMask.push_back(llvm::UndefValue::get( + llvm::Type::getInt32Ty(VMContext))); llvm::Value *ExtMaskV = llvm::ConstantVector::get(&ExtMask[0], ExtMask.size()); - llvm::Value *ExtSrcVal = + llvm::Value *ExtSrcVal = Builder.CreateShuffleVector(SrcVal, llvm::UndefValue::get(SrcVal->getType()), ExtMaskV, "tmp"); // build identity llvm::SmallVector<llvm::Constant*, 4> Mask; for (unsigned i = 0; i != NumDstElts; ++i) { - Mask.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, i)); + Mask.push_back(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), i)); } // modify when what gets shuffled in for (unsigned i = 0; i != NumSrcElts; ++i) { unsigned Idx = getAccessedFieldNo(i, Elts); - Mask[Idx] =llvm::ConstantInt::get(llvm::Type::Int32Ty, i+NumDstElts); + Mask[Idx] = llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), i+NumDstElts); } llvm::Value *MaskV = llvm::ConstantVector::get(&Mask[0], Mask.size()); Vec = Builder.CreateShuffleVector(Vec, ExtSrcVal, MaskV, "tmp"); - } - else { + } else { // We should never shorten the vector assert(0 && "unexpected shorten vector length"); } } else { // If the Src is a scalar (not a vector) it must be updating one element. unsigned InIdx = getAccessedFieldNo(0, Elts); - llvm::Value *Elt = llvm::ConstantInt::get(llvm::Type::Int32Ty, InIdx); + llvm::Value *Elt = llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), InIdx); Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt, "tmp"); } - + Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified()); } +// setObjCGCLValueClass - sets class of he lvalue for the purpose of +// generating write-barries API. It is currently a global, ivar, +// or neither. +static +void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) { + if (Ctx.getLangOptions().getGCMode() == LangOptions::NonGC) + return; + + if (isa<ObjCIvarRefExpr>(E)) { + LV.SetObjCIvar(LV, true); + ObjCIvarRefExpr *Exp = cast<ObjCIvarRefExpr>(const_cast<Expr*>(E)); + LV.setBaseIvarExp(Exp->getBase()); + LV.SetObjCArray(LV, E->getType()->isArrayType()); + return; + } + if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) { + if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) || + VD->isFileVarDecl()) + LV.SetGlobalObjCRef(LV, true); + } + LV.SetObjCArray(LV, E->getType()->isArrayType()); + } + else if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E)) + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + else if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) { + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + if (LV.isObjCIvar()) { + // If cast is to a structure pointer, follow gcc's behavior and make it + // a non-ivar write-barrier. + QualType ExpTy = E->getType(); + if (ExpTy->isPointerType()) + ExpTy = ExpTy->getAs<PointerType>()->getPointeeType(); + if (ExpTy->isRecordType()) + LV.SetObjCIvar(LV, false); + } + } + else if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E)) + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + else if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E)) + setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + else if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) { + setObjCGCLValueClass(Ctx, Exp->getBase(), LV); + if (LV.isObjCIvar() && !LV.isObjCArray()) + // Using array syntax to assigning to what an ivar points to is not + // same as assigning to the ivar itself. {id *Names;} Names[i] = 0; + LV.SetObjCIvar(LV, false); + else if (LV.isGlobalObjCRef() && !LV.isObjCArray()) + // Using array syntax to assigning to what global points to is not + // same as assigning to the global itself. {id *G;} G[i] = 0; + LV.SetGlobalObjCRef(LV, false); + } + else if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) { + setObjCGCLValueClass(Ctx, Exp->getBase(), LV); + // We don't know if member is an 'ivar', but this flag is looked at + // only in the context of LV.isObjCIvar(). + LV.SetObjCArray(LV, E->getType()->isArrayType()); + } +} + LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()); - + if (VD && (VD->isBlockVarDecl() || isa<ParmVarDecl>(VD) || isa<ImplicitParamDecl>(VD))) { LValue LV; - bool NonGCable = VD->hasLocalStorage() && + bool NonGCable = VD->hasLocalStorage() && !VD->hasAttr<BlocksAttr>(); if (VD->hasExternalStorage()) { llvm::Value *V = CGM.GetAddrOfGlobalVar(VD); if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); - } - else { + LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); + } else { llvm::Value *V = LocalDeclMap[VD]; assert(V && "DeclRefExpr not entered in LocalDeclMap?"); + + Qualifiers Quals = MakeQualifiers(E->getType()); // local variables do not get their gc attribute set. - QualType::GCAttrTypes attr = QualType::GCNone; // local static? - if (!NonGCable) - attr = getContext().getObjCGCAttrKind(E->getType()); + if (NonGCable) Quals.removeObjCGCAttr(); + if (VD->hasAttr<BlocksAttr>()) { - bool needsCopyDispose = BlockRequiresCopying(VD->getType()); - const llvm::Type *PtrStructTy = V->getType(); - const llvm::Type *Ty = PtrStructTy; - Ty = llvm::PointerType::get(Ty, 0); V = Builder.CreateStructGEP(V, 1, "forwarding"); - V = Builder.CreateBitCast(V, Ty); V = Builder.CreateLoad(V, false); - V = Builder.CreateBitCast(V, PtrStructTy); - V = Builder.CreateStructGEP(V, needsCopyDispose*2 + 4, "x"); + V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD), + VD->getNameAsString()); } if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), attr); + LV = LValue::MakeAddr(V, Quals); } LValue::SetObjCNonGC(LV, NonGCable); + setObjCGCLValueClass(getContext(), E, LV); return LV; } else if (VD && VD->isFileVarDecl()) { llvm::Value *V = CGM.GetAddrOfGlobalVar(VD); if (VD->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); - if (LV.isObjCStrong()) - LV.SetGlobalObjCRef(LV, true); + LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); + setObjCGCLValueClass(getContext(), E, LV); return LV; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) { - llvm::Value* V = CGM.GetAddrOfFunction(GlobalDecl(FD)); + llvm::Value* V = CGM.GetAddrOfFunction(FD); if (!FD->hasPrototype()) { if (const FunctionProtoType *Proto = - FD->getType()->getAsFunctionProtoType()) { + FD->getType()->getAs<FunctionProtoType>()) { // Ugly case: for a K&R-style definition, the type of the definition // isn't the same as the type of a use. Correct for this with a // bitcast. @@ -726,15 +810,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { V = Builder.CreateBitCast(V, ConvertType(NoProtoType), "tmp"); } } - return LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); - } - else if (const ImplicitParamDecl *IPD = + return LValue::MakeAddr(V, MakeQualifiers(E->getType())); + } else if (const ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(E->getDecl())) { llvm::Value *V = LocalDeclMap[IPD]; assert(V && "BlockVarDecl not entered in LocalDeclMap?"); - return LValue::MakeAddr(V, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + return LValue::MakeAddr(V, MakeQualifiers(E->getType())); } assert(0 && "Unimp declref"); //an invalid LValue, but the assert will @@ -743,27 +824,26 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { } LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) { - return LValue::MakeAddr(GetAddrOfBlockDecl(E), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + return LValue::MakeAddr(GetAddrOfBlockDecl(E), MakeQualifiers(E->getType())); } LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { // __extension__ doesn't affect lvalue-ness. if (E->getOpcode() == UnaryOperator::Extension) return EmitLValue(E->getSubExpr()); - + QualType ExprTy = getContext().getCanonicalType(E->getSubExpr()->getType()); switch (E->getOpcode()) { default: assert(0 && "Unknown unary operator lvalue!"); case UnaryOperator::Deref: { - QualType T = - E->getSubExpr()->getType()->getAsPointerType()->getPointeeType(); - LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), - ExprTy->getAsPointerType()->getPointeeType() - .getCVRQualifiers(), - getContext().getObjCGCAttrKind(T)); + QualType T = E->getSubExpr()->getType()->getPointeeType(); + assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type"); + + Qualifiers Quals = MakeQualifiers(T); + Quals.setAddressSpace(ExprTy.getAddressSpace()); + + LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals); // We should not generate __weak write barrier on indirect reference // of a pointer to object; as in void foo (__weak id *param); *param = 0; // But, we continue to generate __strong write barrier on indirect write @@ -780,16 +860,18 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) { unsigned Idx = E->getOpcode() == UnaryOperator::Imag; return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(), Idx, "idx"), - ExprTy.getCVRQualifiers()); + MakeQualifiers(ExprTy)); } } LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) { - return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), 0); + return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), + Qualifiers()); } LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) { - return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E), 0); + return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E), + Qualifiers()); } @@ -806,32 +888,25 @@ LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) { GlobalVarName = "__FUNCTION__."; break; case PredefinedExpr::PrettyFunction: - // FIXME:: Demangle C++ method names GlobalVarName = "__PRETTY_FUNCTION__."; break; } - // FIXME: This isn't right at all. The logic for computing this should go - // into a method on PredefinedExpr. This would allow sema and codegen to be - // consistent for things like sizeof(__func__) etc. - std::string FunctionName; - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl)) { - FunctionName = CGM.getMangledName(FD); - } else { - // Just get the mangled name; skipping the asm prefix if it - // exists. - FunctionName = CurFn->getName(); - if (FunctionName[0] == '\01') - FunctionName = FunctionName.substr(1, std::string::npos); - } + llvm::StringRef FnName = CurFn->getName(); + if (FnName.startswith("\01")) + FnName = FnName.substr(1); + GlobalVarName += FnName; - GlobalVarName += FunctionName; - llvm::Constant *C = + std::string FunctionName = + PredefinedExpr::ComputeName(getContext(), (PredefinedExpr::IdentType)Type, + CurCodeDecl); + + llvm::Constant *C = CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str()); - return LValue::MakeAddr(C, 0); + return LValue::MakeAddr(C, Qualifiers()); } -LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { +LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { switch (E->getIdentType()) { default: return EmitUnsupportedLValue(E, "predefined expression"); @@ -854,68 +929,78 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { // Emit the vector as an lvalue to get its address. LValue LHS = EmitLValue(E->getBase()); assert(LHS.isSimple() && "Can only subscript lvalue vectors here!"); - Idx = Builder.CreateIntCast(Idx, llvm::Type::Int32Ty, IdxSigned, "vidx"); + Idx = Builder.CreateIntCast(Idx, + llvm::Type::getInt32Ty(VMContext), IdxSigned, "vidx"); return LValue::MakeVectorElt(LHS.getAddress(), Idx, - E->getBase()->getType().getCVRQualifiers()); + E->getBase()->getType().getCVRQualifiers()); } - + // The base must be a pointer, which is not an aggregate. Emit it. llvm::Value *Base = EmitScalarExpr(E->getBase()); - + // Extend or truncate the index type to 32 or 64-bits. unsigned IdxBitwidth = cast<llvm::IntegerType>(Idx->getType())->getBitWidth(); if (IdxBitwidth != LLVMPointerWidth) - Idx = Builder.CreateIntCast(Idx, llvm::IntegerType::get(LLVMPointerWidth), + Idx = Builder.CreateIntCast(Idx, + llvm::IntegerType::get(VMContext, LLVMPointerWidth), IdxSigned, "idxprom"); - // We know that the pointer points to a type of the correct size, - // unless the size is a VLA or Objective-C interface. + // We know that the pointer points to a type of the correct size, unless the + // size is a VLA or Objective-C interface. llvm::Value *Address = 0; - if (const VariableArrayType *VAT = + if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(E->getType())) { - llvm::Value *VLASize = VLASizeMap[VAT]; - + llvm::Value *VLASize = GetVLASize(VAT); + Idx = Builder.CreateMul(Idx, VLASize); - + QualType BaseType = getContext().getBaseElementType(VAT); - + uint64_t BaseTypeSize = getContext().getTypeSize(BaseType) / 8; Idx = Builder.CreateUDiv(Idx, - llvm::ConstantInt::get(Idx->getType(), + llvm::ConstantInt::get(Idx->getType(), BaseTypeSize)); - Address = Builder.CreateGEP(Base, Idx, "arrayidx"); - } else if (const ObjCInterfaceType *OIT = + Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); + } else if (const ObjCInterfaceType *OIT = dyn_cast<ObjCInterfaceType>(E->getType())) { - llvm::Value *InterfaceSize = + llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), getContext().getTypeSize(OIT) / 8); - + Idx = Builder.CreateMul(Idx, InterfaceSize); - llvm::Type *i8PTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - Address = Builder.CreateGEP(Builder.CreateBitCast(Base, i8PTy), + const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(VMContext); + Address = Builder.CreateGEP(Builder.CreateBitCast(Base, i8PTy), Idx, "arrayidx"); Address = Builder.CreateBitCast(Address, Base->getType()); } else { - Address = Builder.CreateGEP(Base, Idx, "arrayidx"); + Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); } - - QualType T = E->getBase()->getType()->getAsPointerType()->getPointeeType(); - LValue LV = LValue::MakeAddr(Address, - T.getCVRQualifiers(), - getContext().getObjCGCAttrKind(T)); + + QualType T = E->getBase()->getType()->getPointeeType(); + assert(!T.isNull() && + "CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type"); + + Qualifiers Quals = MakeQualifiers(T); + Quals.setAddressSpace(E->getBase()->getType().getAddressSpace()); + + LValue LV = LValue::MakeAddr(Address, Quals); if (getContext().getLangOptions().ObjC1 && - getContext().getLangOptions().getGCMode() != LangOptions::NonGC) + getContext().getLangOptions().getGCMode() != LangOptions::NonGC) { LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext())); + setObjCGCLValueClass(getContext(), E, LV); + } return LV; } -static -llvm::Constant *GenerateConstantVector(llvm::SmallVector<unsigned, 4> &Elts) { +static +llvm::Constant *GenerateConstantVector(llvm::LLVMContext &VMContext, + llvm::SmallVector<unsigned, 4> &Elts) { llvm::SmallVector<llvm::Constant *, 4> CElts; - + for (unsigned i = 0, e = Elts.size(); i != e; ++i) - CElts.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, Elts[i])); + CElts.push_back(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), Elts[i])); return llvm::ConstantVector::get(&CElts[0], CElts.size()); } @@ -930,9 +1015,11 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { assert(E->getBase()->getType()->isVectorType()); Base = EmitLValue(E->getBase()); } else { - const PointerType *PT = E->getBase()->getType()->getAsPointerType(); + const PointerType *PT = E->getBase()->getType()->getAs<PointerType>(); llvm::Value *Ptr = EmitScalarExpr(E->getBase()); - Base = LValue::MakeAddr(Ptr, PT->getPointeeType().getCVRQualifiers()); + Qualifiers Quals = MakeQualifiers(PT->getPointeeType()); + Quals.removeObjCGCAttr(); + Base = LValue::MakeAddr(Ptr, Quals); } // Encode the element access list into a vector of unsigned indices. @@ -940,9 +1027,9 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { E->getEncodedElementAccess(Indices); if (Base.isSimple()) { - llvm::Constant *CV = GenerateConstantVector(Indices); + llvm::Constant *CV = GenerateConstantVector(VMContext, Indices); return LValue::MakeExtVectorElt(Base.getAddress(), CV, - Base.getQualifiers()); + Base.getVRQualifiers()); } assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); @@ -951,68 +1038,69 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { for (unsigned i = 0, e = Indices.size(); i != e; ++i) { if (isa<llvm::ConstantAggregateZero>(BaseElts)) - CElts.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0)); + CElts.push_back(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), 0)); else CElts.push_back(BaseElts->getOperand(Indices[i])); } llvm::Constant *CV = llvm::ConstantVector::get(&CElts[0], CElts.size()); return LValue::MakeExtVectorElt(Base.getExtVectorAddr(), CV, - Base.getQualifiers()); + Base.getVRQualifiers()); } LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { bool isUnion = false; - bool isIvar = false; bool isNonGC = false; Expr *BaseExpr = E->getBase(); llvm::Value *BaseValue = NULL; - unsigned CVRQualifiers=0; + Qualifiers BaseQuals; // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. if (E->isArrow()) { BaseValue = EmitScalarExpr(BaseExpr); - const PointerType *PTy = - BaseExpr->getType()->getAsPointerType(); + const PointerType *PTy = + BaseExpr->getType()->getAs<PointerType>(); if (PTy->getPointeeType()->isUnionType()) isUnion = true; - CVRQualifiers = PTy->getPointeeType().getCVRQualifiers(); - } else if (isa<ObjCPropertyRefExpr>(BaseExpr) || - isa<ObjCKVCRefExpr>(BaseExpr)) { + BaseQuals = PTy->getPointeeType().getQualifiers(); + } else if (isa<ObjCPropertyRefExpr>(BaseExpr->IgnoreParens()) || + isa<ObjCImplicitSetterGetterRefExpr>( + BaseExpr->IgnoreParens())) { RValue RV = EmitObjCPropertyGet(BaseExpr); BaseValue = RV.getAggregateAddr(); if (BaseExpr->getType()->isUnionType()) isUnion = true; - CVRQualifiers = BaseExpr->getType().getCVRQualifiers(); + BaseQuals = BaseExpr->getType().getQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); - if (BaseLV.isObjCIvar()) - isIvar = true; if (BaseLV.isNonGC()) isNonGC = true; // FIXME: this isn't right for bitfields. BaseValue = BaseLV.getAddress(); - if (BaseExpr->getType()->isUnionType()) + QualType BaseTy = BaseExpr->getType(); + if (BaseTy->isUnionType()) isUnion = true; - CVRQualifiers = BaseExpr->getType().getCVRQualifiers(); + BaseQuals = BaseTy.getQualifiers(); } FieldDecl *Field = dyn_cast<FieldDecl>(E->getMemberDecl()); // FIXME: Handle non-field member expressions assert(Field && "No code generation for non-field member references"); LValue MemExpLV = EmitLValueForField(BaseValue, Field, isUnion, - CVRQualifiers); - LValue::SetObjCIvar(MemExpLV, isIvar); + BaseQuals.getCVRQualifiers()); LValue::SetObjCNonGC(MemExpLV, isNonGC); + setObjCGCLValueClass(getContext(), E, MemExpLV); return MemExpLV; } LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue, FieldDecl* Field, unsigned CVRQualifiers) { - unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); + CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field); + // FIXME: CodeGenTypes should expose a method to get the appropriate type for // FieldTy (the appropriate type is ABI-dependent). - const llvm::Type *FieldTy = + const llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(Field->getType()); const llvm::PointerType *BaseTy = cast<llvm::PointerType>(BaseValue->getType()); @@ -1020,13 +1108,12 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue, BaseValue = Builder.CreateBitCast(BaseValue, llvm::PointerType::get(FieldTy, AS), "tmp"); - llvm::Value *V = Builder.CreateGEP(BaseValue, - llvm::ConstantInt::get(llvm::Type::Int32Ty, idx), - "tmp"); - - CodeGenTypes::BitFieldInfo bitFieldInfo = - CGM.getTypes().getBitFieldInfo(Field); - return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size, + + llvm::Value *Idx = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Info.FieldNo); + llvm::Value *V = Builder.CreateGEP(BaseValue, Idx, "tmp"); + + return LValue::MakeBitfield(V, Info.Start, Info.Size, Field->getType()->isSignedIntegerType(), Field->getType().getCVRQualifiers()|CVRQualifiers); } @@ -1034,46 +1121,34 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue, LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue, FieldDecl* Field, bool isUnion, - unsigned CVRQualifiers) -{ + unsigned CVRQualifiers) { if (Field->isBitField()) return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers); - + unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp"); // Match union field type. if (isUnion) { - const llvm::Type *FieldTy = + const llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(Field->getType()); - const llvm::PointerType * BaseTy = + const llvm::PointerType * BaseTy = cast<llvm::PointerType>(BaseValue->getType()); unsigned AS = BaseTy->getAddressSpace(); - V = Builder.CreateBitCast(V, - llvm::PointerType::get(FieldTy, AS), + V = Builder.CreateBitCast(V, + llvm::PointerType::get(FieldTy, AS), "tmp"); } if (Field->getType()->isReferenceType()) V = Builder.CreateLoad(V, "tmp"); - QualType::GCAttrTypes attr = QualType::GCNone; - if (CGM.getLangOptions().ObjC1 && - CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { - QualType Ty = Field->getType(); - attr = Ty.getObjCGCAttr(); - if (attr != QualType::GCNone) { - // __weak attribute on a field is ignored. - if (attr == QualType::Weak) - attr = QualType::GCNone; - } - else if (getContext().isObjCObjectPointerType(Ty)) - attr = QualType::Strong; - } - LValue LV = - LValue::MakeAddr(V, - Field->getType().getCVRQualifiers()|CVRQualifiers, - attr); - return LV; + Qualifiers Quals = MakeQualifiers(Field->getType()); + Quals.addCVRQualifiers(CVRQualifiers); + // __weak attribute on a field is ignored. + if (Quals.getObjCGCAttr() == Qualifiers::Weak) + Quals.removeObjCGCAttr(); + + return LValue::MakeAddr(V, Quals); } LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){ @@ -1081,7 +1156,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){ llvm::Value *DeclPtr = CreateTempAlloca(LTy, ".compoundliteral"); const Expr* InitExpr = E->getInitializer(); - LValue Result = LValue::MakeAddr(DeclPtr, E->getType().getCVRQualifiers()); + LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType())); if (E->getType()->isComplexType()) { EmitComplexExprIntoAddr(InitExpr, DeclPtr, false); @@ -1094,22 +1169,51 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){ return Result; } -LValue CodeGenFunction::EmitConditionalOperator(const ConditionalOperator* E) { - // We don't handle vectors yet. - if (E->getType()->isVectorType()) - return EmitUnsupportedLValue(E, "conditional operator"); +LValue +CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) { + if (E->isLvalue(getContext()) == Expr::LV_Valid) { + llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true"); + llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false"); + llvm::BasicBlock *ContBlock = createBasicBlock("cond.end"); + + llvm::Value *Cond = EvaluateExprAsBool(E->getCond()); + Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); + + EmitBlock(LHSBlock); + + LValue LHS = EmitLValue(E->getLHS()); + if (!LHS.isSimple()) + return EmitUnsupportedLValue(E, "conditional operator"); + + llvm::Value *Temp = CreateTempAlloca(LHS.getAddress()->getType(), + "condtmp"); + + Builder.CreateStore(LHS.getAddress(), Temp); + EmitBranch(ContBlock); + + EmitBlock(RHSBlock); + LValue RHS = EmitLValue(E->getRHS()); + if (!RHS.isSimple()) + return EmitUnsupportedLValue(E, "conditional operator"); + + Builder.CreateStore(RHS.getAddress(), Temp); + EmitBranch(ContBlock); + EmitBlock(ContBlock); + + Temp = Builder.CreateLoad(Temp, "lv"); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); + } + // ?: here should be an aggregate. - assert((hasAggregateLLVMType(E->getType()) && + assert((hasAggregateLLVMType(E->getType()) && !E->getType()->isAnyComplexType()) && "Unexpected conditional operator!"); llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); EmitAggExpr(E, Temp, false); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); - + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } /// EmitCastLValue - Casts are never lvalues. If a cast is needed by the code @@ -1118,21 +1222,47 @@ LValue CodeGenFunction::EmitConditionalOperator(const ConditionalOperator* E) { /// all the reasons that casts are permitted with aggregate result, including /// noop aggregate casts, and cast from scalar to union. LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { - // If this is an aggregate-to-aggregate cast, just use the input's address as - // the lvalue. - if (getContext().hasSameUnqualifiedType(E->getType(), - E->getSubExpr()->getType())) + switch (E->getCastKind()) { + default: + // If this is an lvalue cast, treat it as a no-op. + // FIXME: We shouldn't need to check for this explicitly! + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + if (ICE->isLvalueCast()) + return EmitLValue(E->getSubExpr()); + + assert(0 && "Unhandled cast!"); + + case CastExpr::CK_NoOp: + case CastExpr::CK_ConstructorConversion: + case CastExpr::CK_UserDefinedConversion: return EmitLValue(E->getSubExpr()); - - // Otherwise, we must have a cast from scalar to union. - assert(E->getType()->isUnionType() && "Expected scalar-to-union cast"); - - // Casts are only lvalues when the source and destination types are the same. - llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); - EmitAnyExpr(E->getSubExpr(), Temp, false); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + case CastExpr::CK_DerivedToBase: { + const RecordType *DerivedClassTy = + E->getSubExpr()->getType()->getAs<RecordType>(); + CXXRecordDecl *DerivedClassDecl = + cast<CXXRecordDecl>(DerivedClassTy->getDecl()); + + const RecordType *BaseClassTy = E->getType()->getAs<RecordType>(); + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseClassTy->getDecl()); + + LValue LV = EmitLValue(E->getSubExpr()); + + // Perform the derived-to-base conversion + llvm::Value *Base = + GetAddressCXXOfBaseClass(LV.getAddress(), DerivedClassDecl, + BaseClassDecl, /*NullCheckValue=*/false); + + return LValue::MakeAddr(Base, MakeQualifiers(E->getType())); + } + + case CastExpr::CK_ToUnion: { + llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); + EmitAnyExpr(E->getSubExpr(), Temp, false); + + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); + } + } } //===--------------------------------------------------------------------===// @@ -1147,13 +1277,13 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { if (const CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(E)) return EmitCXXMemberCallExpr(CE); - + const Decl *TargetDecl = 0; if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E->getCallee())) { if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) { TargetDecl = DRE->getDecl(); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(TargetDecl)) - if (unsigned builtinID = FD->getBuiltinID(getContext())) + if (unsigned builtinID = FD->getBuiltinID()) return EmitBuiltinExpr(FD, builtinID, E); } } @@ -1161,7 +1291,17 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) { if (const CXXOperatorCallExpr *CE = dyn_cast<CXXOperatorCallExpr>(E)) if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl)) return EmitCXXOperatorMemberCallExpr(CE, MD); - + + if (isa<CXXPseudoDestructorExpr>(E->getCallee())) { + // C++ [expr.pseudo]p1: + // The result shall only be used as the operand for the function call + // operator (), and the result of such a call has type void. The only + // effect is the evaluation of the postfix-expression before the dot or + // arrow. + EmitScalarExpr(E->getCallee()); + return RValue::get(0); + } + llvm::Value *Callee = EmitScalarExpr(E->getCallee()); return EmitCall(Callee, E->getCallee()->getType(), E->arg_begin(), E->arg_end(), TargetDecl); @@ -1173,7 +1313,7 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { EmitAnyExpr(E->getLHS()); return EmitLValue(E->getRHS()); } - + // Can only get l-value for binary operator expressions which are a // simple assignment of aggregate type. if (E->getOpcode() != BinaryOperator::Assign) @@ -1182,8 +1322,7 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) { llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); EmitAggExpr(E, Temp, false); // FIXME: Are these qualifiers correct? - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { @@ -1193,21 +1332,18 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { assert(E->getCallReturnType()->isReferenceType() && "Can't have a scalar return unless the return type is a " "reference type!"); - - return LValue::MakeAddr(RV.getScalarVal(), E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + + return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType())); } - - return LValue::MakeAddr(RV.getAggregateAddr(), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + + return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) { // FIXME: This shouldn't require another copy. llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType())); EmitAggExpr(E, Temp, false); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } LValue @@ -1219,15 +1355,15 @@ CodeGenFunction::EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E) { LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "tmp"); EmitCXXConstructExpr(Temp, E); - return LValue::MakeAddr(Temp, E->getType().getCVRQualifiers()); + return LValue::MakeAddr(Temp, MakeQualifiers(E->getType())); } LValue CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) { LValue LV = EmitLValue(E->getSubExpr()); - + PushCXXTemporary(E->getTemporary(), LV.getAddress()); - + return LV; } @@ -1235,9 +1371,7 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) { // Can only get l-value for message expression returning aggregate type RValue RV = EmitObjCMessageExpr(E); // FIXME: can this be volatile? - return LValue::MakeAddr(RV.getAggregateAddr(), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface, @@ -1257,35 +1391,39 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) { // FIXME: A lot of the code below could be shared with EmitMemberExpr. llvm::Value *BaseValue = 0; const Expr *BaseExpr = E->getBase(); - unsigned CVRQualifiers = 0; + Qualifiers BaseQuals; QualType ObjectTy; if (E->isArrow()) { BaseValue = EmitScalarExpr(BaseExpr); - const PointerType *PTy = BaseExpr->getType()->getAsPointerType(); - ObjectTy = PTy->getPointeeType(); - CVRQualifiers = ObjectTy.getCVRQualifiers(); + ObjectTy = BaseExpr->getType()->getPointeeType(); + BaseQuals = ObjectTy.getQualifiers(); } else { LValue BaseLV = EmitLValue(BaseExpr); // FIXME: this isn't right for bitfields. BaseValue = BaseLV.getAddress(); ObjectTy = BaseExpr->getType(); - CVRQualifiers = ObjectTy.getCVRQualifiers(); + BaseQuals = ObjectTy.getQualifiers(); } - return EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), CVRQualifiers); + LValue LV = + EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), + BaseQuals.getCVRQualifiers()); + setObjCGCLValueClass(getContext(), E, LV); + return LV; } -LValue +LValue CodeGenFunction::EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E) { - // This is a special l-value that just issues sends when we load or - // store through it. + // This is a special l-value that just issues sends when we load or store + // through it. return LValue::MakePropertyRef(E, E->getType().getCVRQualifiers()); } -LValue -CodeGenFunction::EmitObjCKVCRefLValue(const ObjCKVCRefExpr *E) { - // This is a special l-value that just issues sends when we load or - // store through it. +LValue +CodeGenFunction::EmitObjCKVCRefLValue( + const ObjCImplicitSetterGetterRefExpr *E) { + // This is a special l-value that just issues sends when we load or store + // through it. return LValue::MakeKVCRef(E, E->getType().getCVRQualifiers()); } @@ -1295,31 +1433,36 @@ CodeGenFunction::EmitObjCSuperExprLValue(const ObjCSuperExpr *E) { } LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) { - + // Can only get l-value for message expression returning aggregate type RValue RV = EmitAnyExprToTemp(E); // FIXME: can this be volatile? - return LValue::MakeAddr(RV.getAggregateAddr(), - E->getType().getCVRQualifiers(), - getContext().getObjCGCAttrKind(E->getType())); + return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType())); } -RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType, +RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, const Decl *TargetDecl) { - // Get the actual function type. The callee type will always be a - // pointer to function type or a block pointer type. - assert(CalleeType->isFunctionPointerType() && + // Get the actual function type. The callee type will always be a pointer to + // function type or a block pointer type. + assert(CalleeType->isFunctionPointerType() && "Call must have function pointer type!"); - QualType FnType = CalleeType->getAsPointerType()->getPointeeType(); - QualType ResultType = FnType->getAsFunctionType()->getResultType(); + QualType FnType = CalleeType->getAs<PointerType>()->getPointeeType(); + QualType ResultType = FnType->getAs<FunctionType>()->getResultType(); CallArgList Args; - EmitCallArgs(Args, FnType->getAsFunctionProtoType(), ArgBeg, ArgEnd); - - return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), + EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), ArgBeg, ArgEnd); + + // FIXME: We should not need to do this, it should be part of the function + // type. + unsigned CallingConvention = 0; + if (const llvm::Function *F = + dyn_cast<llvm::Function>(Callee->stripPointerCasts())) + CallingConvention = F->getCallingConv(); + return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args, + CallingConvention), Callee, Args, TargetDecl); } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 412a06594f532..0866ff893c4e3 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -13,6 +13,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/StmtVisitor.h" @@ -35,12 +36,14 @@ class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor<AggExprEmitter> { llvm::Value *DestPtr; bool VolatileDest; bool IgnoreResult; - + bool IsInitializer; + bool RequiresGCollection; public: AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool v, - bool ignore) + bool ignore, bool isinit, bool requiresGCollection) : CGF(cgf), Builder(CGF.Builder), - DestPtr(destPtr), VolatileDest(v), IgnoreResult(ignore) { + DestPtr(destPtr), VolatileDest(v), IgnoreResult(ignore), + IsInitializer(isinit), RequiresGCollection(requiresGCollection) { } //===--------------------------------------------------------------------===// @@ -59,7 +62,7 @@ public: //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// - + void VisitStmt(Stmt *S) { CGF.ErrorUnsupported(S, "aggregate expression"); } @@ -72,35 +75,36 @@ public: void VisitUnaryDeref(UnaryOperator *E) { EmitAggLoadOfLValue(E); } void VisitStringLiteral(StringLiteral *E) { EmitAggLoadOfLValue(E); } void VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - EmitAggLoadOfLValue(E); + EmitAggLoadOfLValue(E); } void VisitArraySubscriptExpr(ArraySubscriptExpr *E) { EmitAggLoadOfLValue(E); } void VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) { - EmitAggLoadOfLValue(E); + EmitAggLoadOfLValue(E); } void VisitPredefinedExpr(const PredefinedExpr *E) { - EmitAggLoadOfLValue(E); + EmitAggLoadOfLValue(E); } - + // Operators. - void VisitCStyleCastExpr(CStyleCastExpr *E); - void VisitImplicitCastExpr(ImplicitCastExpr *E); + void VisitCastExpr(CastExpr *E); void VisitCallExpr(const CallExpr *E); void VisitStmtExpr(const StmtExpr *E); void VisitBinaryOperator(const BinaryOperator *BO); void VisitBinAssign(const BinaryOperator *E); void VisitBinComma(const BinaryOperator *E); + void VisitUnaryAddrOf(const UnaryOperator *E); void VisitObjCMessageExpr(ObjCMessageExpr *E); void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { EmitAggLoadOfLValue(E); } void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E); - void VisitObjCKVCRefExpr(ObjCKVCRefExpr *E); - + void VisitObjCImplicitSetterGetterRefExpr(ObjCImplicitSetterGetterRefExpr *E); + void VisitConditionalOperator(const ConditionalOperator *CO); + void VisitChooseExpr(const ChooseExpr *CE); void VisitInitListExpr(InitListExpr *E); void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { Visit(DAE->getExpr()); @@ -143,6 +147,12 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { DestPtr = CGF.CreateTempAlloca(CGF.ConvertType(E->getType()), "agg.tmp"); } + if (RequiresGCollection) { + CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, + DestPtr, Src.getAggregateAddr(), + E->getType()); + return; + } // If the result of the assignment is used, copy the LHS there also. // FIXME: Pass VolatileDest as well. I think we also need to merge volatile // from the source as well, as we can't eliminate it if either operand @@ -164,25 +174,80 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { // Visitor Methods //===----------------------------------------------------------------------===// -void AggExprEmitter::VisitCStyleCastExpr(CStyleCastExpr *E) { - // GCC union extension - if (E->getSubExpr()->getType()->isScalarType()) { +void AggExprEmitter::VisitCastExpr(CastExpr *E) { + switch (E->getCastKind()) { + default: assert(0 && "Unhandled cast kind!"); + + case CastExpr::CK_ToUnion: { + // GCC union extension QualType PtrTy = - CGF.getContext().getPointerType(E->getSubExpr()->getType()); + CGF.getContext().getPointerType(E->getSubExpr()->getType()); llvm::Value *CastPtr = Builder.CreateBitCast(DestPtr, CGF.ConvertType(PtrTy)); - EmitInitializationToLValue(E->getSubExpr(), LValue::MakeAddr(CastPtr, 0)); - return; + EmitInitializationToLValue(E->getSubExpr(), + LValue::MakeAddr(CastPtr, Qualifiers())); + break; } - Visit(E->getSubExpr()); -} + // FIXME: Remove the CK_Unknown check here. + case CastExpr::CK_Unknown: + case CastExpr::CK_NoOp: + case CastExpr::CK_UserDefinedConversion: + case CastExpr::CK_ConstructorConversion: + assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(), + E->getType()) && + "Implicit cast types must be compatible"); + Visit(E->getSubExpr()); + break; + + case CastExpr::CK_NullToMemberPointer: { + const llvm::Type *PtrDiffTy = + CGF.ConvertType(CGF.getContext().getPointerDiffType()); -void AggExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *E) { - assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(), - E->getType()) && - "Implicit cast types must be compatible"); - Visit(E->getSubExpr()); + llvm::Value *NullValue = llvm::Constant::getNullValue(PtrDiffTy); + llvm::Value *Ptr = Builder.CreateStructGEP(DestPtr, 0, "ptr"); + Builder.CreateStore(NullValue, Ptr, VolatileDest); + + llvm::Value *Adj = Builder.CreateStructGEP(DestPtr, 1, "adj"); + Builder.CreateStore(NullValue, Adj, VolatileDest); + + break; + } + + case CastExpr::CK_BaseToDerivedMemberPointer: { + QualType SrcType = E->getSubExpr()->getType(); + + llvm::Value *Src = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(SrcType), + "tmp"); + CGF.EmitAggExpr(E->getSubExpr(), Src, SrcType.isVolatileQualified()); + + llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr"); + SrcPtr = Builder.CreateLoad(SrcPtr); + + llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj"); + SrcAdj = Builder.CreateLoad(SrcAdj); + + llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr"); + Builder.CreateStore(SrcPtr, DstPtr, VolatileDest); + + llvm::Value *DstAdj = Builder.CreateStructGEP(DestPtr, 1, "dst.adj"); + + // Now See if we need to update the adjustment. + const CXXRecordDecl *SrcDecl = + cast<CXXRecordDecl>(SrcType->getAs<MemberPointerType>()-> + getClass()->getAs<RecordType>()->getDecl()); + const CXXRecordDecl *DstDecl = + cast<CXXRecordDecl>(E->getType()->getAs<MemberPointerType>()-> + getClass()->getAs<RecordType>()->getDecl()); + + llvm::Constant *Adj = CGF.CGM.GetCXXBaseClassOffset(DstDecl, SrcDecl); + if (Adj) + SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj"); + + Builder.CreateStore(SrcAdj, DstAdj, VolatileDest); + break; + } + } } void AggExprEmitter::VisitCallExpr(const CallExpr *E) { @@ -190,7 +255,7 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) { EmitAggLoadOfLValue(E); return; } - + RValue RV = CGF.EmitCallExpr(E); EmitFinalDestCopy(E, RV); } @@ -205,14 +270,49 @@ void AggExprEmitter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { EmitFinalDestCopy(E, RV); } -void AggExprEmitter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { +void AggExprEmitter::VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *E) { RValue RV = CGF.EmitObjCPropertyGet(E); EmitFinalDestCopy(E, RV); } void AggExprEmitter::VisitBinComma(const BinaryOperator *E) { CGF.EmitAnyExpr(E->getLHS(), 0, false, true); - CGF.EmitAggExpr(E->getRHS(), DestPtr, VolatileDest); + CGF.EmitAggExpr(E->getRHS(), DestPtr, VolatileDest, + /*IgnoreResult=*/false, IsInitializer); +} + +void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) { + // We have a member function pointer. + const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>(); + assert(MPT->getPointeeType()->isFunctionProtoType() && + "Unexpected member pointer type!"); + + const QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr()); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl()); + + const llvm::Type *PtrDiffTy = + CGF.ConvertType(CGF.getContext().getPointerDiffType()); + + llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr"); + llvm::Value *FuncPtr; + + if (MD->isVirtual()) { + int64_t Index = + CGF.CGM.getVtableInfo().getMethodVtableIndex(MD); + + FuncPtr = llvm::ConstantInt::get(PtrDiffTy, Index + 1); + } else { + FuncPtr = llvm::ConstantExpr::getPtrToInt(CGF.CGM.GetAddrOfFunction(MD), + PtrDiffTy); + } + Builder.CreateStore(FuncPtr, DstPtr, VolatileDest); + + llvm::Value *AdjPtr = Builder.CreateStructGEP(DestPtr, 1, "dst.adj"); + + // The adjustment will always be 0. + Builder.CreateStore(llvm::ConstantInt::get(PtrDiffTy, 0), AdjPtr, + VolatileDest); } void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { @@ -238,19 +338,25 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { if (!AggLoc) AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType())); CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); - CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), + CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), RValue::getAggregate(AggLoc, VolatileDest)); - } - else if (LHS.isKVCRef()) { + } else if (LHS.isKVCRef()) { llvm::Value *AggLoc = DestPtr; if (!AggLoc) AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType())); CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); - CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), + CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), RValue::getAggregate(AggLoc, VolatileDest)); } else { + bool RequiresGCollection = false; + if (CGF.getContext().getLangOptions().NeXTRuntime) { + QualType LHSTy = E->getLHS()->getType(); + if (const RecordType *FDTTy = LHSTy.getTypePtr()->getAs<RecordType>()) + RequiresGCollection = FDTTy->getDecl()->hasObjectMember(); + } // Codegen the RHS so that it stores directly into the LHS. - CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified()); + CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified(), + false, false, RequiresGCollection); EmitFinalDestCopy(E, LHS, true); } } @@ -259,30 +365,34 @@ void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) { llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); - + llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond()); Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); - + CGF.PushConditionalTempDestruction(); CGF.EmitBlock(LHSBlock); - + // Handle the GNU extension for missing LHS. assert(E->getLHS() && "Must have LHS for aggregate value"); Visit(E->getLHS()); CGF.PopConditionalTempDestruction(); CGF.EmitBranch(ContBlock); - + CGF.PushConditionalTempDestruction(); CGF.EmitBlock(RHSBlock); - + Visit(E->getRHS()); CGF.PopConditionalTempDestruction(); CGF.EmitBranch(ContBlock); - + CGF.EmitBlock(ContBlock); } +void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) { + Visit(CE->getChosenSubExpr(CGF.getContext())); +} + void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr()); llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); @@ -292,28 +402,30 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { return; } - EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, 0)); + EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, Qualifiers())); } void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { llvm::Value *Val = DestPtr; - + if (!Val) { // Create a temporary variable. Val = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(E->getType()), "tmp"); // FIXME: volatile CGF.EmitAggExpr(E->getSubExpr(), Val, false); - } else + } else Visit(E->getSubExpr()); - - CGF.PushCXXTemporary(E->getTemporary(), Val); + + // Don't make this a live temporary if we're emitting an initializer expr. + if (!IsInitializer) + CGF.PushCXXTemporary(E->getTemporary(), Val); } void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { llvm::Value *Val = DestPtr; - + if (!Val) { // Create a temporary variable. Val = CGF.CreateTempAlloca(CGF.ConvertTypeForMem(E->getType()), "tmp"); @@ -323,7 +435,7 @@ AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { } void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest); + CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest, IsInitializer); } void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { @@ -359,7 +471,7 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue LV, QualType T) { void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { #if 0 - // FIXME: Disabled while we figure out what to do about + // FIXME: Disabled while we figure out what to do about // test/CodeGen/bitfield.c // // If we can, prefer a copy from a global; this is a lot less code for long @@ -387,7 +499,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { cast<llvm::PointerType>(DestPtr->getType()); const llvm::ArrayType *AType = cast<llvm::ArrayType>(APType->getElementType()); - + uint64_t NumInitElements = E->getNumInits(); if (E->getNumInits() > 0) { @@ -402,29 +514,30 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { uint64_t NumArrayElements = AType->getNumElements(); QualType ElementType = CGF.getContext().getCanonicalType(E->getType()); ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType(); - - unsigned CVRqualifier = ElementType.getCVRQualifiers(); + + // FIXME: were we intentionally ignoring address spaces and GC attributes? + Qualifiers Quals = CGF.MakeQualifiers(ElementType); for (uint64_t i = 0; i != NumArrayElements; ++i) { llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array"); if (i < NumInitElements) EmitInitializationToLValue(E->getInit(i), - LValue::MakeAddr(NextVal, CVRqualifier)); + LValue::MakeAddr(NextVal, Quals)); else - EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, CVRqualifier), + EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, Quals), ElementType); } return; } - + assert(E->getType()->isRecordType() && "Only support structs/unions here!"); - + // Do struct initialization; this code just sets each individual member // to the approprate value. This makes bitfield support automatic; // the disadvantage is that the generated code is more difficult for // the optimizer, especially with bitfields. unsigned NumInitElements = E->getNumInits(); - RecordDecl *SD = E->getType()->getAsRecordType()->getDecl(); + RecordDecl *SD = E->getType()->getAs<RecordType>()->getDecl(); unsigned CurInitVal = 0; if (E->getType()->isUnionType()) { @@ -432,7 +545,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // specified by the initializer list. if (!E->getInitializedFieldInUnion()) { // Empty union; we have nothing to do. - + #ifndef NDEBUG // Make sure that it's really an empty and not a failure of // semantic analysis. @@ -458,7 +571,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { return; } - + // Here we iterate over the fields; this makes it simpler to both // default-initialize fields and skip over unnamed fields. for (RecordDecl::field_iterator Field = SD->field_begin(), @@ -494,13 +607,16 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { /// the value of the aggregate expression is not needed. If VolatileDest is /// true, DestPtr cannot be 0. void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, - bool VolatileDest, bool IgnoreResult) { + bool VolatileDest, bool IgnoreResult, + bool IsInitializer, + bool RequiresGCollection) { assert(E && hasAggregateLLVMType(E->getType()) && "Invalid aggregate expression to emit"); assert ((DestPtr != 0 || VolatileDest == false) && "volatile aggregate can't be 0"); - - AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult) + + AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult, IsInitializer, + RequiresGCollection) .Visit(const_cast<Expr*>(E)); } @@ -514,7 +630,7 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr, QualType Ty, bool isVolatile) { assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); - + // Aggregate assignment turns into llvm.memcpy. This is almost valid per // C99 6.5.16.1p3, which states "If the value being stored in an object is // read from another object that overlaps in anyway the storage of the first @@ -525,18 +641,19 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, // equal, but other compilers do this optimization, and almost every memcpy // implementation handles this case safely. If there is a libc that does not // safely handle this, we can add a target hook. - const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); if (DestPtr->getType() != BP) DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); if (SrcPtr->getType() != BP) SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); - + // Get size and alignment info for this aggregate. std::pair<uint64_t, unsigned> TypeInfo = getContext().getTypeInfo(Ty); - + // FIXME: Handle variable sized types. - const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); - + const llvm::Type *IntPtr = + llvm::IntegerType::get(VMContext, LLVMPointerWidth); + // FIXME: If we have a volatile struct, the optimizer can remove what might // appear to be `extra' memory ops: // @@ -553,6 +670,6 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, DestPtr, SrcPtr, // TypeInfo.first describes size in bits. llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), - llvm::ConstantInt::get(llvm::Type::Int32Ty, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), TypeInfo.second/8)); } diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 3555c8c9b6917..9e81e4fbeabee 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -46,7 +46,7 @@ public: IgnoreRealAssign(irn), IgnoreImagAssign(iin) { } - + //===--------------------------------------------------------------------===// // Utilities //===--------------------------------------------------------------------===// @@ -82,23 +82,23 @@ public: if (LV.isPropertyRef()) return CGF.EmitObjCPropertyGet(LV.getPropertyRefExpr()).getComplexVal(); - + assert(LV.isKVCRef() && "Unknown LValue type!"); return CGF.EmitObjCPropertyGet(LV.getKVCRefExpr()).getComplexVal(); } - + /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load /// the real and imaginary pieces. ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile); - + /// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer. void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr, bool isVol); - + /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType. ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType, QualType DestType); - + //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// @@ -111,16 +111,17 @@ public: ComplexPairTy VisitExpr(Expr *S); ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());} ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL); - + // l-values. ComplexPairTy VisitDeclRefExpr(const Expr *E) { return EmitLoadOfLValue(E); } - ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { return EmitLoadOfLValue(E); } ComplexPairTy VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { return EmitLoadOfLValue(E); } - ComplexPairTy VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { + ComplexPairTy VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *E) { return EmitLoadOfLValue(E); } ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) { @@ -130,7 +131,7 @@ public: ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); } // FIXME: CompoundLiteralExpr - + ComplexPairTy EmitCast(Expr *Op, QualType DestTy); ComplexPairTy VisitImplicitCastExpr(ImplicitCastExpr *E) { // Unlike for scalars, we don't have to worry about function->ptr demotion @@ -180,23 +181,24 @@ public: } ComplexPairTy VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { assert(E->getType()->isAnyComplexType() && "Expected complex type!"); - QualType Elem = E->getType()->getAsComplexType()->getElementType(); + QualType Elem = E->getType()->getAs<ComplexType>()->getElementType(); llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem)); return ComplexPairTy(Null, Null); } ComplexPairTy VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { assert(E->getType()->isAnyComplexType() && "Expected complex type!"); - QualType Elem = E->getType()->getAsComplexType()->getElementType(); - llvm::Constant *Null = llvm::Constant::getNullValue(CGF.ConvertType(Elem)); + QualType Elem = E->getType()->getAs<ComplexType>()->getElementType(); + llvm::Constant *Null = + llvm::Constant::getNullValue(CGF.ConvertType(Elem)); return ComplexPairTy(Null, Null); } - + struct BinOpInfo { ComplexPairTy LHS; ComplexPairTy RHS; QualType Ty; // Computation Type. - }; - + }; + BinOpInfo EmitBinOps(const BinaryOperator *E); ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E, ComplexPairTy (ComplexExprEmitter::*Func) @@ -206,7 +208,7 @@ public: ComplexPairTy EmitBinSub(const BinOpInfo &Op); ComplexPairTy EmitBinMul(const BinOpInfo &Op); ComplexPairTy EmitBinDiv(const BinOpInfo &Op); - + ComplexPairTy VisitBinMul(const BinaryOperator *E) { return EmitBinMul(EmitBinOps(E)); } @@ -219,7 +221,7 @@ public: ComplexPairTy VisitBinDiv(const BinaryOperator *E) { return EmitBinDiv(EmitBinOps(E)); } - + // Compound assignments. ComplexPairTy VisitBinAddAssign(const CompoundAssignOperator *E) { return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinAdd); @@ -233,7 +235,7 @@ public: ComplexPairTy VisitBinDivAssign(const CompoundAssignOperator *E) { return EmitCompoundAssign(E, &ComplexExprEmitter::EmitBinDiv); } - + // GCC rejects rem/and/or/xor for integer complex. // Logical and/or always return int, never complex. @@ -241,7 +243,7 @@ public: ComplexPairTy VisitBinAssign (const BinaryOperator *E); ComplexPairTy VisitBinComma (const BinaryOperator *E); - + ComplexPairTy VisitConditionalOperator(const ConditionalOperator *CO); ComplexPairTy VisitChooseExpr(ChooseExpr *CE); @@ -259,27 +261,34 @@ public: /// load the real and imaginary pieces, returning them as Real/Imag. ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile) { - llvm::SmallString<64> Name(SrcPtr->getNameStart(), - SrcPtr->getNameStart()+SrcPtr->getNameLen()); - + llvm::SmallString<64> Name(SrcPtr->getName().begin(), + SrcPtr->getName().end()); + llvm::Value *Real=0, *Imag=0; if (!IgnoreReal) { + // FIXME: Clean this up once builder takes Twine/StringRef. Name += ".realp"; - llvm::Value *RealPtr = Builder.CreateStructGEP(SrcPtr, 0, Name.c_str()); + llvm::Value *RealPtr = Builder.CreateStructGEP(SrcPtr, 0, + Name.str().str().c_str()); Name.pop_back(); // .realp -> .real - Real = Builder.CreateLoad(RealPtr, isVolatile, Name.c_str()); + // FIXME: Clean this up once builder takes Twine/StringRef. + Real = Builder.CreateLoad(RealPtr, isVolatile, + Name.str().str().c_str()); Name.resize(Name.size()-4); // .real -> .imagp } - + if (!IgnoreImag) { Name += "imagp"; - - llvm::Value *ImagPtr = Builder.CreateStructGEP(SrcPtr, 1, Name.c_str()); + + // FIXME: Clean this up once builder takes Twine/StringRef. + llvm::Value *ImagPtr = Builder.CreateStructGEP(SrcPtr, 1, + Name.str().str().c_str()); Name.pop_back(); // .imagp -> .imag - Imag = Builder.CreateLoad(ImagPtr, isVolatile, Name.c_str()); + // FIXME: Clean this up once builder takes Twine/StringRef. + Imag = Builder.CreateLoad(ImagPtr, isVolatile, Name.str().str().c_str()); } return ComplexPairTy(Real, Imag); } @@ -290,7 +299,7 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *Ptr, bool isVolatile) { llvm::Value *RealPtr = Builder.CreateStructGEP(Ptr, 0, "real"); llvm::Value *ImagPtr = Builder.CreateStructGEP(Ptr, 1, "imag"); - + Builder.CreateStore(Val.first, RealPtr, isVolatile); Builder.CreateStore(Val.second, ImagPtr, isVolatile); } @@ -303,8 +312,8 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *Ptr, ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { CGF.ErrorUnsupported(E, "complex expression"); - const llvm::Type *EltTy = - CGF.ConvertType(E->getType()->getAsComplexType()->getElementType()); + const llvm::Type *EltTy = + CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType()); llvm::Value *U = llvm::UndefValue::get(EltTy); return ComplexPairTy(U, U); } @@ -312,7 +321,8 @@ ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { ComplexPairTy ComplexExprEmitter:: VisitImaginaryLiteral(const ImaginaryLiteral *IL) { llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr()); - return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag); + return + ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag); } @@ -332,8 +342,8 @@ ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType, QualType DestType) { // Get the src/dest element type. - SrcType = SrcType->getAsComplexType()->getElementType(); - DestType = DestType->getAsComplexType()->getElementType(); + SrcType = SrcType->getAs<ComplexType>()->getElementType(); + DestType = DestType->getAs<ComplexType>()->getElementType(); // C99 6.3.1.6: When a value of complex type is converted to another // complex type, both the real and imaginary parts follow the conversion @@ -347,7 +357,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) { // Two cases here: cast from (complex to complex) and (scalar to complex). if (Op->getType()->isAnyComplexType()) return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy); - + // C99 6.3.1.7: When a value of real type is converted to a complex type, the // real part of the complex result value is determined by the rules of // conversion to the corresponding real type and the imaginary part of the @@ -355,9 +365,9 @@ ComplexPairTy ComplexExprEmitter::EmitCast(Expr *Op, QualType DestTy) { llvm::Value *Elt = CGF.EmitScalarExpr(Op); // Convert the input element to the element type of the complex. - DestTy = DestTy->getAsComplexType()->getElementType(); + DestTy = DestTy->getAs<ComplexType>()->getElementType(); Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy); - + // Return (realval, 0). return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType())); } @@ -367,31 +377,30 @@ ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, LValue LV = CGF.EmitLValue(E->getSubExpr()); ComplexPairTy InVal = EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); - + llvm::Value *NextVal; if (isa<llvm::IntegerType>(InVal.first->getType())) { uint64_t AmountVal = isInc ? 1 : -1; NextVal = llvm::ConstantInt::get(InVal.first->getType(), AmountVal, true); - + // Add the inc/dec to the real part. NextVal = Builder.CreateAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); - } else { - QualType ElemTy = E->getType()->getAsComplexType()->getElementType(); + QualType ElemTy = E->getType()->getAs<ComplexType>()->getElementType(); llvm::APFloat FVal(CGF.getContext().getFloatTypeSemantics(ElemTy), 1); if (!isInc) FVal.changeSign(); - NextVal = llvm::ConstantFP::get(FVal); - + NextVal = llvm::ConstantFP::get(CGF.getLLVMContext(), FVal); + // Add the inc/dec to the real part. NextVal = Builder.CreateFAdd(InVal.first, NextVal, isInc ? "inc" : "dec"); } - + ComplexPairTy IncVal(NextVal, InVal.second); - + // Store the updated result through the lvalue. EmitStoreOfComplex(IncVal, LV.getAddress(), LV.isVolatileQualified()); - + // If this is a postinc, return the value read from memory, otherwise use the // updated value. return isPre ? IncVal : InVal; @@ -403,7 +412,7 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { TestAndClearIgnoreRealAssign(); TestAndClearIgnoreImagAssign(); ComplexPairTy Op = Visit(E->getSubExpr()); - + llvm::Value *ResR, *ResI; if (Op.first->getType()->isFloatingPoint()) { ResR = Builder.CreateFNeg(Op.first, "neg.r"); @@ -427,13 +436,13 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) { ResI = Builder.CreateFNeg(Op.second, "conj.i"); else ResI = Builder.CreateNeg(Op.second, "conj.i"); - + return ComplexPairTy(Op.first, ResI); } ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) { llvm::Value *ResR, *ResI; - + if (Op.LHS.first->getType()->isFloatingPoint()) { ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r"); ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i"); @@ -460,12 +469,12 @@ ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) { ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { using llvm::Value; Value *ResR, *ResI; - + if (Op.LHS.first->getType()->isFloatingPoint()) { Value *ResRl = Builder.CreateFMul(Op.LHS.first, Op.RHS.first, "mul.rl"); Value *ResRr = Builder.CreateFMul(Op.LHS.second, Op.RHS.second,"mul.rr"); ResR = Builder.CreateFSub(ResRl, ResRr, "mul.r"); - + Value *ResIl = Builder.CreateFMul(Op.LHS.second, Op.RHS.first, "mul.il"); Value *ResIr = Builder.CreateFMul(Op.LHS.first, Op.RHS.second, "mul.ir"); ResI = Builder.CreateFAdd(ResIl, ResIr, "mul.i"); @@ -473,7 +482,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { Value *ResRl = Builder.CreateMul(Op.LHS.first, Op.RHS.first, "mul.rl"); Value *ResRr = Builder.CreateMul(Op.LHS.second, Op.RHS.second,"mul.rr"); ResR = Builder.CreateSub(ResRl, ResRr, "mul.r"); - + Value *ResIl = Builder.CreateMul(Op.LHS.second, Op.RHS.first, "mul.il"); Value *ResIr = Builder.CreateMul(Op.LHS.first, Op.RHS.second, "mul.ir"); ResI = Builder.CreateAdd(ResIl, ResIr, "mul.i"); @@ -484,7 +493,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second; llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second; - + llvm::Value *DSTr, *DSTi; if (Op.LHS.first->getType()->isFloatingPoint()) { @@ -492,15 +501,15 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { llvm::Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr, "tmp"); // a*c llvm::Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi, "tmp"); // b*d llvm::Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2, "tmp"); // ac+bd - + llvm::Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr, "tmp"); // c*c llvm::Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi, "tmp"); // d*d llvm::Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5, "tmp"); // cc+dd - + llvm::Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr, "tmp"); // b*c llvm::Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi, "tmp"); // a*d llvm::Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8, "tmp"); // bc-ad - + DSTr = Builder.CreateFDiv(Tmp3, Tmp6, "tmp"); DSTi = Builder.CreateFDiv(Tmp9, Tmp6, "tmp"); } else { @@ -508,16 +517,16 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { llvm::Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c llvm::Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d llvm::Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd - + llvm::Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c llvm::Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d llvm::Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd - + llvm::Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c llvm::Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d llvm::Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad - - if (Op.Ty->getAsComplexType()->getElementType()->isUnsignedIntegerType()) { + + if (Op.Ty->getAs<ComplexType>()->getElementType()->isUnsignedIntegerType()) { DSTr = Builder.CreateUDiv(Tmp3, Tmp6, "tmp"); DSTi = Builder.CreateUDiv(Tmp9, Tmp6, "tmp"); } else { @@ -525,11 +534,11 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { DSTi = Builder.CreateSDiv(Tmp9, Tmp6, "tmp"); } } - + return ComplexPairTy(DSTr, DSTi); } -ComplexExprEmitter::BinOpInfo +ComplexExprEmitter::BinOpInfo ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); @@ -554,27 +563,27 @@ EmitCompoundAssign(const CompoundAssignOperator *E, QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType(); BinOpInfo OpInfo; - + // Load the RHS and LHS operands. // __block variables need to have the rhs evaluated first, plus this should // improve codegen a little. It is possible for the RHS to be complex or // scalar. OpInfo.Ty = E->getComputationResultType(); OpInfo.RHS = EmitCast(E->getRHS(), OpInfo.Ty); - + LValue LHSLV = CGF.EmitLValue(E->getLHS()); // We know the LHS is a complex lvalue. - OpInfo.LHS=EmitLoadOfComplex(LHSLV.getAddress(),LHSLV.isVolatileQualified()); + OpInfo.LHS=EmitLoadOfComplex(LHSLV.getAddress(), LHSLV.isVolatileQualified()); OpInfo.LHS=EmitComplexToComplexCast(OpInfo.LHS, LHSTy, OpInfo.Ty); - + // Expand the binary operator. ComplexPairTy Result = (this->*Func)(OpInfo); - + // Truncate the result back to the LHS type. Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy); - + // Store the result value into the LHS lvalue. EmitStoreOfComplex(Result, LHSLV.getAddress(), LHSLV.isVolatileQualified()); // And now return the LHS @@ -598,7 +607,7 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { // Compute the address to store into. LValue LHS = CGF.EmitLValue(E->getLHS()); - + // Store into it, if simple. if (LHS.isSimple()) { EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified()); @@ -610,7 +619,7 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { IgnoreImagAssign = ignimag; return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified()); } - + // Otherwise we must have a property setter (no complex vector/bitfields). if (LHS.isPropertyRef()) CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), RValue::getComplex(Val)); @@ -641,27 +650,27 @@ VisitConditionalOperator(const ConditionalOperator *E) { llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); - + llvm::Value *Cond = CGF.EvaluateExprAsBool(E->getCond()); Builder.CreateCondBr(Cond, LHSBlock, RHSBlock); - + CGF.EmitBlock(LHSBlock); - + // Handle the GNU extension for missing LHS. assert(E->getLHS() && "Must have LHS for complex value"); ComplexPairTy LHS = Visit(E->getLHS()); LHSBlock = Builder.GetInsertBlock(); CGF.EmitBranch(ContBlock); - + CGF.EmitBlock(RHSBlock); - + ComplexPairTy RHS = Visit(E->getRHS()); RHSBlock = Builder.GetInsertBlock(); CGF.EmitBranch(ContBlock); - + CGF.EmitBlock(ContBlock); - + // Create a PHI node for the real part. llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), "cond.r"); RealPN->reserveOperandSpace(2); @@ -673,7 +682,7 @@ VisitConditionalOperator(const ConditionalOperator *E) { ImagPN->reserveOperandSpace(2); ImagPN->addIncoming(LHS.second, LHSBlock); ImagPN->addIncoming(RHS.second, RHSBlock); - + return ComplexPairTy(RealPN, ImagPN); } @@ -692,7 +701,7 @@ ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) { return Visit(E->getInit(0)); // Empty init list intializes to null - QualType Ty = E->getType()->getAsComplexType()->getElementType(); + QualType Ty = E->getType()->getAs<ComplexType>()->getElementType(); const llvm::Type* LTy = CGF.ConvertType(Ty); llvm::Value* zeroConstant = llvm::Constant::getNullValue(LTy); return ComplexPairTy(zeroConstant, zeroConstant); @@ -704,8 +713,8 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) { if (!ArgPtr) { CGF.ErrorUnsupported(E, "complex va_arg expression"); - const llvm::Type *EltTy = - CGF.ConvertType(E->getType()->getAsComplexType()->getElementType()); + const llvm::Type *EltTy = + CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType()); llvm::Value *U = llvm::UndefValue::get(EltTy); return ComplexPairTy(U, U); } @@ -724,7 +733,7 @@ ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal, bool IgnoreImag, bool IgnoreRealAssign, bool IgnoreImagAssign) { assert(E && E->getType()->isAnyComplexType() && "Invalid complex expression to emit"); - + return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag, IgnoreRealAssign, IgnoreImagAssign) .Visit(const_cast<Expr*>(E)); @@ -750,7 +759,7 @@ void CodeGenFunction::StoreComplexToAddr(ComplexPairTy V, } /// LoadComplexFromAddr - Load a complex number from the specified address. -ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr, +ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile) { return ComplexExprEmitter(*this).EmitLoadOfComplex(SrcAddr, SrcIsVolatile); } diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 37c9c366fee64..7f540c3c06885 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -16,6 +16,7 @@ #include "CGObjCRuntime.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "llvm/Constants.h" @@ -27,45 +28,541 @@ using namespace clang; using namespace CodeGen; namespace { -class VISIBILITY_HIDDEN ConstExprEmitter : + +class VISIBILITY_HIDDEN ConstStructBuilder { + CodeGenModule &CGM; + CodeGenFunction *CGF; + + bool Packed; + + unsigned NextFieldOffsetInBytes; + + unsigned LLVMStructAlignment; + + std::vector<llvm::Constant *> Elements; + + ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF) + : CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0), + LLVMStructAlignment(1) { } + + bool AppendField(const FieldDecl *Field, uint64_t FieldOffset, + const Expr *InitExpr) { + uint64_t FieldOffsetInBytes = FieldOffset / 8; + + assert(NextFieldOffsetInBytes <= FieldOffsetInBytes + && "Field offset mismatch!"); + + // Emit the field. + llvm::Constant *C = CGM.EmitConstantExpr(InitExpr, Field->getType(), CGF); + if (!C) + return false; + + unsigned FieldAlignment = getAlignment(C); + + // Round up the field offset to the alignment of the field type. + uint64_t AlignedNextFieldOffsetInBytes = + llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment); + + if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) { + assert(!Packed && "Alignment is wrong even with a packed struct!"); + + // Convert the struct to a packed struct. + ConvertStructToPacked(); + + AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes; + } + + if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) { + // We need to append padding. + AppendPadding(FieldOffsetInBytes - NextFieldOffsetInBytes); + + assert(NextFieldOffsetInBytes == FieldOffsetInBytes && + "Did not add enough padding!"); + + AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes; + } + + // Add the field. + Elements.push_back(C); + NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C); + + if (Packed) + assert(LLVMStructAlignment == 1 && "Packed struct not byte-aligned!"); + else + LLVMStructAlignment = std::max(LLVMStructAlignment, FieldAlignment); + + return true; + } + + bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset, + const Expr *InitExpr) { + llvm::ConstantInt *CI = + cast_or_null<llvm::ConstantInt>(CGM.EmitConstantExpr(InitExpr, + Field->getType(), + CGF)); + // FIXME: Can this ever happen? + if (!CI) + return false; + + if (FieldOffset > NextFieldOffsetInBytes * 8) { + // We need to add padding. + uint64_t NumBytes = + llvm::RoundUpToAlignment(FieldOffset - + NextFieldOffsetInBytes * 8, 8) / 8; + + AppendPadding(NumBytes); + } + + uint64_t FieldSize = + Field->getBitWidth()->EvaluateAsInt(CGM.getContext()).getZExtValue(); + + llvm::APInt FieldValue = CI->getValue(); + + // Promote the size of FieldValue if necessary + // FIXME: This should never occur, but currently it can because initializer + // constants are cast to bool, and because clang is not enforcing bitfield + // width limits. + if (FieldSize > FieldValue.getBitWidth()) + FieldValue.zext(FieldSize); + + // Truncate the size of FieldValue to the bit field size. + if (FieldSize < FieldValue.getBitWidth()) + FieldValue.trunc(FieldSize); + + if (FieldOffset < NextFieldOffsetInBytes * 8) { + // Either part of the field or the entire field can go into the previous + // byte. + assert(!Elements.empty() && "Elements can't be empty!"); + + unsigned BitsInPreviousByte = + NextFieldOffsetInBytes * 8 - FieldOffset; + + bool FitsCompletelyInPreviousByte = + BitsInPreviousByte >= FieldValue.getBitWidth(); + + llvm::APInt Tmp = FieldValue; + + if (!FitsCompletelyInPreviousByte) { + unsigned NewFieldWidth = FieldSize - BitsInPreviousByte; + + if (CGM.getTargetData().isBigEndian()) { + Tmp = Tmp.lshr(NewFieldWidth); + Tmp.trunc(BitsInPreviousByte); + + // We want the remaining high bits. + FieldValue.trunc(NewFieldWidth); + } else { + Tmp.trunc(BitsInPreviousByte); + + // We want the remaining low bits. + FieldValue = FieldValue.lshr(BitsInPreviousByte); + FieldValue.trunc(NewFieldWidth); + } + } + + Tmp.zext(8); + if (CGM.getTargetData().isBigEndian()) { + if (FitsCompletelyInPreviousByte) + Tmp = Tmp.shl(BitsInPreviousByte - FieldValue.getBitWidth()); + } else { + Tmp = Tmp.shl(8 - BitsInPreviousByte); + } + + // Or in the bits that go into the previous byte. + Tmp |= cast<llvm::ConstantInt>(Elements.back())->getValue(); + Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp); + + if (FitsCompletelyInPreviousByte) + return true; + } + + while (FieldValue.getBitWidth() > 8) { + llvm::APInt Tmp; + + if (CGM.getTargetData().isBigEndian()) { + // We want the high bits. + Tmp = FieldValue; + Tmp = Tmp.lshr(Tmp.getBitWidth() - 8); + Tmp.trunc(8); + } else { + // We want the low bits. + Tmp = FieldValue; + Tmp.trunc(8); + + FieldValue = FieldValue.lshr(8); + } + + Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp)); + NextFieldOffsetInBytes++; + + FieldValue.trunc(FieldValue.getBitWidth() - 8); + } + + assert(FieldValue.getBitWidth() > 0 && + "Should have at least one bit left!"); + assert(FieldValue.getBitWidth() <= 8 && + "Should not have more than a byte left!"); + + if (FieldValue.getBitWidth() < 8) { + if (CGM.getTargetData().isBigEndian()) { + unsigned BitWidth = FieldValue.getBitWidth(); + + FieldValue.zext(8); + FieldValue = FieldValue << (8 - BitWidth); + } else + FieldValue.zext(8); + } + + // Append the last element. + Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), + FieldValue)); + NextFieldOffsetInBytes++; + return true; + } + + void AppendPadding(uint64_t NumBytes) { + if (!NumBytes) + return; + + const llvm::Type *Ty = llvm::Type::getInt8Ty(CGM.getLLVMContext()); + if (NumBytes > 1) + Ty = llvm::ArrayType::get(Ty, NumBytes); + + llvm::Constant *C = llvm::Constant::getNullValue(Ty); + Elements.push_back(C); + assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!"); + + NextFieldOffsetInBytes += getSizeInBytes(C); + } + + void AppendTailPadding(uint64_t RecordSize) { + assert(RecordSize % 8 == 0 && "Invalid record size!"); + + uint64_t RecordSizeInBytes = RecordSize / 8; + assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!"); + + unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes; + AppendPadding(NumPadBytes); + } + + void ConvertStructToPacked() { + std::vector<llvm::Constant *> PackedElements; + uint64_t ElementOffsetInBytes = 0; + + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { + llvm::Constant *C = Elements[i]; + + unsigned ElementAlign = + CGM.getTargetData().getABITypeAlignment(C->getType()); + uint64_t AlignedElementOffsetInBytes = + llvm::RoundUpToAlignment(ElementOffsetInBytes, ElementAlign); + + if (AlignedElementOffsetInBytes > ElementOffsetInBytes) { + // We need some padding. + uint64_t NumBytes = + AlignedElementOffsetInBytes - ElementOffsetInBytes; + + const llvm::Type *Ty = llvm::Type::getInt8Ty(CGF->getLLVMContext()); + if (NumBytes > 1) + Ty = llvm::ArrayType::get(Ty, NumBytes); + + llvm::Constant *Padding = llvm::Constant::getNullValue(Ty); + PackedElements.push_back(Padding); + ElementOffsetInBytes += getSizeInBytes(Padding); + } + + PackedElements.push_back(C); + ElementOffsetInBytes += getSizeInBytes(C); + } + + assert(ElementOffsetInBytes == NextFieldOffsetInBytes && + "Packing the struct changed its size!"); + + Elements = PackedElements; + LLVMStructAlignment = 1; + Packed = true; + } + + bool Build(InitListExpr *ILE) { + RecordDecl *RD = ILE->getType()->getAs<RecordType>()->getDecl(); + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + + unsigned FieldNo = 0; + unsigned ElementNo = 0; + for (RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); + ElementNo < ILE->getNumInits() && Field != FieldEnd; + ++Field, ++FieldNo) { + if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field) + continue; + + if (Field->isBitField()) { + if (!Field->getIdentifier()) + continue; + + if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo), + ILE->getInit(ElementNo))) + return false; + } else { + if (!AppendField(*Field, Layout.getFieldOffset(FieldNo), + ILE->getInit(ElementNo))) + return false; + } + + ElementNo++; + } + + uint64_t LayoutSizeInBytes = Layout.getSize() / 8; + + if (NextFieldOffsetInBytes > LayoutSizeInBytes) { + // If the struct is bigger than the size of the record type, + // we must have a flexible array member at the end. + assert(RD->hasFlexibleArrayMember() && + "Must have flexible array member if struct is bigger than type!"); + + // No tail padding is necessary. + return true; + } + + uint64_t LLVMSizeInBytes = llvm::RoundUpToAlignment(NextFieldOffsetInBytes, + LLVMStructAlignment); + + // Check if we need to convert the struct to a packed struct. + if (NextFieldOffsetInBytes <= LayoutSizeInBytes && + LLVMSizeInBytes > LayoutSizeInBytes) { + assert(!Packed && "Size mismatch!"); + + ConvertStructToPacked(); + assert(NextFieldOffsetInBytes == LayoutSizeInBytes && + "Converting to packed did not help!"); + } + + // Append tail padding if necessary. + AppendTailPadding(Layout.getSize()); + + assert(Layout.getSize() / 8 == NextFieldOffsetInBytes && + "Tail padding mismatch!"); + + return true; + } + + unsigned getAlignment(const llvm::Constant *C) const { + if (Packed) + return 1; + + return CGM.getTargetData().getABITypeAlignment(C->getType()); + } + + uint64_t getSizeInBytes(const llvm::Constant *C) const { + return CGM.getTargetData().getTypeAllocSize(C->getType()); + } + +public: + static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF, + InitListExpr *ILE) { + ConstStructBuilder Builder(CGM, CGF); + + if (!Builder.Build(ILE)) + return 0; + + llvm::Constant *Result = + llvm::ConstantStruct::get(CGM.getLLVMContext(), + Builder.Elements, Builder.Packed); + + assert(llvm::RoundUpToAlignment(Builder.NextFieldOffsetInBytes, + Builder.getAlignment(Result)) == + Builder.getSizeInBytes(Result) && "Size mismatch!"); + + return Result; + } +}; + +class VISIBILITY_HIDDEN ConstExprEmitter : public StmtVisitor<ConstExprEmitter, llvm::Constant*> { CodeGenModule &CGM; CodeGenFunction *CGF; + llvm::LLVMContext &VMContext; public: ConstExprEmitter(CodeGenModule &cgm, CodeGenFunction *cgf) - : CGM(cgm), CGF(cgf) { + : CGM(cgm), CGF(cgf), VMContext(cgm.getLLVMContext()) { } - + //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// - + llvm::Constant *VisitStmt(Stmt *S) { return 0; } - - llvm::Constant *VisitParenExpr(ParenExpr *PE) { - return Visit(PE->getSubExpr()); + + llvm::Constant *VisitParenExpr(ParenExpr *PE) { + return Visit(PE->getSubExpr()); } - + llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { return Visit(E->getInitializer()); } - + + llvm::Constant *EmitMemberFunctionPointer(CXXMethodDecl *MD) { + assert(MD->isInstance() && "Member function must not be static!"); + + const llvm::Type *PtrDiffTy = + CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); + + llvm::Constant *Values[2]; + + // Get the function pointer (or index if this is a virtual function). + if (MD->isVirtual()) { + int64_t Index = CGM.getVtableInfo().getMethodVtableIndex(MD); + + Values[0] = llvm::ConstantInt::get(PtrDiffTy, Index + 1); + } else { + llvm::Constant *FuncPtr = CGM.GetAddrOfFunction(MD); + + Values[0] = llvm::ConstantExpr::getPtrToInt(FuncPtr, PtrDiffTy); + } + + // The adjustment will always be 0. + Values[1] = llvm::ConstantInt::get(PtrDiffTy, 0); + + return llvm::ConstantStruct::get(CGM.getLLVMContext(), + Values, 2, /*Packed=*/false); + } + + llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) { + if (const MemberPointerType *MPT = + E->getType()->getAs<MemberPointerType>()) { + QualType T = MPT->getPointeeType(); + if (T->isFunctionProtoType()) { + QualifiedDeclRefExpr *DRE = cast<QualifiedDeclRefExpr>(E->getSubExpr()); + + return EmitMemberFunctionPointer(cast<CXXMethodDecl>(DRE->getDecl())); + } + + // FIXME: Should we handle other member pointer types here too, + // or should they be handled by Expr::Evaluate? + } + + return 0; + } + + llvm::Constant *VisitBinSub(BinaryOperator *E) { + // This must be a pointer/pointer subtraction. This only happens for + // address of label. + if (!isa<AddrLabelExpr>(E->getLHS()->IgnoreParenNoopCasts(CGM.getContext())) || + !isa<AddrLabelExpr>(E->getRHS()->IgnoreParenNoopCasts(CGM.getContext()))) + return 0; + + llvm::Constant *LHS = CGM.EmitConstantExpr(E->getLHS(), + E->getLHS()->getType(), CGF); + llvm::Constant *RHS = CGM.EmitConstantExpr(E->getRHS(), + E->getRHS()->getType(), CGF); + + const llvm::Type *ResultType = ConvertType(E->getType()); + LHS = llvm::ConstantExpr::getPtrToInt(LHS, ResultType); + RHS = llvm::ConstantExpr::getPtrToInt(RHS, ResultType); + + // No need to divide by element size, since addr of label is always void*, + // which has size 1 in GNUish. + return llvm::ConstantExpr::getSub(LHS, RHS); + } + llvm::Constant *VisitCastExpr(CastExpr* E) { - // GCC cast to union extension - if (E->getType()->isUnionType()) { + switch (E->getCastKind()) { + case CastExpr::CK_ToUnion: { + // GCC cast to union extension + assert(E->getType()->isUnionType() && + "Destination type is not union type!"); const llvm::Type *Ty = ConvertType(E->getType()); Expr *SubExpr = E->getSubExpr(); - return EmitUnion(CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF), - Ty); + + llvm::Constant *C = + CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF); + if (!C) + return 0; + + // Build a struct with the union sub-element as the first member, + // and padded to the appropriate size + std::vector<llvm::Constant*> Elts; + std::vector<const llvm::Type*> Types; + Elts.push_back(C); + Types.push_back(C->getType()); + unsigned CurSize = CGM.getTargetData().getTypeAllocSize(C->getType()); + unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(Ty); + + assert(CurSize <= TotalSize && "Union size mismatch!"); + if (unsigned NumPadBytes = TotalSize - CurSize) { + const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext); + if (NumPadBytes > 1) + Ty = llvm::ArrayType::get(Ty, NumPadBytes); + + Elts.push_back(llvm::Constant::getNullValue(Ty)); + Types.push_back(Ty); + } + + llvm::StructType* STy = + llvm::StructType::get(C->getType()->getContext(), Types, false); + return llvm::ConstantStruct::get(STy, Elts); + } + case CastExpr::CK_NullToMemberPointer: + return CGM.EmitNullConstant(E->getType()); + + case CastExpr::CK_BaseToDerivedMemberPointer: { + Expr *SubExpr = E->getSubExpr(); + + const MemberPointerType *SrcTy = + SubExpr->getType()->getAs<MemberPointerType>(); + const MemberPointerType *DestTy = + E->getType()->getAs<MemberPointerType>(); + + const CXXRecordDecl *BaseClass = + cast<CXXRecordDecl>(cast<RecordType>(SrcTy->getClass())->getDecl()); + const CXXRecordDecl *DerivedClass = + cast<CXXRecordDecl>(cast<RecordType>(DestTy->getClass())->getDecl()); + + if (SrcTy->getPointeeType()->isFunctionProtoType()) { + llvm::Constant *C = + CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF); + if (!C) + return 0; + + llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C); + + // Check if we need to update the adjustment. + if (llvm::Constant *Offset = CGM.GetCXXBaseClassOffset(DerivedClass, + BaseClass)) { + llvm::Constant *Values[2]; + + Values[0] = CS->getOperand(0); + Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset); + return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2, + /*Packed=*/false); + } + + return CS; + } + } + + default: { + // FIXME: This should be handled by the CK_NoOp cast kind. + // Explicit and implicit no-op casts + QualType Ty = E->getType(), SubTy = E->getSubExpr()->getType(); + if (CGM.getContext().hasSameUnqualifiedType(Ty, SubTy)) + return Visit(E->getSubExpr()); + + // Handle integer->integer casts for address-of-label differences. + if (Ty->isIntegerType() && SubTy->isIntegerType() && + CGF) { + llvm::Value *Src = Visit(E->getSubExpr()); + if (Src == 0) return 0; + + // Use EmitScalarConversion to perform the conversion. + return cast<llvm::Constant>(CGF->EmitScalarConversion(Src, SubTy, Ty)); + } + + return 0; } - // Explicit and implicit no-op casts - QualType Ty = E->getType(), SubTy = E->getSubExpr()->getType(); - if (CGM.getContext().hasSameUnqualifiedType(Ty, SubTy)) { - return Visit(E->getSubExpr()); } - return 0; } llvm::Constant *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { @@ -79,7 +576,7 @@ public: unsigned NumInitElements = ILE->getNumInits(); // FIXME: Check for wide strings // FIXME: Check for NumInitElements exactly equal to 1?? - if (NumInitElements > 0 && + if (NumInitElements > 0 && (isa<StringLiteral>(ILE->getInit(0)) || isa<ObjCEncodeExpr>(ILE->getInit(0))) && ILE->getType()->getArrayElementTypeNoTypeQual()->isCharType()) @@ -87,7 +584,7 @@ public: const llvm::Type *ElemTy = AType->getElementType(); unsigned NumElements = AType->getNumElements(); - // Initialising an array requires us to automatically + // Initialising an array requires us to automatically // initialise any elements that have not been initialised explicitly unsigned NumInitableElts = std::min(NumInitElements, NumElements); @@ -113,184 +610,20 @@ public: std::vector<const llvm::Type*> Types; for (unsigned i = 0; i < Elts.size(); ++i) Types.push_back(Elts[i]->getType()); - const llvm::StructType *SType = llvm::StructType::get(Types, true); + const llvm::StructType *SType = llvm::StructType::get(AType->getContext(), + Types, true); return llvm::ConstantStruct::get(SType, Elts); } - return llvm::ConstantArray::get(AType, Elts); - } - - void InsertBitfieldIntoStruct(std::vector<llvm::Constant*>& Elts, - FieldDecl* Field, Expr* E) { - // Calculate the value to insert - llvm::Constant *C = CGM.EmitConstantExpr(E, Field->getType(), CGF); - if (!C) - return; - - llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C); - if (!CI) { - CGM.ErrorUnsupported(E, "bitfield initialization"); - return; - } - llvm::APInt V = CI->getValue(); - - // Calculate information about the relevant field - const llvm::Type* Ty = CI->getType(); - const llvm::TargetData &TD = CGM.getTypes().getTargetData(); - unsigned size = TD.getTypeAllocSizeInBits(Ty); - unsigned fieldOffset = CGM.getTypes().getLLVMFieldNo(Field) * size; - CodeGenTypes::BitFieldInfo bitFieldInfo = - CGM.getTypes().getBitFieldInfo(Field); - fieldOffset += bitFieldInfo.Begin; - - // Find where to start the insertion - // FIXME: This is O(n^2) in the number of bit-fields! - // FIXME: This won't work if the struct isn't completely packed! - unsigned offset = 0, i = 0; - while (offset < (fieldOffset & -8)) - offset += TD.getTypeAllocSizeInBits(Elts[i++]->getType()); - - // Advance over 0 sized elements (must terminate in bounds since - // the bitfield must have a size). - while (TD.getTypeAllocSizeInBits(Elts[i]->getType()) == 0) - ++i; - - // Promote the size of V if necessary - // FIXME: This should never occur, but currently it can because initializer - // constants are cast to bool, and because clang is not enforcing bitfield - // width limits. - if (bitFieldInfo.Size > V.getBitWidth()) - V.zext(bitFieldInfo.Size); - - // Insert the bits into the struct - // FIXME: This algorthm is only correct on X86! - // FIXME: THis algorthm assumes bit-fields only have byte-size elements! - unsigned bitsToInsert = bitFieldInfo.Size; - unsigned curBits = std::min(8 - (fieldOffset & 7), bitsToInsert); - unsigned byte = V.getLoBits(curBits).getZExtValue() << (fieldOffset & 7); - do { - llvm::Constant* byteC = llvm::ConstantInt::get(llvm::Type::Int8Ty, byte); - Elts[i] = llvm::ConstantExpr::getOr(Elts[i], byteC); - ++i; - V = V.lshr(curBits); - bitsToInsert -= curBits; - - if (!bitsToInsert) - break; - - curBits = bitsToInsert > 8 ? 8 : bitsToInsert; - byte = V.getLoBits(curBits).getZExtValue(); - } while (true); + return llvm::ConstantArray::get(AType, Elts); } llvm::Constant *EmitStructInitialization(InitListExpr *ILE) { - const llvm::StructType *SType = - cast<llvm::StructType>(ConvertType(ILE->getType())); - RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl(); - std::vector<llvm::Constant*> Elts; - - // Initialize the whole structure to zero. - // FIXME: This doesn't handle member pointers correctly! - for (unsigned i = 0; i < SType->getNumElements(); ++i) { - const llvm::Type *FieldTy = SType->getElementType(i); - Elts.push_back(llvm::Constant::getNullValue(FieldTy)); - } - - // Copy initializer elements. Skip padding fields. - unsigned EltNo = 0; // Element no in ILE - bool RewriteType = false; - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); - EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) { - if (Field->isBitField()) { - if (!Field->getIdentifier()) - continue; - InsertBitfieldIntoStruct(Elts, *Field, ILE->getInit(EltNo)); - } else { - unsigned FieldNo = CGM.getTypes().getLLVMFieldNo(*Field); - llvm::Constant *C = CGM.EmitConstantExpr(ILE->getInit(EltNo), - Field->getType(), CGF); - if (!C) return 0; - RewriteType |= (C->getType() != Elts[FieldNo]->getType()); - Elts[FieldNo] = C; - } - EltNo++; - } - - if (RewriteType) { - // FIXME: Make this work for non-packed structs - assert(SType->isPacked() && "Cannot recreate unpacked structs"); - std::vector<const llvm::Type*> Types; - for (unsigned i = 0; i < Elts.size(); ++i) - Types.push_back(Elts[i]->getType()); - SType = llvm::StructType::get(Types, true); - } - - return llvm::ConstantStruct::get(SType, Elts); - } - - llvm::Constant *EmitUnion(llvm::Constant *C, const llvm::Type *Ty) { - if (!C) - return 0; - - // Build a struct with the union sub-element as the first member, - // and padded to the appropriate size - std::vector<llvm::Constant*> Elts; - std::vector<const llvm::Type*> Types; - Elts.push_back(C); - Types.push_back(C->getType()); - unsigned CurSize = CGM.getTargetData().getTypeAllocSize(C->getType()); - unsigned TotalSize = CGM.getTargetData().getTypeAllocSize(Ty); - while (CurSize < TotalSize) { - Elts.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty)); - Types.push_back(llvm::Type::Int8Ty); - CurSize++; - } - - // This always generates a packed struct - // FIXME: Try to generate an unpacked struct when we can - llvm::StructType* STy = llvm::StructType::get(Types, true); - return llvm::ConstantStruct::get(STy, Elts); + return ConstStructBuilder::BuildStruct(CGM, CGF, ILE); } llvm::Constant *EmitUnionInitialization(InitListExpr *ILE) { - const llvm::Type *Ty = ConvertType(ILE->getType()); - - FieldDecl* curField = ILE->getInitializedFieldInUnion(); - if (!curField) { - // There's no field to initialize, so value-initialize the union. -#ifndef NDEBUG - // Make sure that it's really an empty and not a failure of - // semantic analysis. - RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl(); - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); - Field != FieldEnd; ++Field) - assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed"); -#endif - return llvm::Constant::getNullValue(Ty); - } - - if (curField->isBitField()) { - // Create a dummy struct for bit-field insertion - unsigned NumElts = CGM.getTargetData().getTypeAllocSize(Ty); - llvm::Constant* NV = llvm::Constant::getNullValue(llvm::Type::Int8Ty); - std::vector<llvm::Constant*> Elts(NumElts, NV); - - InsertBitfieldIntoStruct(Elts, curField, ILE->getInit(0)); - const llvm::ArrayType *RetTy = - llvm::ArrayType::get(NV->getType(), NumElts); - return llvm::ConstantArray::get(RetTy, Elts); - } - - llvm::Constant *InitElem; - if (ILE->getNumInits() > 0) { - Expr *Init = ILE->getInit(0); - InitElem = CGM.EmitConstantExpr(Init, Init->getType(), CGF); - } else { - InitElem = CGM.EmitNullConstant(curField->getType()); - } - return EmitUnion(InitElem, Ty); + return ConstStructBuilder::BuildStruct(CGM, CGF, ILE); } llvm::Constant *EmitVectorInitialization(InitListExpr *ILE) { @@ -316,13 +649,13 @@ public: for (; i < NumElements; ++i) Elts.push_back(llvm::Constant::getNullValue(ElemTy)); - return llvm::ConstantVector::get(VType, Elts); + return llvm::ConstantVector::get(VType, Elts); } - + llvm::Constant *VisitImplicitValueInitExpr(ImplicitValueInitExpr* E) { return CGM.EmitNullConstant(E->getType()); } - + llvm::Constant *VisitInitListExpr(InitListExpr *ILE) { if (ILE->getType()->isScalarType()) { // We have a scalar in braces. Just use the first element. @@ -332,7 +665,7 @@ public: } return CGM.EmitNullConstant(ILE->getType()); } - + if (ILE->getType()->isArrayType()) return EmitArrayInitialization(ILE); @@ -353,11 +686,12 @@ public: llvm::Constant *VisitStringLiteral(StringLiteral *E) { assert(!E->getType()->isPointerType() && "Strings are always arrays"); - + // This must be a string initializing an array in a static initializer. // Don't emit it as the address of the string, emit the string data itself // as an inline array. - return llvm::ConstantArray::get(CGM.GetStringForStringLiteral(E), false); + return llvm::ConstantArray::get(VMContext, + CGM.GetStringForStringLiteral(E), false); } llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E) { @@ -367,13 +701,13 @@ public: std::string Str; CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str); const ConstantArrayType *CAT = cast<ConstantArrayType>(E->getType()); - + // Resize the string to the right size, adding zeros at the end, or // truncating as needed. Str.resize(CAT->getSize().getZExtValue(), '\0'); - return llvm::ConstantArray::get(Str, false); + return llvm::ConstantArray::get(VMContext, Str, false); } - + llvm::Constant *VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } @@ -394,20 +728,21 @@ public: llvm::Constant* C = Visit(CLE->getInitializer()); // FIXME: "Leaked" on failure. if (C) - C = new llvm::GlobalVariable(C->getType(), - E->getType().isConstQualified(), + C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), + E->getType().isConstant(CGM.getContext()), llvm::GlobalValue::InternalLinkage, - C, ".compoundliteral", &CGM.getModule()); + C, ".compoundliteral", 0, false, + E->getType().getAddressSpace()); return C; } - case Expr::DeclRefExprClass: + case Expr::DeclRefExprClass: case Expr::QualifiedDeclRefExprClass: { NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl)) - return CGM.GetAddrOfFunction(GlobalDecl(FD)); + return CGM.GetAddrOfFunction(FD); if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) { // We can never refer to a variable with local storage. - if (!VD->hasLocalStorage()) { + if (!VD->hasLocalStorage()) { if (VD->isFileVarDecl() || VD->hasExternalStorage()) return CGM.GetAddrOfGlobalVar(VD); else if (VD->isBlockVarDecl()) { @@ -430,21 +765,23 @@ public: case Expr::PredefinedExprClass: { // __func__/__FUNCTION__ -> "". __PRETTY_FUNCTION__ -> "top level". std::string Str; - if (cast<PredefinedExpr>(E)->getIdentType() == + if (cast<PredefinedExpr>(E)->getIdentType() == PredefinedExpr::PrettyFunction) Str = "top level"; - + return CGM.GetAddrOfConstantCString(Str, ".tmp"); } case Expr::AddrLabelExprClass: { assert(CGF && "Invalid address of label expression outside function."); - unsigned id = CGF->GetIDForAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel()); - llvm::Constant *C = llvm::ConstantInt::get(llvm::Type::Int32Ty, id); + unsigned id = + CGF->GetIDForAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel()); + llvm::Constant *C = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), id); return llvm::ConstantExpr::getIntToPtr(C, ConvertType(E->getType())); } case Expr::CallExprClass: { CallExpr* CE = cast<CallExpr>(E); - if (CE->isBuiltinCall(CGM.getContext()) != + if (CE->isBuiltinCall(CGM.getContext()) != Builtin::BI__builtin___CFStringMakeConstantString) break; const Expr *Arg = CE->getArg(0)->IgnoreParenCasts(); @@ -466,23 +803,23 @@ public: return 0; } }; - + } // end anonymous namespace. llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, QualType DestType, CodeGenFunction *CGF) { Expr::EvalResult Result; - + bool Success = false; - + if (DestType->isReferenceType()) Success = E->EvaluateAsLValue(Result, Context); - else + else Success = E->Evaluate(Result, Context); - + if (Success) { - assert(!Result.HasSideEffects && + assert(!Result.HasSideEffects && "Constant expr should not have any side effects!"); switch (Result.Val.getKind()) { case APValue::Uninitialized: @@ -490,18 +827,17 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, return 0; case APValue::LValue: { const llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType); - llvm::Constant *Offset = - llvm::ConstantInt::get(llvm::Type::Int64Ty, + llvm::Constant *Offset = + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), Result.Val.getLValueOffset()); - + llvm::Constant *C; if (const Expr *LVBase = Result.Val.getLValueBase()) { C = ConstExprEmitter(*this, CGF).EmitLValue(const_cast<Expr*>(LVBase)); // Apply offset if necessary. if (!Offset->isNullValue()) { - const llvm::Type *Type = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext); llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, Type); Casted = llvm::ConstantExpr::getGetElementPtr(Casted, &Offset, 1); C = llvm::ConstantExpr::getBitCast(Casted, C->getType()); @@ -529,9 +865,10 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, } } case APValue::Int: { - llvm::Constant *C = llvm::ConstantInt::get(Result.Val.getInt()); - - if (C->getType() == llvm::Type::Int1Ty) { + llvm::Constant *C = llvm::ConstantInt::get(VMContext, + Result.Val.getInt()); + + if (C->getType() == llvm::Type::getInt1Ty(VMContext)) { const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType()); C = llvm::ConstantExpr::getZExt(C, BoolTy); } @@ -539,32 +876,38 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, } case APValue::ComplexInt: { llvm::Constant *Complex[2]; - - Complex[0] = llvm::ConstantInt::get(Result.Val.getComplexIntReal()); - Complex[1] = llvm::ConstantInt::get(Result.Val.getComplexIntImag()); - - return llvm::ConstantStruct::get(Complex, 2); + + Complex[0] = llvm::ConstantInt::get(VMContext, + Result.Val.getComplexIntReal()); + Complex[1] = llvm::ConstantInt::get(VMContext, + Result.Val.getComplexIntImag()); + + // FIXME: the target may want to specify that this is packed. + return llvm::ConstantStruct::get(VMContext, Complex, 2, false); } case APValue::Float: - return llvm::ConstantFP::get(Result.Val.getFloat()); + return llvm::ConstantFP::get(VMContext, Result.Val.getFloat()); case APValue::ComplexFloat: { llvm::Constant *Complex[2]; - - Complex[0] = llvm::ConstantFP::get(Result.Val.getComplexFloatReal()); - Complex[1] = llvm::ConstantFP::get(Result.Val.getComplexFloatImag()); - - return llvm::ConstantStruct::get(Complex, 2); + + Complex[0] = llvm::ConstantFP::get(VMContext, + Result.Val.getComplexFloatReal()); + Complex[1] = llvm::ConstantFP::get(VMContext, + Result.Val.getComplexFloatImag()); + + // FIXME: the target may want to specify that this is packed. + return llvm::ConstantStruct::get(VMContext, Complex, 2, false); } case APValue::Vector: { llvm::SmallVector<llvm::Constant *, 4> Inits; unsigned NumElts = Result.Val.getVectorLength(); - + for (unsigned i = 0; i != NumElts; ++i) { APValue &Elt = Result.Val.getVectorElt(i); if (Elt.isInt()) - Inits.push_back(llvm::ConstantInt::get(Elt.getInt())); + Inits.push_back(llvm::ConstantInt::get(VMContext, Elt.getInt())); else - Inits.push_back(llvm::ConstantFP::get(Elt.getFloat())); + Inits.push_back(llvm::ConstantFP::get(VMContext, Elt.getFloat())); } return llvm::ConstantVector::get(&Inits[0], Inits.size()); } @@ -572,15 +915,58 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, } llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E)); - if (C && C->getType() == llvm::Type::Int1Ty) { + if (C && C->getType() == llvm::Type::getInt1Ty(VMContext)) { const llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType()); C = llvm::ConstantExpr::getZExt(C, BoolTy); } return C; } +static inline bool isDataMemberPointerType(QualType T) { + if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) + return !MPT->getPointeeType()->isFunctionType(); + + return false; +} + llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { - // Always return an LLVM null constant for now; this will change when we - // get support for IRGen of member pointers. - return llvm::Constant::getNullValue(getTypes().ConvertType(T)); + // No need to check for member pointers when not compiling C++. + if (!getContext().getLangOptions().CPlusPlus) + return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); + + if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) { + + QualType ElementTy = CAT->getElementType(); + + // FIXME: Handle arrays of structs that contain member pointers. + if (isDataMemberPointerType(Context.getBaseElementType(ElementTy))) { + llvm::Constant *Element = EmitNullConstant(ElementTy); + uint64_t NumElements = CAT->getSize().getZExtValue(); + std::vector<llvm::Constant *> Array(NumElements); + for (uint64_t i = 0; i != NumElements; ++i) + Array[i] = Element; + + const llvm::ArrayType *ATy = + cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T)); + return llvm::ConstantArray::get(ATy, Array); + } + } + + if (const RecordType *RT = T->getAs<RecordType>()) { + const RecordDecl *RD = RT->getDecl(); + // FIXME: It would be better if there was a way to explicitly compute the + // record layout instead of converting to a type. + Types.ConvertTagDeclType(RD); + + const CGRecordLayout &Layout = Types.getCGRecordLayout(RD); + if (Layout.containsMemberPointer()) { + assert(0 && "FIXME: No support for structs with member pointers yet!"); + } + } + + // FIXME: Handle structs that contain member pointers. + if (isDataMemberPointerType(T)) + return llvm::Constant::getAllOnesValue(getTypes().ConvertTypeForMem(T)); + + return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T)); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 2af0639f5ce38..cc81256032afb 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenFunction.h" +#include "CGObjCRuntime.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -49,20 +50,23 @@ class VISIBILITY_HIDDEN ScalarExprEmitter CodeGenFunction &CGF; CGBuilderTy &Builder; bool IgnoreResultAssign; - + llvm::LLVMContext &VMContext; public: ScalarExprEmitter(CodeGenFunction &cgf, bool ira=false) - : CGF(cgf), Builder(CGF.Builder), IgnoreResultAssign(ira) { + : CGF(cgf), Builder(CGF.Builder), IgnoreResultAssign(ira), + VMContext(cgf.getLLVMContext()) { } - + //===--------------------------------------------------------------------===// // Utilities //===--------------------------------------------------------------------===// bool TestAndClearIgnoreResultAssign() { - bool I = IgnoreResultAssign; IgnoreResultAssign = false; - return I; } + bool I = IgnoreResultAssign; + IgnoreResultAssign = false; + return I; + } const llvm::Type *ConvertType(QualType T) { return CGF.ConvertType(T); } LValue EmitLValue(const Expr *E) { return CGF.EmitLValue(E); } @@ -70,25 +74,25 @@ public: Value *EmitLoadOfLValue(LValue LV, QualType T) { return CGF.EmitLoadOfLValue(LV, T).getScalarVal(); } - + /// EmitLoadOfLValue - Given an expression with complex type that represents a /// value l-value, this method emits the address of the l-value, then loads /// and returns the result. Value *EmitLoadOfLValue(const Expr *E) { return EmitLoadOfLValue(EmitLValue(E), E->getType()); } - + /// EmitConversionToBool - Convert the specified expression value to a /// boolean (i1) truth value. This is equivalent to "Val != 0". Value *EmitConversionToBool(Value *Src, QualType DstTy); - + /// EmitScalarConversion - Emit a conversion from the specified type to the /// specified destination type, both of which are LLVM scalar types. Value *EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy); /// EmitComplexToScalarConversion - Emit a conversion from the specified - /// complex type to the specified destination type, where the destination - /// type is an LLVM scalar type. + /// complex type to the specified destination type, where the destination type + /// is an LLVM scalar type. Value *EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy); @@ -106,10 +110,10 @@ public: // Leaves. Value *VisitIntegerLiteral(const IntegerLiteral *E) { - return llvm::ConstantInt::get(E->getValue()); + return llvm::ConstantInt::get(VMContext, E->getValue()); } Value *VisitFloatingLiteral(const FloatingLiteral *E) { - return llvm::ConstantFP::get(E->getValue()); + return llvm::ConstantFP::get(VMContext, E->getValue()); } Value *VisitCharacterLiteral(const CharacterLiteral *E) { return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); @@ -130,32 +134,33 @@ public: } Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E); Value *VisitAddrLabelExpr(const AddrLabelExpr *E) { - llvm::Value *V = - llvm::ConstantInt::get(llvm::Type::Int32Ty, + llvm::Value *V = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), CGF.GetIDForAddrOfLabel(E->getLabel())); - + return Builder.CreateIntToPtr(V, ConvertType(E->getType())); } - + // l-values. Value *VisitDeclRefExpr(DeclRefExpr *E) { if (const EnumConstantDecl *EC = dyn_cast<EnumConstantDecl>(E->getDecl())) - return llvm::ConstantInt::get(EC->getInitVal()); + return llvm::ConstantInt::get(VMContext, EC->getInitVal()); return EmitLoadOfLValue(E); } - Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - return CGF.EmitObjCSelectorExpr(E); + Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) { + return CGF.EmitObjCSelectorExpr(E); } - Value *VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - return CGF.EmitObjCProtocolExpr(E); + Value *VisitObjCProtocolExpr(ObjCProtocolExpr *E) { + return CGF.EmitObjCProtocolExpr(E); } - Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + Value *VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { return EmitLoadOfLValue(E); } Value *VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { return EmitLoadOfLValue(E); } - Value *VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { + Value *VisitObjCImplicitSetterGetterRefExpr( + ObjCImplicitSetterGetterRefExpr *E) { return EmitLoadOfLValue(E); } Value *VisitObjCMessageExpr(ObjCMessageExpr *E) { @@ -173,7 +178,7 @@ public: Value *VisitObjCEncodeExpr(const ObjCEncodeExpr *E) { return EmitLValue(E).getAddress(); } - + Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); } Value *VisitInitListExpr(InitListExpr *E) { @@ -181,66 +186,67 @@ public: (void)Ignore; assert (Ignore == false && "init list ignored"); unsigned NumInitElements = E->getNumInits(); - + if (E->hadArrayRangeDesignator()) { CGF.ErrorUnsupported(E, "GNU array range designator extension"); } - const llvm::VectorType *VType = + const llvm::VectorType *VType = dyn_cast<llvm::VectorType>(ConvertType(E->getType())); - + // We have a scalar in braces. Just use the first element. - if (!VType) + if (!VType) return Visit(E->getInit(0)); - + unsigned NumVectorElements = VType->getNumElements(); const llvm::Type *ElementType = VType->getElementType(); // Emit individual vector element stores. llvm::Value *V = llvm::UndefValue::get(VType); - + // Emit initializers unsigned i; for (i = 0; i < NumInitElements; ++i) { Value *NewV = Visit(E->getInit(i)); - Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Value *Idx = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i); V = Builder.CreateInsertElement(V, NewV, Idx); } - + // Emit remaining default initializers for (/* Do not initialize i*/; i < NumVectorElements; ++i) { - Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + Value *Idx = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i); llvm::Value *NewV = llvm::Constant::getNullValue(ElementType); V = Builder.CreateInsertElement(V, NewV, Idx); } - + return V; } - + Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { return llvm::Constant::getNullValue(ConvertType(E->getType())); } - Value *VisitImplicitCastExpr(const ImplicitCastExpr *E); Value *VisitCastExpr(const CastExpr *E) { // Make sure to evaluate VLA bounds now so that we have them for later. if (E->getType()->isVariablyModifiedType()) CGF.EmitVLASize(E->getType()); - return EmitCastExpr(E->getSubExpr(), E->getType()); + return EmitCastExpr(E); } - Value *EmitCastExpr(const Expr *E, QualType T); + Value *EmitCastExpr(const CastExpr *E); Value *VisitCallExpr(const CallExpr *E) { if (E->getCallReturnType()->isReferenceType()) return EmitLoadOfLValue(E); - + return CGF.EmitCallExpr(E).getScalarVal(); } Value *VisitStmtExpr(const StmtExpr *E); Value *VisitBlockDeclRefExpr(const BlockDeclRefExpr *E); - + // Unary Operators. Value *VisitPrePostIncDec(const UnaryOperator *E, bool isInc, bool isPre); Value *VisitUnaryPostDec(const UnaryOperator *E) { @@ -273,22 +279,40 @@ public: return Visit(E->getSubExpr()); } Value *VisitUnaryOffsetOf(const UnaryOperator *E); - + // C++ Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { return Visit(DAE->getExpr()); } Value *VisitCXXThisExpr(CXXThisExpr *TE) { return CGF.LoadCXXThis(); - } - + } + Value *VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { return CGF.EmitCXXExprWithTemporaries(E).getScalarVal(); } Value *VisitCXXNewExpr(const CXXNewExpr *E) { return CGF.EmitCXXNewExpr(E); } - + Value *VisitCXXDeleteExpr(const CXXDeleteExpr *E) { + CGF.EmitCXXDeleteExpr(E); + return 0; + } + + Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) { + // C++ [expr.pseudo]p1: + // The result shall only be used as the operand for the function call + // operator (), and the result of such a call has type void. The only + // effect is the evaluation of the postfix-expression before the dot or + // arrow. + CGF.EmitScalarExpr(E->getBase()); + return 0; + } + + Value *VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) { + return llvm::Constant::getNullValue(ConvertType(E->getType())); + } + // Binary Operators. Value *EmitMul(const BinOpInfo &Ops) { if (CGF.getContext().getLangOptions().OverflowChecking @@ -355,7 +379,7 @@ public: VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ); VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE); #undef VISITCOMP - + Value *VisitBinAssign (const BinaryOperator *E); Value *VisitBinLAnd (const BinaryOperator *E); @@ -381,21 +405,30 @@ public: /// boolean (i1) truth value. This is equivalent to "Val != 0". Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { assert(SrcType->isCanonical() && "EmitScalarConversion strips typedefs"); - + if (SrcType->isRealFloatingType()) { // Compare against 0.0 for fp scalars. llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType()); return Builder.CreateFCmpUNE(Src, Zero, "tobool"); } - + + if (SrcType->isMemberPointerType()) { + // FIXME: This is ABI specific. + + // Compare against -1. + llvm::Value *NegativeOne = llvm::Constant::getAllOnesValue(Src->getType()); + return Builder.CreateICmpNE(Src, NegativeOne, "tobool"); + } + assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) && "Unknown scalar type to convert"); - + // Because of the type rules of C, we often end up computing a logical value, // then zero extending it to int, then wanting it as a logical value again. // Optimize this common case. if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(Src)) { - if (ZI->getOperand(0)->getType() == llvm::Type::Int1Ty) { + if (ZI->getOperand(0)->getType() == + llvm::Type::getInt1Ty(CGF.getLLVMContext())) { Value *Result = ZI->getOperand(0); // If there aren't any more uses, zap the instruction to save space. // Note that there can be more uses, for example if this @@ -405,7 +438,7 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { return Result; } } - + // Compare against an integer or pointer null. llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType()); return Builder.CreateICmpNE(Src, Zero, "tobool"); @@ -418,61 +451,66 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, SrcType = CGF.getContext().getCanonicalType(SrcType); DstType = CGF.getContext().getCanonicalType(DstType); if (SrcType == DstType) return Src; - + if (DstType->isVoidType()) return 0; + llvm::LLVMContext &VMContext = CGF.getLLVMContext(); + // Handle conversions to bool first, they are special: comparisons against 0. if (DstType->isBooleanType()) return EmitConversionToBool(Src, SrcType); - + const llvm::Type *DstTy = ConvertType(DstType); // Ignore conversions like int -> uint. if (Src->getType() == DstTy) return Src; - // Handle pointer conversions next: pointers can only be converted - // to/from other pointers and integers. Check for pointer types in - // terms of LLVM, as some native types (like Obj-C id) may map to a - // pointer type. + // Handle pointer conversions next: pointers can only be converted to/from + // other pointers and integers. Check for pointer types in terms of LLVM, as + // some native types (like Obj-C id) may map to a pointer type. if (isa<llvm::PointerType>(DstTy)) { // The source value may be an integer, or a pointer. if (isa<llvm::PointerType>(Src->getType())) return Builder.CreateBitCast(Src, DstTy, "conv"); + assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?"); // First, convert to the correct width so that we control the kind of // extension. - const llvm::Type *MiddleTy = llvm::IntegerType::get(CGF.LLVMPointerWidth); + const llvm::Type *MiddleTy = + llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth); bool InputSigned = SrcType->isSignedIntegerType(); llvm::Value* IntResult = Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); // Then, cast to pointer. return Builder.CreateIntToPtr(IntResult, DstTy, "conv"); } - + if (isa<llvm::PointerType>(Src->getType())) { // Must be an ptr to int cast. assert(isa<llvm::IntegerType>(DstTy) && "not ptr->int?"); return Builder.CreatePtrToInt(Src, DstTy, "conv"); } - + // A scalar can be splatted to an extended vector of the same element type - if (DstType->isExtVectorType() && !isa<VectorType>(SrcType)) { + if (DstType->isExtVectorType() && !SrcType->isVectorType()) { // Cast the scalar to element type - QualType EltTy = DstType->getAsExtVectorType()->getElementType(); + QualType EltTy = DstType->getAs<ExtVectorType>()->getElementType(); llvm::Value *Elt = EmitScalarConversion(Src, SrcType, EltTy); // Insert the element in element zero of an undef vector llvm::Value *UnV = llvm::UndefValue::get(DstTy); - llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + llvm::Value *Idx = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0); UnV = Builder.CreateInsertElement(UnV, Elt, Idx, "tmp"); // Splat the element across to all elements llvm::SmallVector<llvm::Constant*, 16> Args; unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements(); for (unsigned i = 0; i < NumElements; i++) - Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0)); - + Args.push_back(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), 0)); + llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements); llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat"); return Yay; @@ -482,7 +520,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, if (isa<llvm::VectorType>(Src->getType()) || isa<llvm::VectorType>(DstTy)) return Builder.CreateBitCast(Src, DstTy, "conv"); - + // Finally, we have the arithmetic types: real int/float. if (isa<llvm::IntegerType>(Src->getType())) { bool InputSigned = SrcType->isSignedIntegerType(); @@ -493,7 +531,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, else return Builder.CreateUIToFP(Src, DstTy, "conv"); } - + assert(Src->getType()->isFloatingPoint() && "Unknown real conversion"); if (isa<llvm::IntegerType>(DstTy)) { if (DstType->isSignedIntegerType()) @@ -509,15 +547,15 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, return Builder.CreateFPExt(Src, DstTy, "conv"); } -/// EmitComplexToScalarConversion - Emit a conversion from the specified -/// complex type to the specified destination type, where the destination -/// type is an LLVM scalar type. +/// EmitComplexToScalarConversion - Emit a conversion from the specified complex +/// type to the specified destination type, where the destination type is an +/// LLVM scalar type. Value *ScalarExprEmitter:: EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, QualType SrcTy, QualType DstTy) { // Get the source element type. - SrcTy = SrcTy->getAsComplexType()->getElementType(); - + SrcTy = SrcTy->getAs<ComplexType>()->getElementType(); + // Handle conversions to bool first, they are special: comparisons against 0. if (DstTy->isBooleanType()) { // Complex != 0 -> (Real != 0) | (Imag != 0) @@ -525,11 +563,11 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src, Src.second = EmitScalarConversion(Src.second, SrcTy, DstTy); return Builder.CreateOr(Src.first, Src.second, "tobool"); } - + // C99 6.3.1.7p2: "When a value of complex type is converted to a real type, // the imaginary part of the complex value is discarded and the value of the // real part is converted according to the conversion rules for the - // corresponding real type. + // corresponding real type. return EmitScalarConversion(Src.first, SrcTy, DstTy); } @@ -565,72 +603,122 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { // so we can't get it as an lvalue. if (!E->getBase()->getType()->isVectorType()) return EmitLoadOfLValue(E); - + // Handle the vector case. The base must be a vector, the index must be an // integer value. Value *Base = Visit(E->getBase()); Value *Idx = Visit(E->getIdx()); bool IdxSigned = E->getIdx()->getType()->isSignedIntegerType(); - Idx = Builder.CreateIntCast(Idx, llvm::Type::Int32Ty, IdxSigned, + Idx = Builder.CreateIntCast(Idx, + llvm::Type::getInt32Ty(CGF.getLLVMContext()), + IdxSigned, "vecidxcast"); return Builder.CreateExtractElement(Base, Idx, "vecext"); } -/// VisitImplicitCastExpr - Implicit casts are the same as normal casts, but -/// also handle things like function to pointer-to-function decay, and array to -/// pointer decay. -Value *ScalarExprEmitter::VisitImplicitCastExpr(const ImplicitCastExpr *E) { - const Expr *Op = E->getSubExpr(); +// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts +// have to handle a more broad range of conversions than explicit casts, as they +// handle things like function to ptr-to-function decay etc. +Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) { + const Expr *E = CE->getSubExpr(); + QualType DestTy = CE->getType(); + CastExpr::CastKind Kind = CE->getCastKind(); - // If this is due to array->pointer conversion, emit the array expression as - // an l-value. - if (Op->getType()->isArrayType()) { - Value *V = EmitLValue(Op).getAddress(); // Bitfields can't be arrays. + if (!DestTy->isVoidType()) + TestAndClearIgnoreResultAssign(); + + switch (Kind) { + default: + // FIXME: Assert here. + // assert(0 && "Unhandled cast kind!"); + break; + case CastExpr::CK_Unknown: + // FIXME: We should really assert here - Unknown casts should never get + // as far as to codegen. + break; + case CastExpr::CK_BitCast: { + Value *Src = Visit(const_cast<Expr*>(E)); + return Builder.CreateBitCast(Src, ConvertType(DestTy)); + } + case CastExpr::CK_ArrayToPointerDecay: { + assert(E->getType()->isArrayType() && + "Array to pointer decay must have array source type!"); + + Value *V = EmitLValue(E).getAddress(); // Bitfields can't be arrays. // Note that VLA pointers are always decayed, so we don't need to do // anything here. - if (!Op->getType()->isVariableArrayType()) { + if (!E->getType()->isVariableArrayType()) { assert(isa<llvm::PointerType>(V->getType()) && "Expected pointer"); assert(isa<llvm::ArrayType>(cast<llvm::PointerType>(V->getType()) ->getElementType()) && "Expected pointer to array"); V = Builder.CreateStructGEP(V, 0, "arraydecay"); } - + // The resultant pointer type can be implicitly casted to other pointer // types as well (e.g. void*) and can be implicitly converted to integer. - const llvm::Type *DestTy = ConvertType(E->getType()); - if (V->getType() != DestTy) { - if (isa<llvm::PointerType>(DestTy)) - V = Builder.CreateBitCast(V, DestTy, "ptrconv"); + const llvm::Type *DestLTy = ConvertType(DestTy); + if (V->getType() != DestLTy) { + if (isa<llvm::PointerType>(DestLTy)) + V = Builder.CreateBitCast(V, DestLTy, "ptrconv"); else { - assert(isa<llvm::IntegerType>(DestTy) && "Unknown array decay"); - V = Builder.CreatePtrToInt(V, DestTy, "ptrconv"); + assert(isa<llvm::IntegerType>(DestLTy) && "Unknown array decay"); + V = Builder.CreatePtrToInt(V, DestLTy, "ptrconv"); } } return V; } + case CastExpr::CK_NullToMemberPointer: + return CGF.CGM.EmitNullConstant(DestTy); + + case CastExpr::CK_DerivedToBase: { + const RecordType *DerivedClassTy = + E->getType()->getAs<PointerType>()->getPointeeType()->getAs<RecordType>(); + CXXRecordDecl *DerivedClassDecl = + cast<CXXRecordDecl>(DerivedClassTy->getDecl()); + + const RecordType *BaseClassTy = + DestTy->getAs<PointerType>()->getPointeeType()->getAs<RecordType>(); + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseClassTy->getDecl()); + + Value *Src = Visit(const_cast<Expr*>(E)); - return EmitCastExpr(Op, E->getType()); -} + bool NullCheckValue = true; + + if (isa<CXXThisExpr>(E)) { + // We always assume that 'this' is never null. + NullCheckValue = false; + } else if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) { + // And that lvalue casts are never null. + if (ICE->isLvalueCast()) + NullCheckValue = false; + } + return CGF.GetAddressCXXOfBaseClass(Src, DerivedClassDecl, BaseClassDecl, + NullCheckValue); + } + case CastExpr::CK_IntegralToPointer: { + Value *Src = Visit(const_cast<Expr*>(E)); + return Builder.CreateIntToPtr(Src, ConvertType(DestTy)); + } -// VisitCastExpr - Emit code for an explicit or implicit cast. Implicit casts -// have to handle a more broad range of conversions than explicit casts, as they -// handle things like function to ptr-to-function decay etc. -Value *ScalarExprEmitter::EmitCastExpr(const Expr *E, QualType DestTy) { - if (!DestTy->isVoidType()) - TestAndClearIgnoreResultAssign(); + case CastExpr::CK_PointerToIntegral: { + Value *Src = Visit(const_cast<Expr*>(E)); + return Builder.CreatePtrToInt(Src, ConvertType(DestTy)); + } + + } // Handle cases where the source is an non-complex type. - + if (!CGF.hasAggregateLLVMType(E->getType())) { Value *Src = Visit(const_cast<Expr*>(E)); // Use EmitScalarConversion to perform the conversion. return EmitScalarConversion(Src, E->getType(), DestTy); } - + if (E->getType()->isAnyComplexType()) { // Handle cases where the source is a complex type. bool IgnoreImag = true; @@ -661,7 +749,10 @@ Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) { } Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) { - return Builder.CreateLoad(CGF.GetAddrOfBlockDecl(E), false, "tmp"); + llvm::Value *V = CGF.GetAddrOfBlockDecl(E); + if (E->getType().isObjCGCWeak()) + return CGF.CGM.getObjCRuntime().EmitObjCWeakRead(CGF, V); + return Builder.CreateLoad(V, false, "tmp"); } //===----------------------------------------------------------------------===// @@ -673,55 +764,80 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E, LValue LV = EmitLValue(E->getSubExpr()); QualType ValTy = E->getSubExpr()->getType(); Value *InVal = CGF.EmitLoadOfLValue(LV, ValTy).getScalarVal(); - + + llvm::LLVMContext &VMContext = CGF.getLLVMContext(); + int AmountVal = isInc ? 1 : -1; if (ValTy->isPointerType() && - ValTy->getAsPointerType()->isVariableArrayType()) { + ValTy->getAs<PointerType>()->isVariableArrayType()) { // The amount of the addition/subtraction needs to account for the VLA size CGF.ErrorUnsupported(E, "VLA pointer inc/dec"); } Value *NextVal; - if (const llvm::PointerType *PT = + if (const llvm::PointerType *PT = dyn_cast<llvm::PointerType>(InVal->getType())) { - llvm::Constant *Inc =llvm::ConstantInt::get(llvm::Type::Int32Ty, AmountVal); + llvm::Constant *Inc = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), AmountVal); if (!isa<llvm::FunctionType>(PT->getElementType())) { - NextVal = Builder.CreateGEP(InVal, Inc, "ptrincdec"); + QualType PTEE = ValTy->getPointeeType(); + if (const ObjCInterfaceType *OIT = + dyn_cast<ObjCInterfaceType>(PTEE)) { + // Handle interface types, which are not represented with a concrete type. + int size = CGF.getContext().getTypeSize(OIT) / 8; + if (!isInc) + size = -size; + Inc = llvm::ConstantInt::get(Inc->getType(), size); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); + InVal = Builder.CreateBitCast(InVal, i8Ty); + NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr"); + llvm::Value *lhs = LV.getAddress(); + lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty)); + LV = LValue::MakeAddr(lhs, CGF.MakeQualifiers(ValTy)); + } else + NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec"); } else { - const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); NextVal = Builder.CreateBitCast(InVal, i8Ty, "tmp"); NextVal = Builder.CreateGEP(NextVal, Inc, "ptrincdec"); NextVal = Builder.CreateBitCast(NextVal, InVal->getType()); } - } else if (InVal->getType() == llvm::Type::Int1Ty && isInc) { + } else if (InVal->getType() == llvm::Type::getInt1Ty(VMContext) && isInc) { // Bool++ is an interesting case, due to promotion rules, we get: // Bool++ -> Bool = Bool+1 -> Bool = (int)Bool+1 -> // Bool = ((int)Bool+1) != 0 // An interesting aspect of this is that increment is always true. // Decrement does not have this property. - NextVal = llvm::ConstantInt::getTrue(); + NextVal = llvm::ConstantInt::getTrue(VMContext); } else if (isa<llvm::IntegerType>(InVal->getType())) { NextVal = llvm::ConstantInt::get(InVal->getType(), AmountVal); - NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec"); + + // Signed integer overflow is undefined behavior. + if (ValTy->isSignedIntegerType()) + NextVal = Builder.CreateNSWAdd(InVal, NextVal, isInc ? "inc" : "dec"); + else + NextVal = Builder.CreateAdd(InVal, NextVal, isInc ? "inc" : "dec"); } else { // Add the inc/dec to the real part. - if (InVal->getType() == llvm::Type::FloatTy) - NextVal = - llvm::ConstantFP::get(llvm::APFloat(static_cast<float>(AmountVal))); - else if (InVal->getType() == llvm::Type::DoubleTy) - NextVal = - llvm::ConstantFP::get(llvm::APFloat(static_cast<double>(AmountVal))); + if (InVal->getType()->isFloatTy()) + NextVal = + llvm::ConstantFP::get(VMContext, + llvm::APFloat(static_cast<float>(AmountVal))); + else if (InVal->getType()->isDoubleTy()) + NextVal = + llvm::ConstantFP::get(VMContext, + llvm::APFloat(static_cast<double>(AmountVal))); else { llvm::APFloat F(static_cast<float>(AmountVal)); bool ignored; F.convert(CGF.Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero, &ignored); - NextVal = llvm::ConstantFP::get(F); + NextVal = llvm::ConstantFP::get(VMContext, F); } NextVal = Builder.CreateFAdd(InVal, NextVal, isInc ? "inc" : "dec"); } - + // Store the updated result through the lvalue. if (LV.isBitfield()) CGF.EmitStoreThroughBitfieldLValue(RValue::get(NextVal), LV, ValTy, @@ -752,12 +868,12 @@ Value *ScalarExprEmitter::VisitUnaryNot(const UnaryOperator *E) { Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) { // Compare operand to zero. Value *BoolVal = CGF.EvaluateExprAsBool(E->getSubExpr()); - + // Invert value. // TODO: Could dynamically modify easy computations here. For example, if // the operand is an icmp ne, turn into icmp eq. BoolVal = Builder.CreateNot(BoolVal, "lnot"); - + // ZExt result to the expr type. return Builder.CreateZExt(BoolVal, ConvertType(E->getType()), "lnot.ext"); } @@ -768,7 +884,7 @@ Value * ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { QualType TypeToSize = E->getTypeOfArgument(); if (E->isSizeOf()) { - if (const VariableArrayType *VAT = + if (const VariableArrayType *VAT = CGF.getContext().getAsVariableArrayType(TypeToSize)) { if (E->isArgumentType()) { // sizeof(type) - make sure to emit the VLA size. @@ -778,16 +894,16 @@ ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { // VLA, it is evaluated. CGF.EmitAnyExpr(E->getArgumentExpr()); } - + return CGF.GetVLASize(VAT); } } - // If this isn't sizeof(vla), the result must be constant; use the - // constant folding logic so we don't have to duplicate it here. + // If this isn't sizeof(vla), the result must be constant; use the constant + // folding logic so we don't have to duplicate it here. Expr::EvalResult Result; E->Evaluate(Result, CGF.getContext()); - return llvm::ConstantInt::get(Result.Val.getInt()); + return llvm::ConstantInt::get(VMContext, Result.Val.getInt()); } Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) { @@ -800,7 +916,7 @@ Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) { Expr *Op = E->getSubExpr(); if (Op->getType()->isAnyComplexType()) return CGF.EmitComplexExpr(Op, true, false, true, false).second; - + // __imag on a scalar returns zero. Emit the subexpr to ensure side // effects are evaluated, but not the actual value. if (E->isLvalue(CGF.getContext()) == Expr::LV_Valid) @@ -810,8 +926,7 @@ Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) { return llvm::Constant::getNullValue(ConvertType(E->getType())); } -Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E) -{ +Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E) { Value* ResultAsPtr = EmitLValue(E->getSubExpr()).getAddress(); const llvm::Type* ResultType = ConvertType(E->getType()); return Builder.CreatePtrToInt(ResultAsPtr, ResultType, "offsetof"); @@ -839,10 +954,10 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, BinOpInfo OpInfo; if (E->getComputationResultType()->isAnyComplexType()) { - // This needs to go through the complex expression emitter, but - // it's a tad complicated to do that... I'm leaving it out for now. - // (Note that we do actually need the imaginary part of the RHS for - // multiplication and division.) + // This needs to go through the complex expression emitter, but it's a tad + // complicated to do that... I'm leaving it out for now. (Note that we do + // actually need the imaginary part of the RHS for multiplication and + // division.) CGF.ErrorUnsupported(E, "complex compound assignment"); return llvm::UndefValue::get(CGF.ConvertType(E->getType())); } @@ -857,17 +972,17 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy); OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy, E->getComputationLHSType()); - + // Expand the binary operator. Value *Result = (this->*Func)(OpInfo); - + // Convert the result back to the LHS type. Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy); - // Store the result value into the LHS lvalue. Bit-fields are - // handled specially because the result is altered by the store, - // i.e., [C99 6.5.16p1] 'An assignment expression has the value of - // the left operand after the assignment...'. + // Store the result value into the LHS lvalue. Bit-fields are handled + // specially because the result is altered by the store, i.e., [C99 6.5.16p1] + // 'An assignment expression has the value of the left operand after the + // assignment...'. if (LHSLV.isBitfield()) { if (!LHSLV.isVolatileQualified()) { CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy, @@ -949,31 +1064,31 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { Builder.SetInsertPoint(overflowBB); // Handler is: - // long long *__overflow_handler)(long long a, long long b, char op, + // long long *__overflow_handler)(long long a, long long b, char op, // char width) std::vector<const llvm::Type*> handerArgTypes; - handerArgTypes.push_back(llvm::Type::Int64Ty); - handerArgTypes.push_back(llvm::Type::Int64Ty); - handerArgTypes.push_back(llvm::Type::Int8Ty); - handerArgTypes.push_back(llvm::Type::Int8Ty); - llvm::FunctionType *handlerTy = llvm::FunctionType::get(llvm::Type::Int64Ty, - handerArgTypes, false); + handerArgTypes.push_back(llvm::Type::getInt64Ty(VMContext)); + handerArgTypes.push_back(llvm::Type::getInt64Ty(VMContext)); + handerArgTypes.push_back(llvm::Type::getInt8Ty(VMContext)); + handerArgTypes.push_back(llvm::Type::getInt8Ty(VMContext)); + llvm::FunctionType *handlerTy = llvm::FunctionType::get( + llvm::Type::getInt64Ty(VMContext), handerArgTypes, false); llvm::Value *handlerFunction = CGF.CGM.getModule().getOrInsertGlobal("__overflow_handler", llvm::PointerType::getUnqual(handlerTy)); handlerFunction = Builder.CreateLoad(handlerFunction); llvm::Value *handlerResult = Builder.CreateCall4(handlerFunction, - Builder.CreateSExt(Ops.LHS, llvm::Type::Int64Ty), - Builder.CreateSExt(Ops.RHS, llvm::Type::Int64Ty), - llvm::ConstantInt::get(llvm::Type::Int8Ty, OpID), - llvm::ConstantInt::get(llvm::Type::Int8Ty, + Builder.CreateSExt(Ops.LHS, llvm::Type::getInt64Ty(VMContext)), + Builder.CreateSExt(Ops.RHS, llvm::Type::getInt64Ty(VMContext)), + llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), OpID), + llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), cast<llvm::IntegerType>(opTy)->getBitWidth())); handlerResult = Builder.CreateTrunc(handlerResult, opTy); Builder.CreateBr(continueBB); - + // Set up the continuation Builder.SetInsertPoint(continueBB); // Get the correct result @@ -986,31 +1101,39 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) { } Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { - if (!Ops.Ty->isPointerType()) { + if (!Ops.Ty->isAnyPointerType()) { if (CGF.getContext().getLangOptions().OverflowChecking && Ops.Ty->isSignedIntegerType()) return EmitOverflowCheckedBinOp(Ops); - + if (Ops.LHS->getType()->isFPOrFPVector()) return Builder.CreateFAdd(Ops.LHS, Ops.RHS, "add"); - + + // Signed integer overflow is undefined behavior. + if (Ops.Ty->isSignedIntegerType()) + return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add"); + return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add"); } - if (Ops.Ty->getAsPointerType()->isVariableArrayType()) { + if (Ops.Ty->isPointerType() && + Ops.Ty->getAs<PointerType>()->isVariableArrayType()) { // The amount of the addition needs to account for the VLA size CGF.ErrorUnsupported(Ops.E, "VLA pointer addition"); } Value *Ptr, *Idx; Expr *IdxExp; - const PointerType *PT; - if ((PT = Ops.E->getLHS()->getType()->getAsPointerType())) { + const PointerType *PT = Ops.E->getLHS()->getType()->getAs<PointerType>(); + const ObjCObjectPointerType *OPT = + Ops.E->getLHS()->getType()->getAs<ObjCObjectPointerType>(); + if (PT || OPT) { Ptr = Ops.LHS; Idx = Ops.RHS; IdxExp = Ops.E->getRHS(); - } else { // int + pointer - PT = Ops.E->getRHS()->getType()->getAsPointerType(); - assert(PT && "Invalid add expr"); + } else { // int + pointer + PT = Ops.E->getRHS()->getType()->getAs<PointerType>(); + OPT = Ops.E->getRHS()->getType()->getAs<ObjCObjectPointerType>(); + assert((PT || OPT) && "Invalid add expr"); Ptr = Ops.RHS; Idx = Ops.LHS; IdxExp = Ops.E->getLHS(); @@ -1020,38 +1143,37 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { if (Width < CGF.LLVMPointerWidth) { // Zero or sign extend the pointer value based on whether the index is // signed or not. - const llvm::Type *IdxType = llvm::IntegerType::get(CGF.LLVMPointerWidth); + const llvm::Type *IdxType = + llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth); if (IdxExp->getType()->isSignedIntegerType()) Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); else Idx = Builder.CreateZExt(Idx, IdxType, "idx.ext"); } - - const QualType ElementType = PT->getPointeeType(); - // Handle interface types, which are not represented with a concrete - // type. + const QualType ElementType = PT ? PT->getPointeeType() : OPT->getPointeeType(); + // Handle interface types, which are not represented with a concrete type. if (const ObjCInterfaceType *OIT = dyn_cast<ObjCInterfaceType>(ElementType)) { - llvm::Value *InterfaceSize = + llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), CGF.getContext().getTypeSize(OIT) / 8); Idx = Builder.CreateMul(Idx, InterfaceSize); - const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); Value *Casted = Builder.CreateBitCast(Ptr, i8Ty); Value *Res = Builder.CreateGEP(Casted, Idx, "add.ptr"); return Builder.CreateBitCast(Res, Ptr->getType()); - } + } - // Explicitly handle GNU void* and function pointer arithmetic - // extensions. The GNU void* casts amount to no-ops since our void* - // type is i8*, but this is future proof. + // Explicitly handle GNU void* and function pointer arithmetic extensions. The + // GNU void* casts amount to no-ops since our void* type is i8*, but this is + // future proof. if (ElementType->isVoidType() || ElementType->isFunctionType()) { - const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); Value *Casted = Builder.CreateBitCast(Ptr, i8Ty); Value *Res = Builder.CreateGEP(Casted, Idx, "add.ptr"); return Builder.CreateBitCast(Res, Ptr->getType()); - } - - return Builder.CreateGEP(Ptr, Idx, "add.ptr"); + } + + return Builder.CreateInBoundsGEP(Ptr, Idx, "add.ptr"); } Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { @@ -1065,7 +1187,8 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub"); } - if (Ops.E->getLHS()->getType()->getAsPointerType()->isVariableArrayType()) { + if (Ops.E->getLHS()->getType()->isPointerType() && + Ops.E->getLHS()->getType()->getAs<PointerType>()->isVariableArrayType()) { // The amount of the addition needs to account for the VLA size for // ptr-int // The amount of the division needs to account for the VLA size for @@ -1074,7 +1197,7 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { } const QualType LHSType = Ops.E->getLHS()->getType(); - const QualType LHSElementType = LHSType->getAsPointerType()->getPointeeType(); + const QualType LHSElementType = LHSType->getPointeeType(); if (!isa<llvm::PointerType>(Ops.RHS->getType())) { // pointer - int Value *Idx = Ops.RHS; @@ -1082,7 +1205,8 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { if (Width < CGF.LLVMPointerWidth) { // Zero or sign extend the pointer value based on whether the index is // signed or not. - const llvm::Type *IdxType = llvm::IntegerType::get(CGF.LLVMPointerWidth); + const llvm::Type *IdxType = + llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth); if (Ops.E->getRHS()->getType()->isSignedIntegerType()) Idx = Builder.CreateSExt(Idx, IdxType, "idx.ext"); else @@ -1090,36 +1214,35 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { } Idx = Builder.CreateNeg(Idx, "sub.ptr.neg"); - // Handle interface types, which are not represented with a concrete - // type. - if (const ObjCInterfaceType *OIT = + // Handle interface types, which are not represented with a concrete type. + if (const ObjCInterfaceType *OIT = dyn_cast<ObjCInterfaceType>(LHSElementType)) { - llvm::Value *InterfaceSize = + llvm::Value *InterfaceSize = llvm::ConstantInt::get(Idx->getType(), CGF.getContext().getTypeSize(OIT) / 8); Idx = Builder.CreateMul(Idx, InterfaceSize); - const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); Value *LHSCasted = Builder.CreateBitCast(Ops.LHS, i8Ty); Value *Res = Builder.CreateGEP(LHSCasted, Idx, "add.ptr"); return Builder.CreateBitCast(Res, Ops.LHS->getType()); - } + } // Explicitly handle GNU void* and function pointer arithmetic - // extensions. The GNU void* casts amount to no-ops since our - // void* type is i8*, but this is future proof. + // extensions. The GNU void* casts amount to no-ops since our void* type is + // i8*, but this is future proof. if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) { - const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(VMContext); Value *LHSCasted = Builder.CreateBitCast(Ops.LHS, i8Ty); Value *Res = Builder.CreateGEP(LHSCasted, Idx, "sub.ptr"); return Builder.CreateBitCast(Res, Ops.LHS->getType()); - } - - return Builder.CreateGEP(Ops.LHS, Idx, "sub.ptr"); + } + + return Builder.CreateInBoundsGEP(Ops.LHS, Idx, "sub.ptr"); } else { // pointer - pointer Value *LHS = Ops.LHS; Value *RHS = Ops.RHS; - + uint64_t ElementSize; // Handle GCC extension for pointer arithmetic on void* and function pointer @@ -1129,28 +1252,21 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { } else { ElementSize = CGF.getContext().getTypeSize(LHSElementType) / 8; } - + const llvm::Type *ResultType = ConvertType(Ops.Ty); LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast"); RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub"); - + // Optimize out the shift for element size of 1. if (ElementSize == 1) return BytesBetween; - - // HACK: LLVM doesn't have an divide instruction that 'knows' there is no - // remainder. As such, we handle common power-of-two cases here to generate - // better code. See PR2247. - if (llvm::isPowerOf2_64(ElementSize)) { - Value *ShAmt = - llvm::ConstantInt::get(ResultType, llvm::Log2_64(ElementSize)); - return Builder.CreateAShr(BytesBetween, ShAmt, "sub.ptr.shr"); - } - - // Otherwise, do a full sdiv. + + // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since + // pointer difference in C is only defined in the case where both operands + // are pointing to elements of an array. Value *BytesPerElt = llvm::ConstantInt::get(ResultType, ElementSize); - return Builder.CreateSDiv(BytesBetween, BytesPerElt, "sub.ptr.div"); + return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div"); } } @@ -1160,7 +1276,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { Value *RHS = Ops.RHS; if (Ops.LHS->getType() != RHS->getType()) RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); - + return Builder.CreateShl(Ops.LHS, RHS, "shl"); } @@ -1170,7 +1286,7 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) { Value *RHS = Ops.RHS; if (Ops.LHS->getType() != RHS->getType()) RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); - + if (Ops.Ty->isUnsignedIntegerType()) return Builder.CreateLShr(Ops.LHS, RHS, "shr"); return Builder.CreateAShr(Ops.LHS, RHS, "shr"); @@ -1181,11 +1297,11 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, TestAndClearIgnoreResultAssign(); Value *Result; QualType LHSTy = E->getLHS()->getType(); - if (!LHSTy->isAnyComplexType() && !LHSTy->isVectorType()) { + if (!LHSTy->isAnyComplexType()) { Value *LHS = Visit(E->getLHS()); Value *RHS = Visit(E->getRHS()); - - if (LHS->getType()->isFloatingPoint()) { + + if (LHS->getType()->isFPOrFPVector()) { Result = Builder.CreateFCmp((llvm::CmpInst::Predicate)FCmpOpc, LHS, RHS, "cmp"); } else if (LHSTy->isSignedIntegerType()) { @@ -1196,29 +1312,19 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc, LHS, RHS, "cmp"); } - } else if (LHSTy->isVectorType()) { - Value *LHS = Visit(E->getLHS()); - Value *RHS = Visit(E->getRHS()); - - if (LHS->getType()->isFPOrFPVector()) { - Result = Builder.CreateVFCmp((llvm::CmpInst::Predicate)FCmpOpc, - LHS, RHS, "cmp"); - } else if (LHSTy->isUnsignedIntegerType()) { - Result = Builder.CreateVICmp((llvm::CmpInst::Predicate)UICmpOpc, - LHS, RHS, "cmp"); - } else { - // Signed integers and pointers. - Result = Builder.CreateVICmp((llvm::CmpInst::Predicate)SICmpOpc, - LHS, RHS, "cmp"); - } - return Result; + + // If this is a vector comparison, sign extend the result to the appropriate + // vector integer type and return it (don't convert to bool). + if (LHSTy->isVectorType()) + return Builder.CreateSExt(Result, ConvertType(E->getType()), "sext"); + } else { // Complex Comparison: can only be an equality comparison. CodeGenFunction::ComplexPairTy LHS = CGF.EmitComplexExpr(E->getLHS()); CodeGenFunction::ComplexPairTy RHS = CGF.EmitComplexExpr(E->getRHS()); - - QualType CETy = LHSTy->getAsComplexType()->getElementType(); - + + QualType CETy = LHSTy->getAs<ComplexType>()->getElementType(); + Value *ResultR, *ResultI; if (CETy->isRealFloatingType()) { ResultR = Builder.CreateFCmp((llvm::FCmpInst::Predicate)FCmpOpc, @@ -1233,7 +1339,7 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc, ResultI = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc, LHS.second, RHS.second, "cmp.i"); } - + if (E->getOpcode() == BinaryOperator::EQ) { Result = Builder.CreateAnd(ResultR, ResultI, "and.ri"); } else { @@ -1253,7 +1359,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { // improve codegen just a little. Value *RHS = Visit(E->getRHS()); LValue LHS = EmitLValue(E->getLHS()); - + // Store the value into the LHS. Bit-fields are handled specially // because the result is altered by the store, i.e., [C99 6.5.16p1] // 'An assignment expression has the value of the left operand after @@ -1281,12 +1387,12 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { // ZExt result to int. return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "land.ext"); } - + // 0 && RHS: If it is safe, just elide the RHS, and return 0. if (!CGF.ContainsLabel(E->getRHS())) return llvm::Constant::getNullValue(CGF.LLVMIntTy); } - + llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end"); llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("land.rhs"); @@ -1296,17 +1402,18 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { // Any edges into the ContBlock are now from an (indeterminate number of) // edges from this first condition. All of these values will be false. Start // setting up the PHI node in the Cont Block for this. - llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::Int1Ty, "", ContBlock); + llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), + "", ContBlock); PN->reserveOperandSpace(2); // Normal case, two inputs. for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock); PI != PE; ++PI) - PN->addIncoming(llvm::ConstantInt::getFalse(), *PI); - + PN->addIncoming(llvm::ConstantInt::getFalse(VMContext), *PI); + CGF.PushConditionalTempDestruction(); CGF.EmitBlock(RHSBlock); Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); CGF.PopConditionalTempDestruction(); - + // Reaquire the RHS block, as there may be subblocks inserted. RHSBlock = Builder.GetInsertBlock(); @@ -1314,7 +1421,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { // into the phi node for the edge with the value of RHSCond. CGF.EmitBlock(ContBlock); PN->addIncoming(RHSCond, RHSBlock); - + // ZExt result to int. return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext"); } @@ -1328,43 +1435,44 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { // ZExt result to int. return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "lor.ext"); } - + // 1 || RHS: If it is safe, just elide the RHS, and return 1. if (!CGF.ContainsLabel(E->getRHS())) return llvm::ConstantInt::get(CGF.LLVMIntTy, 1); } - + llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end"); llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("lor.rhs"); - + // Branch on the LHS first. If it is true, go to the success (cont) block. CGF.EmitBranchOnBoolExpr(E->getLHS(), ContBlock, RHSBlock); // Any edges into the ContBlock are now from an (indeterminate number of) // edges from this first condition. All of these values will be true. Start // setting up the PHI node in the Cont Block for this. - llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::Int1Ty, "", ContBlock); + llvm::PHINode *PN = llvm::PHINode::Create(llvm::Type::getInt1Ty(VMContext), + "", ContBlock); PN->reserveOperandSpace(2); // Normal case, two inputs. for (llvm::pred_iterator PI = pred_begin(ContBlock), PE = pred_end(ContBlock); PI != PE; ++PI) - PN->addIncoming(llvm::ConstantInt::getTrue(), *PI); + PN->addIncoming(llvm::ConstantInt::getTrue(VMContext), *PI); CGF.PushConditionalTempDestruction(); // Emit the RHS condition as a bool value. CGF.EmitBlock(RHSBlock); Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); - + CGF.PopConditionalTempDestruction(); - + // Reaquire the RHS block, as there may be subblocks inserted. RHSBlock = Builder.GetInsertBlock(); - + // Emit an unconditional branch from this block to ContBlock. Insert an entry // into the phi node for the edge with the value of RHSCond. CGF.EmitBlock(ContBlock); PN->addIncoming(RHSCond, RHSBlock); - + // ZExt result to int. return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext"); } @@ -1386,19 +1494,19 @@ Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) { static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E) { if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) return isCheapEnoughToEvaluateUnconditionally(PE->getSubExpr()); - + // TODO: Allow anything we can constant fold to an integer or fp constant. if (isa<IntegerLiteral>(E) || isa<CharacterLiteral>(E) || isa<FloatingLiteral>(E)) return true; - + // Non-volatile automatic variables too, to get "cond ? X : Y" where // X and Y are local variables. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) if (VD->hasLocalStorage() && !VD->getType().isVolatileQualified()) return true; - + return false; } @@ -1412,7 +1520,7 @@ VisitConditionalOperator(const ConditionalOperator *E) { Expr *Live = E->getLHS(), *Dead = E->getRHS(); if (Cond == -1) std::swap(Live, Dead); - + // If the dead side doesn't have labels we need, and if the Live side isn't // the gnu missing ?: extension (which we could handle, but don't bother // to), just emit the Live part. @@ -1420,8 +1528,8 @@ VisitConditionalOperator(const ConditionalOperator *E) { Live) // Live part isn't missing. return Visit(Live); } - - + + // If this is a really simple expression (like x ? 4 : 5), emit this as a // select instead of as control flow. We can only do this if it is cheap and // safe to evaluate the LHS and RHS unconditionally. @@ -1432,15 +1540,15 @@ VisitConditionalOperator(const ConditionalOperator *E) { llvm::Value *RHS = Visit(E->getRHS()); return Builder.CreateSelect(CondV, LHS, RHS, "cond"); } - - + + llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); Value *CondVal = 0; - // If we don't have the GNU missing condition extension, emit a branch on - // bool the normal way. + // If we don't have the GNU missing condition extension, emit a branch on bool + // the normal way. if (E->getLHS()) { // Otherwise, just use EmitBranchOnBoolExpr to get small and simple code for // the branch on bool. @@ -1450,7 +1558,7 @@ VisitConditionalOperator(const ConditionalOperator *E) { // convert it to bool the hard way. We do this explicitly because we need // the unconverted value for the missing middle value of the ?:. CondVal = CGF.EmitScalarExpr(E->getCond()); - + // In some cases, EmitScalarConversion will delete the "CondVal" expression // if there are no extra uses (an optimization). Inhibit this by making an // extra dead use, because we're going to add a use of CondVal later. We @@ -1458,7 +1566,7 @@ VisitConditionalOperator(const ConditionalOperator *E) { // away. This leaves dead code, but the ?: extension isn't common. new llvm::BitCastInst(CondVal, CondVal->getType(), "dummy?:holder", Builder.GetInsertBlock()); - + Value *CondBoolVal = CGF.EmitScalarConversion(CondVal, E->getCond()->getType(), CGF.getContext().BoolTy); @@ -1467,33 +1575,33 @@ VisitConditionalOperator(const ConditionalOperator *E) { CGF.PushConditionalTempDestruction(); CGF.EmitBlock(LHSBlock); - + // Handle the GNU extension for missing LHS. Value *LHS; if (E->getLHS()) LHS = Visit(E->getLHS()); else // Perform promotions, to handle cases like "short ?: int" LHS = EmitScalarConversion(CondVal, E->getCond()->getType(), E->getType()); - + CGF.PopConditionalTempDestruction(); LHSBlock = Builder.GetInsertBlock(); CGF.EmitBranch(ContBlock); - + CGF.PushConditionalTempDestruction(); CGF.EmitBlock(RHSBlock); - + Value *RHS = Visit(E->getRHS()); CGF.PopConditionalTempDestruction(); RHSBlock = Builder.GetInsertBlock(); CGF.EmitBranch(ContBlock); - + CGF.EmitBlock(ContBlock); - + if (!LHS || !RHS) { assert(E->getType()->isVoidType() && "Non-void value should have a value"); return 0; } - + // Create a PHI node for the real part. llvm::PHINode *PN = Builder.CreatePHI(LHS->getType(), "cond"); PN->reserveOperandSpace(2); @@ -1511,7 +1619,7 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); // If EmitVAArg fails, we fall back to the LLVM instruction. - if (!ArgPtr) + if (!ArgPtr) return Builder.CreateVAArg(ArgValue, ConvertType(VE->getType())); // FIXME Volatility. @@ -1526,12 +1634,12 @@ Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *BE) { // Entry Point into this File //===----------------------------------------------------------------------===// -/// EmitScalarExpr - Emit the computation of the specified expression of -/// scalar type, ignoring the result. +/// EmitScalarExpr - Emit the computation of the specified expression of scalar +/// type, ignoring the result. Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) { assert(E && !hasAggregateLLVMType(E->getType()) && "Invalid scalar expression to emit"); - + return ScalarExprEmitter(*this, IgnoreResultAssign) .Visit(const_cast<Expr*>(E)); } @@ -1545,9 +1653,9 @@ Value *CodeGenFunction::EmitScalarConversion(Value *Src, QualType SrcTy, return ScalarExprEmitter(*this).EmitScalarConversion(Src, SrcTy, DstTy); } -/// EmitComplexToScalarConversion - Emit a conversion from the specified -/// complex type to the specified destination type, where the destination -/// type is an LLVM scalar type. +/// EmitComplexToScalarConversion - Emit a conversion from the specified complex +/// type to the specified destination type, where the destination type is an +/// LLVM scalar type. Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy) { @@ -1560,38 +1668,40 @@ Value *CodeGenFunction::EmitComplexToScalarConversion(ComplexPairTy Src, Value *CodeGenFunction::EmitShuffleVector(Value* V1, Value *V2, ...) { assert(V1->getType() == V2->getType() && "Vector operands must be of the same type"); - unsigned NumElements = + unsigned NumElements = cast<llvm::VectorType>(V1->getType())->getNumElements(); - + va_list va; va_start(va, V2); - + llvm::SmallVector<llvm::Constant*, 16> Args; for (unsigned i = 0; i < NumElements; i++) { int n = va_arg(va, int); - assert(n >= 0 && n < (int)NumElements * 2 && + assert(n >= 0 && n < (int)NumElements * 2 && "Vector shuffle index out of bounds!"); - Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, n)); + Args.push_back(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), n)); } - + const char *Name = va_arg(va, const char *); va_end(va); - + llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements); - + return Builder.CreateShuffleVector(V1, V2, Mask, Name); } -llvm::Value *CodeGenFunction::EmitVector(llvm::Value * const *Vals, +llvm::Value *CodeGenFunction::EmitVector(llvm::Value * const *Vals, unsigned NumVals, bool isSplat) { llvm::Value *Vec = llvm::UndefValue::get(llvm::VectorType::get(Vals[0]->getType(), NumVals)); - + for (unsigned i = 0, e = NumVals; i != e; ++i) { llvm::Value *Val = isSplat ? Vals[0] : Vals[i]; - llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::Int32Ty, i); + llvm::Value *Idx = llvm::ConstantInt::get( + llvm::Type::getInt32Ty(VMContext), i); Vec = Builder.CreateInsertElement(Vec, Val, Idx, "tmp"); } - - return Vec; + + return Vec; } diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 33cb5bca3869b..cadba328bf12a 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -24,7 +24,7 @@ using namespace clang; using namespace CodeGen; /// Emits an instance of NSConstantString representing the object. -llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) +llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) { llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(E); // FIXME: This bitcast should just be made an invariant on the Runtime. @@ -50,7 +50,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { // Only the lookup mechanism and first two arguments of the method // implementation vary between runtimes. We can get the receiver and // arguments in generic code. - + CGObjCRuntime &Runtime = CGM.getObjCRuntime(); const Expr *ReceiverExpr = E->getReceiver(); bool isSuperMessage = false; @@ -70,7 +70,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { } else { Receiver = Runtime.GetClass(Builder, OID); } - + isClassMessage = true; } else if (isa<ObjCSuperExpr>(E->getReceiver())) { isSuperMessage = true; @@ -81,7 +81,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { CallArgList Args; EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end()); - + if (isSuperMessage) { // super is only valid in an Objective-C method const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); @@ -92,9 +92,11 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { isCategoryImpl, Receiver, isClassMessage, - Args); + Args, + E->getMethodDecl()); } - return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), + + return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), Receiver, isClassMessage, Args, E->getMethodDecl()); } @@ -110,7 +112,7 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(OMD); CGM.SetInternalFunctionAttributes(OMD, Fn, FI); - Args.push_back(std::make_pair(OMD->getSelfDecl(), + Args.push_back(std::make_pair(OMD->getSelfDecl(), OMD->getSelfDecl()->getType())); Args.push_back(std::make_pair(OMD->getCmdDecl(), OMD->getCmdDecl()->getType())); @@ -123,10 +125,10 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, } /// Generate an Objective-C method. An Objective-C method is a C function with -/// its pointer, name, and types registered in the class struture. +/// its pointer, name, and types registered in the class struture. void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { // Check if we should generate debug info for this method. - if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>()) + if (CGM.getDebugInfo() && !OMD->hasAttr<NoDebugAttr>()) DebugInfo = CGM.getDebugInfo(); StartObjCMethod(OMD, OMD->getClassInterface()); EmitStmt(OMD->getBody()); @@ -159,9 +161,9 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic) && (PD->getSetterKind() == ObjCPropertyDecl::Copy || PD->getSetterKind() == ObjCPropertyDecl::Retain)) { - llvm::Value *GetPropertyFn = + llvm::Value *GetPropertyFn = CGM.getObjCRuntime().GetPropertyGetFunction(); - + if (!GetPropertyFn) { CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); FinishFunction(); @@ -175,7 +177,7 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, ValueDecl *Cmd = OMD->getCmdDecl(); llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); QualType IdTy = getContext().getObjCIdType(); - llvm::Value *SelfAsId = + llvm::Value *SelfAsId = Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); llvm::Value *True = @@ -187,24 +189,23 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP, Args.push_back(std::make_pair(RValue::get(True), getContext().BoolTy)); // FIXME: We shouldn't need to get the function info here, the // runtime already should have computed it to build the function. - RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args), + RValue RV = EmitCall(Types.getFunctionInfo(PD->getType(), Args), GetPropertyFn, Args); // We need to fix the type here. Ivars with copy & retain are // always objects so we don't need to worry about complex or // aggregates. - RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), + RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), Types.ConvertType(PD->getType()))); EmitReturnOfRValue(RV, PD->getType()); } else { LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); if (hasAggregateLLVMType(Ivar->getType())) { EmitAggregateCopy(ReturnValue, LV.getAddress(), Ivar->getType()); - } - else { + } else { CodeGenTypes &Types = CGM.getTypes(); RValue RV = EmitLoadOfLValue(LV, Ivar->getType()); RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(), - Types.ConvertType(PD->getType()))); + Types.ConvertType(PD->getType()))); EmitReturnOfRValue(RV, PD->getType()); } } @@ -227,7 +228,7 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, StartObjCMethod(OMD, IMP->getClassInterface()); bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy; - bool IsAtomic = + bool IsAtomic = !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic); // Determine if we should use an objc_setProperty call for @@ -237,16 +238,16 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, if (IsCopy || (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly && PD->getSetterKind() == ObjCPropertyDecl::Retain)) { - llvm::Value *SetPropertyFn = + llvm::Value *SetPropertyFn = CGM.getObjCRuntime().GetPropertySetFunction(); - + if (!SetPropertyFn) { CGM.ErrorUnsupported(PID, "Obj-C getter requiring atomic copy"); FinishFunction(); return; } - - // Emit objc_setProperty((id) self, _cmd, offset, arg, + + // Emit objc_setProperty((id) self, _cmd, offset, arg, // <is-atomic>, <is-copy>). // FIXME: Can't this be simpler? This might even be worse than the // corresponding gcc code. @@ -254,11 +255,11 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, ValueDecl *Cmd = OMD->getCmdDecl(); llvm::Value *CmdVal = Builder.CreateLoad(LocalDeclMap[Cmd], "cmd"); QualType IdTy = getContext().getObjCIdType(); - llvm::Value *SelfAsId = + llvm::Value *SelfAsId = Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy)); llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar); llvm::Value *Arg = LocalDeclMap[*OMD->param_begin()]; - llvm::Value *ArgAsId = + llvm::Value *ArgAsId = Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"), Types.ConvertType(IdTy)); llvm::Value *True = @@ -270,13 +271,13 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, Args.push_back(std::make_pair(RValue::get(CmdVal), Cmd->getType())); Args.push_back(std::make_pair(RValue::get(Offset), getContext().LongTy)); Args.push_back(std::make_pair(RValue::get(ArgAsId), IdTy)); - Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), + Args.push_back(std::make_pair(RValue::get(IsAtomic ? True : False), getContext().BoolTy)); - Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), + Args.push_back(std::make_pair(RValue::get(IsCopy ? True : False), getContext().BoolTy)); // FIXME: We shouldn't need to get the function info here, the runtime // already should have computed it to build the function. - EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args), + EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args), SetPropertyFn, Args); } else { SourceLocation Loc = PD->getLocation(); @@ -305,18 +306,18 @@ llvm::Value *CodeGenFunction::LoadObjCSelf() { QualType CodeGenFunction::TypeOfSelfObject() { const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); ImplicitParamDecl *selfDecl = OMD->getSelfDecl(); - const PointerType *PTy = - cast<PointerType>(getContext().getCanonicalType(selfDecl->getType())); + const ObjCObjectPointerType *PTy = cast<ObjCObjectPointerType>( + getContext().getCanonicalType(selfDecl->getType())); return PTy->getPointeeType(); } -RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, +RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, const Selector &S) { llvm::Value *Receiver = LoadObjCSelf(); const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl); bool isClassMessage = OMD->isClassMethod(); bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); - return CGM.getObjCRuntime().GenerateMessageSendSuper(*this, + return CGM.getObjCRuntime().GenerateMessageSendSuper(*this, Exp->getType(), S, OMD->getClassInterface(), @@ -324,36 +325,36 @@ RValue CodeGenFunction::EmitObjCSuperPropertyGet(const Expr *Exp, Receiver, isClassMessage, CallArgList()); - + } RValue CodeGenFunction::EmitObjCPropertyGet(const Expr *Exp) { + Exp = Exp->IgnoreParens(); // FIXME: Split it into two separate routines. if (const ObjCPropertyRefExpr *E = dyn_cast<ObjCPropertyRefExpr>(Exp)) { Selector S = E->getProperty()->getGetterName(); if (isa<ObjCSuperExpr>(E->getBase())) return EmitObjCSuperPropertyGet(E, S); return CGM.getObjCRuntime(). - GenerateMessageSend(*this, Exp->getType(), S, - EmitScalarExpr(E->getBase()), + GenerateMessageSend(*this, Exp->getType(), S, + EmitScalarExpr(E->getBase()), false, CallArgList()); - } - else { - const ObjCKVCRefExpr *KE = cast<ObjCKVCRefExpr>(Exp); + } else { + const ObjCImplicitSetterGetterRefExpr *KE = + cast<ObjCImplicitSetterGetterRefExpr>(Exp); Selector S = KE->getGetterMethod()->getSelector(); llvm::Value *Receiver; - if (KE->getClassProp()) { - const ObjCInterfaceDecl *OID = KE->getClassProp(); + if (KE->getInterfaceDecl()) { + const ObjCInterfaceDecl *OID = KE->getInterfaceDecl(); Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); - } - else if (isa<ObjCSuperExpr>(KE->getBase())) + } else if (isa<ObjCSuperExpr>(KE->getBase())) return EmitObjCSuperPropertyGet(KE, S); - else + else Receiver = EmitScalarExpr(KE->getBase()); return CGM.getObjCRuntime(). - GenerateMessageSend(*this, Exp->getType(), S, - Receiver, - KE->getClassProp() != 0, CallArgList()); + GenerateMessageSend(*this, Exp->getType(), S, + Receiver, + KE->getInterfaceDecl() != 0, CallArgList()); } } @@ -366,7 +367,7 @@ void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp, bool isClassMessage = OMD->isClassMethod(); bool isCategoryImpl = isa<ObjCCategoryImplDecl>(OMD->getDeclContext()); Args.push_back(std::make_pair(Src, Exp->getType())); - CGM.getObjCRuntime().GenerateMessageSendSuper(*this, + CGM.getObjCRuntime().GenerateMessageSendSuper(*this, Exp->getType(), S, OMD->getClassInterface(), @@ -385,42 +386,39 @@ void CodeGenFunction::EmitObjCPropertySet(const Expr *Exp, if (isa<ObjCSuperExpr>(E->getBase())) { EmitObjCSuperPropertySet(E, S, Src); return; - } + } CallArgList Args; Args.push_back(std::make_pair(Src, E->getType())); - CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, - EmitScalarExpr(E->getBase()), + CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, + EmitScalarExpr(E->getBase()), false, Args); - } - else if (const ObjCKVCRefExpr *E = dyn_cast<ObjCKVCRefExpr>(Exp)) { + } else if (const ObjCImplicitSetterGetterRefExpr *E = + dyn_cast<ObjCImplicitSetterGetterRefExpr>(Exp)) { Selector S = E->getSetterMethod()->getSelector(); CallArgList Args; llvm::Value *Receiver; - if (E->getClassProp()) { - const ObjCInterfaceDecl *OID = E->getClassProp(); + if (E->getInterfaceDecl()) { + const ObjCInterfaceDecl *OID = E->getInterfaceDecl(); Receiver = CGM.getObjCRuntime().GetClass(Builder, OID); - } - else if (isa<ObjCSuperExpr>(E->getBase())) { + } else if (isa<ObjCSuperExpr>(E->getBase())) { EmitObjCSuperPropertySet(E, S, Src); return; - } - else + } else Receiver = EmitScalarExpr(E->getBase()); Args.push_back(std::make_pair(Src, E->getType())); - CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, - Receiver, - E->getClassProp() != 0, Args); - } - else + CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, + Receiver, + E->getInterfaceDecl() != 0, Args); + } else assert (0 && "bad expression node in EmitObjCPropertySet"); } void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ - llvm::Constant *EnumerationMutationFn = + llvm::Constant *EnumerationMutationFn = CGM.getObjCRuntime().EnumerationMutationFunction(); llvm::Value *DeclAddress; QualType ElementTy; - + if (!EnumerationMutationFn) { CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime"); return; @@ -431,62 +429,62 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ assert(HaveInsertPoint() && "DeclStmt destroyed insert point!"); const Decl* D = SD->getSingleDecl(); ElementTy = cast<ValueDecl>(D)->getType(); - DeclAddress = LocalDeclMap[D]; + DeclAddress = LocalDeclMap[D]; } else { ElementTy = cast<Expr>(S.getElement())->getType(); DeclAddress = 0; } - + // Fast enumeration state. QualType StateTy = getContext().getObjCFastEnumerationStateType(); - llvm::AllocaInst *StatePtr = CreateTempAlloca(ConvertType(StateTy), + llvm::AllocaInst *StatePtr = CreateTempAlloca(ConvertType(StateTy), "state.ptr"); - StatePtr->setAlignment(getContext().getTypeAlign(StateTy) >> 3); + StatePtr->setAlignment(getContext().getTypeAlign(StateTy) >> 3); EmitMemSetToZero(StatePtr, StateTy); - + // Number of elements in the items array. static const unsigned NumItems = 16; - + // Get selector llvm::SmallVector<IdentifierInfo*, 3> II; II.push_back(&CGM.getContext().Idents.get("countByEnumeratingWithState")); II.push_back(&CGM.getContext().Idents.get("objects")); II.push_back(&CGM.getContext().Idents.get("count")); - Selector FastEnumSel = CGM.getContext().Selectors.getSelector(II.size(), + Selector FastEnumSel = CGM.getContext().Selectors.getSelector(II.size(), &II[0]); QualType ItemsTy = getContext().getConstantArrayType(getContext().getObjCIdType(), - llvm::APInt(32, NumItems), + llvm::APInt(32, NumItems), ArrayType::Normal, 0); llvm::Value *ItemsPtr = CreateTempAlloca(ConvertType(ItemsTy), "items.ptr"); - + llvm::Value *Collection = EmitScalarExpr(S.getCollection()); - + CallArgList Args; - Args.push_back(std::make_pair(RValue::get(StatePtr), + Args.push_back(std::make_pair(RValue::get(StatePtr), getContext().getPointerType(StateTy))); - - Args.push_back(std::make_pair(RValue::get(ItemsPtr), + + Args.push_back(std::make_pair(RValue::get(ItemsPtr), getContext().getPointerType(ItemsTy))); - + const llvm::Type *UnsignedLongLTy = ConvertType(getContext().UnsignedLongTy); llvm::Constant *Count = llvm::ConstantInt::get(UnsignedLongLTy, NumItems); - Args.push_back(std::make_pair(RValue::get(Count), + Args.push_back(std::make_pair(RValue::get(Count), getContext().UnsignedLongTy)); - - RValue CountRV = - CGM.getObjCRuntime().GenerateMessageSend(*this, + + RValue CountRV = + CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().UnsignedLongTy, FastEnumSel, Collection, false, Args); llvm::Value *LimitPtr = CreateTempAlloca(UnsignedLongLTy, "limit.ptr"); Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); - + llvm::BasicBlock *NoElements = createBasicBlock("noelements"); llvm::BasicBlock *SetStartMutations = createBasicBlock("setstartmutations"); - + llvm::Value *Limit = Builder.CreateLoad(LimitPtr); llvm::Value *Zero = llvm::Constant::getNullValue(UnsignedLongLTy); @@ -494,60 +492,60 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ Builder.CreateCondBr(IsZero, NoElements, SetStartMutations); EmitBlock(SetStartMutations); - - llvm::Value *StartMutationsPtr = + + llvm::Value *StartMutationsPtr = CreateTempAlloca(UnsignedLongLTy); - - llvm::Value *StateMutationsPtrPtr = + + llvm::Value *StateMutationsPtrPtr = Builder.CreateStructGEP(StatePtr, 2, "mutationsptr.ptr"); - llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, + llvm::Value *StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); - - llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr, + + llvm::Value *StateMutations = Builder.CreateLoad(StateMutationsPtr, "mutations"); - + Builder.CreateStore(StateMutations, StartMutationsPtr); - + llvm::BasicBlock *LoopStart = createBasicBlock("loopstart"); EmitBlock(LoopStart); llvm::Value *CounterPtr = CreateTempAlloca(UnsignedLongLTy, "counter.ptr"); Builder.CreateStore(Zero, CounterPtr); - - llvm::BasicBlock *LoopBody = createBasicBlock("loopbody"); + + llvm::BasicBlock *LoopBody = createBasicBlock("loopbody"); EmitBlock(LoopBody); StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr"); StateMutations = Builder.CreateLoad(StateMutationsPtr, "statemutations"); - llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr, + llvm::Value *StartMutations = Builder.CreateLoad(StartMutationsPtr, "mutations"); - llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations, + llvm::Value *MutationsEqual = Builder.CreateICmpEQ(StateMutations, StartMutations, "tobool"); - - + + llvm::BasicBlock *WasMutated = createBasicBlock("wasmutated"); llvm::BasicBlock *WasNotMutated = createBasicBlock("wasnotmutated"); - + Builder.CreateCondBr(MutationsEqual, WasNotMutated, WasMutated); - + EmitBlock(WasMutated); llvm::Value *V = - Builder.CreateBitCast(Collection, + Builder.CreateBitCast(Collection, ConvertType(getContext().getObjCIdType()), "tmp"); CallArgList Args2; - Args2.push_back(std::make_pair(RValue::get(V), + Args2.push_back(std::make_pair(RValue::get(V), getContext().getObjCIdType())); // FIXME: We shouldn't need to get the function info here, the runtime already // should have computed it to build the function. - EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2), + EmitCall(CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args2), EnumerationMutationFn, Args2); - + EmitBlock(WasNotMutated); - - llvm::Value *StateItemsPtr = + + llvm::Value *StateItemsPtr = Builder.CreateStructGEP(StatePtr, 1, "stateitems.ptr"); llvm::Value *Counter = Builder.CreateLoad(CounterPtr, "counter"); @@ -555,39 +553,39 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ llvm::Value *EnumStateItems = Builder.CreateLoad(StateItemsPtr, "stateitems"); - llvm::Value *CurrentItemPtr = + llvm::Value *CurrentItemPtr = Builder.CreateGEP(EnumStateItems, Counter, "currentitem.ptr"); - + llvm::Value *CurrentItem = Builder.CreateLoad(CurrentItemPtr, "currentitem"); - + // Cast the item to the right type. CurrentItem = Builder.CreateBitCast(CurrentItem, ConvertType(ElementTy), "tmp"); - + if (!DeclAddress) { LValue LV = EmitLValue(cast<Expr>(S.getElement())); - + // Set the value to null. Builder.CreateStore(CurrentItem, LV.getAddress()); } else Builder.CreateStore(CurrentItem, DeclAddress); - + // Increment the counter. - Counter = Builder.CreateAdd(Counter, + Counter = Builder.CreateAdd(Counter, llvm::ConstantInt::get(UnsignedLongLTy, 1)); Builder.CreateStore(Counter, CounterPtr); - + llvm::BasicBlock *LoopEnd = createBasicBlock("loopend"); llvm::BasicBlock *AfterBody = createBasicBlock("afterbody"); - + BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); EmitStmt(S.getBody()); - + BreakContinueStack.pop_back(); - + EmitBlock(AfterBody); - + llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore"); Counter = Builder.CreateLoad(CounterPtr); @@ -597,18 +595,18 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // Fetch more elements. EmitBlock(FetchMore); - - CountRV = - CGM.getObjCRuntime().GenerateMessageSend(*this, + + CountRV = + CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().UnsignedLongTy, - FastEnumSel, + FastEnumSel, Collection, false, Args); Builder.CreateStore(CountRV.getScalarVal(), LimitPtr); Limit = Builder.CreateLoad(LimitPtr); - + IsZero = Builder.CreateICmpEQ(Limit, Zero, "iszero"); Builder.CreateCondBr(IsZero, NoElements, LoopStart); - + // No more elements. EmitBlock(NoElements); @@ -616,7 +614,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // If the element was not a declaration, set it to be null. LValue LV = EmitLValue(cast<Expr>(S.getElement())); - + // Set the value to null. Builder.CreateStore(llvm::Constant::getNullValue(ConvertType(ElementTy)), LV.getAddress()); @@ -625,19 +623,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ EmitBlock(LoopEnd); } -void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) -{ +void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) { CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); } -void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) -{ +void CodeGenFunction::EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S) { CGM.getObjCRuntime().EmitThrowStmt(*this, S); } void CodeGenFunction::EmitObjCAtSynchronizedStmt( - const ObjCAtSynchronizedStmt &S) -{ + const ObjCAtSynchronizedStmt &S) { CGM.getObjCRuntime().EmitTryOrSynchronizedStmt(*this, S); } diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 6554da9cf98c9..f348bfffcb869 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -43,6 +43,7 @@ using llvm::dyn_cast; static const int RuntimeVersion = 8; static const int NonFragileRuntimeVersion = 9; static const int ProtocolVersion = 2; +static const int NonFragileProtocolVersion = 3; namespace { class CGObjCGNU : public CodeGen::CGObjCRuntime { @@ -50,9 +51,11 @@ private: CodeGen::CodeGenModule &CGM; llvm::Module &TheModule; const llvm::PointerType *SelectorTy; + const llvm::IntegerType *Int8Ty; const llvm::PointerType *PtrToInt8Ty; const llvm::FunctionType *IMPTy; const llvm::PointerType *IdTy; + QualType ASTIdTy; const llvm::IntegerType *IntTy; const llvm::PointerType *PtrTy; const llvm::IntegerType *LongTy; @@ -70,6 +73,7 @@ private: // Some zeros used for GEPs in lots of places. llvm::Constant *Zeros[2]; llvm::Constant *NULLPtr; + llvm::LLVMContext &VMContext; private: llvm::Constant *GenerateIvarList( const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, @@ -77,12 +81,19 @@ private: const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets); llvm::Constant *GenerateMethodList(const std::string &ClassName, const std::string &CategoryName, - const llvm::SmallVectorImpl<Selector> &MethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, + const llvm::SmallVectorImpl<Selector> &MethodSels, + const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, bool isClassMethodList); llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName); + llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID, + llvm::SmallVectorImpl<Selector> &InstanceMethodSels, + llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes); llvm::Constant *GenerateProtocolList( const llvm::SmallVectorImpl<std::string> &Protocols); + // To ensure that all protocols are seen by the runtime, we add a category on + // a class defined in the runtime, declaring no methods, but adopting the + // protocols. + void GenerateProtocolHolderCategory(void); llvm::Constant *GenerateClassStructure( llvm::Constant *MetaClass, llvm::Constant *SuperClass, @@ -92,12 +103,16 @@ private: llvm::Constant *InstanceSize, llvm::Constant *IVars, llvm::Constant *Methods, - llvm::Constant *Protocols); + llvm::Constant *Protocols, + llvm::Constant *IvarOffsets, + llvm::Constant *Properties); llvm::Constant *GenerateProtocolMethodList( const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames, const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes); llvm::Constant *MakeConstantString(const std::string &Str, const std::string &Name=""); + llvm::Constant *ExportUniqueString(const std::string &Str, const std::string + prefix); llvm::Constant *MakeGlobal(const llvm::StructType *Ty, std::vector<llvm::Constant*> &V, const std::string &Name=""); llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty, @@ -108,7 +123,7 @@ private: public: CGObjCGNU(CodeGen::CodeGenModule &cgm); virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *); - virtual CodeGen::RValue + virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -116,7 +131,7 @@ public: bool IsClassMessage, const CallArgList &CallArgs, const ObjCMethodDecl *Method); - virtual CodeGen::RValue + virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -124,14 +139,15 @@ public: bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs); + const CallArgList &CallArgs, + const ObjCMethodDecl *Method); virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *OID); virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method); - - virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, + + virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD); virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); @@ -139,11 +155,10 @@ public: const ObjCProtocolDecl *PD); virtual void GenerateProtocol(const ObjCProtocolDecl *PD); virtual llvm::Function *ModuleInitFunction(); - virtual void MergeMetadataGlobals(std::vector<llvm::Constant*> &UsedArray); virtual llvm::Function *GetPropertyGetFunction(); virtual llvm::Function *GetPropertySetFunction(); - virtual llvm::Function *EnumerationMutationFunction(); - + virtual llvm::Constant *EnumerationMutationFunction(); + virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, @@ -155,9 +170,14 @@ public: virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dest); + llvm::Value *src, llvm::Value *dest, + llvm::Value *ivarOffset); virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); + virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, + llvm::Value *DestPtr, + llvm::Value *SrcPtr, + QualType Ty); virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, @@ -173,18 +193,19 @@ public: /// Emits a reference to a dummy variable which is emitted with each class. /// This ensures that a linker error will be generated when trying to link /// together modules where a referenced class is not defined. -void CGObjCGNU::EmitClassRef(const std::string &className){ +void CGObjCGNU::EmitClassRef(const std::string &className) { std::string symbolRef = "__objc_class_ref_" + className; // Don't emit two copies of the same symbol - if (TheModule.getGlobalVariable(symbolRef)) return; + if (TheModule.getGlobalVariable(symbolRef)) + return; std::string symbolName = "__objc_class_name_" + className; llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName); if (!ClassSymbol) { - ClassSymbol = new llvm::GlobalVariable(LongTy, false, - llvm::GlobalValue::ExternalLinkage, 0, symbolName, &TheModule); + ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false, + llvm::GlobalValue::ExternalLinkage, 0, symbolName); } - new llvm::GlobalVariable(ClassSymbol->getType(), true, - llvm::GlobalValue::CommonLinkage, ClassSymbol, symbolRef, &TheModule); + new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true, + llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef); } static std::string SymbolNameForClass(const std::string &ClassName) { @@ -200,36 +221,37 @@ static std::string SymbolNameForMethod(const std::string &ClassName, const CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0), - MetaClassPtrAlias(0) { + MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) { IntTy = cast<llvm::IntegerType>( CGM.getTypes().ConvertType(CGM.getContext().IntTy)); LongTy = cast<llvm::IntegerType>( CGM.getTypes().ConvertType(CGM.getContext().LongTy)); - + + Int8Ty = llvm::Type::getInt8Ty(VMContext); + // C string type. Used in lots of places. + PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); + Zeros[0] = llvm::ConstantInt::get(LongTy, 0); Zeros[1] = Zeros[0]; - NULLPtr = llvm::ConstantPointerNull::get( - llvm::PointerType::getUnqual(llvm::Type::Int8Ty)); - // C string type. Used in lots of places. - PtrToInt8Ty = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty); // Get the selector Type. SelectorTy = cast<llvm::PointerType>( CGM.getTypes().ConvertType(CGM.getContext().getObjCSelType())); PtrToIntTy = llvm::PointerType::getUnqual(IntTy); PtrTy = PtrToInt8Ty; - + // Object type - IdTy = cast<llvm::PointerType>( - CGM.getTypes().ConvertType(CGM.getContext().getObjCIdType())); - + ASTIdTy = CGM.getContext().getObjCIdType(); + IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); + // IMP type std::vector<const llvm::Type*> IMPArgs; IMPArgs.push_back(IdTy); IMPArgs.push_back(SelectorTy); IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true); } + // This has to perform the lookup every time, since posing and related // techniques can modify the name -> class mapping. llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder, @@ -251,10 +273,10 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) { llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()]; if (US == 0) US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy), - llvm::GlobalValue::InternalLinkage, - ".objc_untyped_selector_alias", + llvm::GlobalValue::PrivateLinkage, + ".objc_untyped_selector_alias"+Sel.getAsString(), NULL, &TheModule); - + return Builder.CreateLoad(US); } @@ -269,15 +291,14 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl SelTypes); // If it's already cached, return it. - if (TypedSelectors[Selector]) - { - return Builder.CreateLoad(TypedSelectors[Selector]); + if (TypedSelectors[Selector]) { + return Builder.CreateLoad(TypedSelectors[Selector]); } // If it isn't, cache it. llvm::GlobalAlias *Sel = new llvm::GlobalAlias( llvm::PointerType::getUnqual(SelectorTy), - llvm::GlobalValue::InternalLinkage, SelName, + llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName, NULL, &TheModule); TypedSelectors[Selector] = Sel; @@ -286,23 +307,33 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str, const std::string &Name) { - llvm::Constant * ConstStr = llvm::ConstantArray::get(Str); - ConstStr = new llvm::GlobalVariable(ConstStr->getType(), true, - llvm::GlobalValue::InternalLinkage, - ConstStr, Name, &TheModule); + llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str()); return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); } +llvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str, + const std::string prefix) { + std::string name = prefix + Str; + llvm::Constant *ConstStr = TheModule.getGlobalVariable(name); + if (!ConstStr) { + llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true); + ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true, + llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str); + } + return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); +} + llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty, std::vector<llvm::Constant*> &V, const std::string &Name) { llvm::Constant *C = llvm::ConstantStruct::get(Ty, V); - return new llvm::GlobalVariable(Ty, false, - llvm::GlobalValue::InternalLinkage, C, Name, &TheModule); + return new llvm::GlobalVariable(TheModule, Ty, false, + llvm::GlobalValue::InternalLinkage, C, Name); } + llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty, std::vector<llvm::Constant*> &V, const std::string &Name) { llvm::Constant *C = llvm::ConstantArray::get(Ty, V); - return new llvm::GlobalVariable(Ty, false, - llvm::GlobalValue::InternalLinkage, C, Name, &TheModule); + return new llvm::GlobalVariable(TheModule, Ty, false, + llvm::GlobalValue::InternalLinkage, C, Name); } /// Generate an NSConstantString object. @@ -310,14 +341,14 @@ llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty, //an OpenStep implementation, this should let them select their own class for //constant strings. llvm::Constant *CGObjCGNU::GenerateConstantString(const ObjCStringLiteral *SL) { - std::string Str(SL->getString()->getStrData(), + std::string Str(SL->getString()->getStrData(), SL->getString()->getByteLength()); std::vector<llvm::Constant*> Ivars; Ivars.push_back(NULLPtr); Ivars.push_back(MakeConstantString(Str)); Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size())); llvm::Constant *ObjCStr = MakeGlobal( - llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), + llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), Ivars, ".objc_str"); ConstantStrings.push_back( llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty)); @@ -335,21 +366,23 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs) { + const CallArgList &CallArgs, + const ObjCMethodDecl *Method) { llvm::Value *cmd = GetSelector(CGF.Builder, Sel); CallArgList ActualArgs; ActualArgs.push_back( - std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), - CGF.getContext().getObjCIdType())); + std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), + ASTIdTy)); ActualArgs.push_back(std::make_pair(RValue::get(cmd), CGF.getContext().getObjCSelType())); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); CodeGenTypes &Types = CGM.getTypes(); const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs); - const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, false); + const llvm::FunctionType *impType = + Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); llvm::Value *ReceiverClass = 0; if (isCategoryImpl) { @@ -368,8 +401,8 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, } else { // Set up global aliases for the metaclass or class pointer if they do not // already exist. These will are forward-references which will be set to - // pointers to the class and metaclass structure created for the runtime load - // function. To send a message to super, we look up the value of the + // pointers to the class and metaclass structure created for the runtime + // load function. To send a message to super, we look up the value of the // super_class pointer from either the class or metaclass structure. if (IsClassMessage) { if (!MetaClassPtrAlias) { @@ -388,15 +421,16 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, } } // Cast the pointer to a simplified version of the class structure - ReceiverClass = CGF.Builder.CreateBitCast(ReceiverClass, - llvm::PointerType::getUnqual(llvm::StructType::get(IdTy, IdTy, NULL))); + ReceiverClass = CGF.Builder.CreateBitCast(ReceiverClass, + llvm::PointerType::getUnqual( + llvm::StructType::get(VMContext, IdTy, IdTy, NULL))); // Get the superclass pointer ReceiverClass = CGF.Builder.CreateStructGEP(ReceiverClass, 1); // Load the superclass pointer ReceiverClass = CGF.Builder.CreateLoad(ReceiverClass); // Construct the structure used to look up the IMP - llvm::StructType *ObjCSuperTy = llvm::StructType::get(Receiver->getType(), - IdTy, NULL); + llvm::StructType *ObjCSuperTy = llvm::StructType::get(VMContext, + Receiver->getType(), IdTy, NULL); llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy); CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0)); @@ -407,7 +441,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, std::vector<const llvm::Type*> Params; Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy)); Params.push_back(SelectorTy); - llvm::Constant *lookupFunction = + llvm::Constant *lookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( llvm::PointerType::getUnqual(impType), Params, true), "objc_msg_lookup_super"); @@ -419,7 +453,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, return CGF.EmitCall(FnInfo, imp, ActualArgs); } -/// Generate code for a message send expression. +/// Generate code for a message send expression. CodeGen::RValue CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, @@ -428,32 +462,38 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, bool IsClassMessage, const CallArgList &CallArgs, const ObjCMethodDecl *Method) { + CGBuilderTy &Builder = CGF.Builder; + IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); llvm::Value *cmd; if (Method) - cmd = GetSelector(CGF.Builder, Method); + cmd = GetSelector(Builder, Method); else - cmd = GetSelector(CGF.Builder, Sel); + cmd = GetSelector(Builder, Sel); CallArgList ActualArgs; + Receiver = Builder.CreateBitCast(Receiver, IdTy); ActualArgs.push_back( - std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), - CGF.getContext().getObjCIdType())); + std::make_pair(RValue::get(Receiver), ASTIdTy)); ActualArgs.push_back(std::make_pair(RValue::get(cmd), CGF.getContext().getObjCSelType())); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); CodeGenTypes &Types = CGM.getTypes(); const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs); - const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, false); + const llvm::FunctionType *impType = + Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); llvm::Value *imp; - std::vector<const llvm::Type*> Params; - Params.push_back(Receiver->getType()); - Params.push_back(SelectorTy); // For sender-aware dispatch, we pass the sender as the third argument to a // lookup function. When sending messages from C code, the sender is nil. - // objc_msg_lookup_sender(id receiver, SEL selector, id sender); - if (CGM.getContext().getLangOptions().ObjCSenderDispatch) { + // objc_msg_lookup_sender(id *receiver, SEL selector, id sender); + if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { + + std::vector<const llvm::Type*> Params; + llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType()); + Builder.CreateStore(Receiver, ReceiverPtr); + Params.push_back(ReceiverPtr->getType()); + Params.push_back(SelectorTy); llvm::Value *self; if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) { @@ -461,34 +501,55 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, } else { self = llvm::ConstantPointerNull::get(IdTy); } + Params.push_back(self->getType()); - llvm::Constant *lookupFunction = + + // The lookup function returns a slot, which can be safely cached. + llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy, + IntTy, llvm::PointerType::getUnqual(impType), NULL); + llvm::Constant *lookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( - llvm::PointerType::getUnqual(impType), Params, true), + llvm::PointerType::getUnqual(SlotTy), Params, true), "objc_msg_lookup_sender"); - imp = CGF.Builder.CreateCall3(lookupFunction, Receiver, cmd, self); + // The lookup function is guaranteed not to capture the receiver pointer. + if (llvm::Function *LookupFn = dyn_cast<llvm::Function>(lookupFunction)) { + LookupFn->setDoesNotCapture(1); + } + + llvm::Value *slot = + Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self); + imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); + // The lookup function may have changed the receiver, so make sure we use + // the new one. + ActualArgs[0] = + std::make_pair(RValue::get(Builder.CreateLoad(ReceiverPtr)), ASTIdTy); } else { - llvm::Constant *lookupFunction = + std::vector<const llvm::Type*> Params; + Params.push_back(Receiver->getType()); + Params.push_back(SelectorTy); + llvm::Constant *lookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( llvm::PointerType::getUnqual(impType), Params, true), "objc_msg_lookup"); - imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd); + imp = Builder.CreateCall2(lookupFunction, Receiver, cmd); } return CGF.EmitCall(FnInfo, imp, ActualArgs); } -/// Generates a MethodList. Used in construction of a objc_class and +/// Generates a MethodList. Used in construction of a objc_class and /// objc_category structures. llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, - const std::string &CategoryName, - const llvm::SmallVectorImpl<Selector> &MethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, + const std::string &CategoryName, + const llvm::SmallVectorImpl<Selector> &MethodSels, + const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, bool isClassMethodList) { - // Get the method structure type. - llvm::StructType *ObjCMethodTy = llvm::StructType::get( + if (MethodSels.empty()) + return NULLPtr; + // Get the method structure type. + llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext, PtrToInt8Ty, // Really a selector, but the runtime creates it us. PtrToInt8Ty, // Method types llvm::PointerType::getUnqual(IMPTy), //Method pointer @@ -501,11 +562,9 @@ llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName, MethodSels[i].getAsString(), isClassMethodList))) { - llvm::Constant *C = - CGM.GetAddrOfConstantCString(MethodSels[i].getAsString()); - Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2)); - Elements.push_back( - llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2)); + llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString()); + Elements.push_back(C); + Elements.push_back(MethodTypes[i]); Method = llvm::ConstantExpr::getBitCast(Method, llvm::PointerType::getUnqual(IMPTy)); Elements.push_back(Method); @@ -521,10 +580,11 @@ llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, // Structure containing list pointer, array and array count llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields; - llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(); + llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(VMContext); llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy); - llvm::StructType *ObjCMethodListTy = llvm::StructType::get(NextPtrTy, - IntTy, + llvm::StructType *ObjCMethodListTy = llvm::StructType::get(VMContext, + NextPtrTy, + IntTy, ObjCMethodArrayTy, NULL); // Refine next pointer type to concrete type @@ -535,10 +595,10 @@ llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, Methods.clear(); Methods.push_back(llvm::ConstantPointerNull::get( llvm::PointerType::getUnqual(ObjCMethodListTy))); - Methods.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, + Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), MethodTypes.size())); Methods.push_back(MethodArray); - + // Create an instance of the structure return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list"); } @@ -548,8 +608,8 @@ llvm::Constant *CGObjCGNU::GenerateIvarList( const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) { - // Get the method structure type. - llvm::StructType *ObjCIvarTy = llvm::StructType::get( + // Get the method structure type. + llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, @@ -558,10 +618,8 @@ llvm::Constant *CGObjCGNU::GenerateIvarList( std::vector<llvm::Constant*> Elements; for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) { Elements.clear(); - Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarNames[i], - Zeros, 2)); - Elements.push_back( llvm::ConstantExpr::getGetElementPtr(IvarTypes[i], - Zeros, 2)); + Elements.push_back(IvarNames[i]); + Elements.push_back(IvarTypes[i]); Elements.push_back(IvarOffsets[i]); Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements)); } @@ -570,12 +628,12 @@ llvm::Constant *CGObjCGNU::GenerateIvarList( llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy, IvarNames.size()); - + Elements.clear(); Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size())); Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars)); // Structure containing array and array count - llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy, + llvm::StructType *ObjCIvarListTy = llvm::StructType::get(VMContext, IntTy, ObjCIvarArrayTy, NULL); @@ -593,11 +651,17 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( llvm::Constant *InstanceSize, llvm::Constant *IVars, llvm::Constant *Methods, - llvm::Constant *Protocols) { + llvm::Constant *Protocols, + llvm::Constant *IvarOffsets, + llvm::Constant *Properties) { // Set up the class structure // Note: Several of these are char*s when they should be ids. This is // because the runtime performs this translation on load. - llvm::StructType *ClassTy = llvm::StructType::get( + // + // Fields marked New ABI are part of the GNUstep runtime. We emit them + // anyway; the classes will still work with the GNU runtime, they will just + // be ignored. + llvm::StructType *ClassTy = llvm::StructType::get(VMContext, PtrToInt8Ty, // class_pointer PtrToInt8Ty, // super_class PtrToInt8Ty, // name @@ -606,16 +670,18 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( LongTy, // instance_size IVars->getType(), // ivars Methods->getType(), // methods - // These are all filled in by the runtime, so we pretend + // These are all filled in by the runtime, so we pretend PtrTy, // dtable PtrTy, // subclass_list PtrTy, // sibling_class PtrTy, // protocols PtrTy, // gc_object_type + // New ABI: + LongTy, // abi_version + IvarOffsets->getType(), // ivar_offsets + Properties->getType(), // properties NULL); llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0); - llvm::Constant *NullP = - llvm::ConstantPointerNull::get(PtrTy); // Fill in the structure std::vector<llvm::Constant*> Elements; Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty)); @@ -626,11 +692,14 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( Elements.push_back(InstanceSize); Elements.push_back(IVars); Elements.push_back(Methods); - Elements.push_back(NullP); - Elements.push_back(NullP); - Elements.push_back(NullP); + Elements.push_back(NULLPtr); + Elements.push_back(NULLPtr); + Elements.push_back(NULLPtr); Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy)); - Elements.push_back(NullP); + Elements.push_back(NULLPtr); + Elements.push_back(Zero); + Elements.push_back(IvarOffsets); + Elements.push_back(Properties); // Create an instance of the structure return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name)); } @@ -638,8 +707,8 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( llvm::Constant *CGObjCGNU::GenerateProtocolMethodList( const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames, const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) { - // Get the method structure type. - llvm::StructType *ObjCMethodDescTy = llvm::StructType::get( + // Get the method structure type. + llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(VMContext, PtrToInt8Ty, // Really a selector, but the runtime does the casting for us. PtrToInt8Ty, NULL); @@ -647,40 +716,40 @@ llvm::Constant *CGObjCGNU::GenerateProtocolMethodList( std::vector<llvm::Constant*> Elements; for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) { Elements.clear(); - Elements.push_back( llvm::ConstantExpr::getGetElementPtr(MethodNames[i], - Zeros, 2)); - Elements.push_back( - llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2)); + Elements.push_back(MethodNames[i]); + Elements.push_back(MethodTypes[i]); Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements)); } llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy, MethodNames.size()); - llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, Methods); - llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get( + llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, + Methods); + llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(VMContext, IntTy, ObjCMethodArrayTy, NULL); Methods.clear(); Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size())); Methods.push_back(Array); return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list"); } + // Create the protocol list structure used in classes, categories and so on llvm::Constant *CGObjCGNU::GenerateProtocolList( const llvm::SmallVectorImpl<std::string> &Protocols) { llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty, Protocols.size()); - llvm::StructType *ProtocolListTy = llvm::StructType::get( + llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext, PtrTy, //Should be a recurisve pointer, but it's always NULL here. LongTy,//FIXME: Should be size_t ProtocolArrayTy, NULL); - std::vector<llvm::Constant*> Elements; + std::vector<llvm::Constant*> Elements; for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end(); iter != endIter ; iter++) { llvm::Constant *protocol = ExistingProtocols[*iter]; if (!protocol) protocol = GenerateEmptyProtocol(*iter); - llvm::Constant *Ptr = - llvm::ConstantExpr::getBitCast(protocol, PtrToInt8Ty); + llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol, + PtrToInt8Ty); Elements.push_back(Ptr); } llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, @@ -692,10 +761,10 @@ llvm::Constant *CGObjCGNU::GenerateProtocolList( return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list"); } -llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder, +llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD) { llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()]; - const llvm::Type *T = + const llvm::Type *T = CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType()); return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T)); } @@ -706,27 +775,31 @@ llvm::Constant *CGObjCGNU::GenerateEmptyProtocol( llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector; llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector); - llvm::Constant *InstanceMethodList = - GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector); - llvm::Constant *ClassMethodList = + llvm::Constant *MethodList = GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector); // Protocols are objects containing lists of the methods implemented and // protocols adopted. - llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy, + llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy, PtrToInt8Ty, ProtocolList->getType(), - InstanceMethodList->getType(), - ClassMethodList->getType(), + MethodList->getType(), + MethodList->getType(), + MethodList->getType(), + MethodList->getType(), NULL); - std::vector<llvm::Constant*> Elements; + std::vector<llvm::Constant*> Elements; // The isa pointer must be set to a magic number so the runtime knows it's // the correct layout. + int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? + NonFragileProtocolVersion : ProtocolVersion; Elements.push_back(llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); Elements.push_back(ProtocolList); - Elements.push_back(InstanceMethodList); - Elements.push_back(ClassMethodList); + Elements.push_back(MethodList); + Elements.push_back(MethodList); + Elements.push_back(MethodList); + Elements.push_back(MethodList); return MakeGlobal(ProtocolTy, Elements, ".objc_protocol"); } @@ -739,25 +812,41 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { Protocols.push_back((*PI)->getNameAsString()); llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames; llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; + llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames; + llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes; for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(), E = PD->instmeth_end(); iter != E; iter++) { std::string TypeStr; Context.getObjCEncodingForMethodDecl(*iter, TypeStr); - InstanceMethodNames.push_back( - CGM.GetAddrOfConstantCString((*iter)->getSelector().getAsString())); - InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { + InstanceMethodNames.push_back( + MakeConstantString((*iter)->getSelector().getAsString())); + InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); + } else { + OptionalInstanceMethodNames.push_back( + MakeConstantString((*iter)->getSelector().getAsString())); + OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr)); + } } // Collect information about class methods: llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames; llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; - for (ObjCProtocolDecl::classmeth_iterator + llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodNames; + llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes; + for (ObjCProtocolDecl::classmeth_iterator iter = PD->classmeth_begin(), endIter = PD->classmeth_end(); iter != endIter ; iter++) { std::string TypeStr; Context.getObjCEncodingForMethodDecl((*iter),TypeStr); - ClassMethodNames.push_back( - CGM.GetAddrOfConstantCString((*iter)->getSelector().getAsString())); - ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { + ClassMethodNames.push_back( + MakeConstantString((*iter)->getSelector().getAsString())); + ClassMethodTypes.push_back(MakeConstantString(TypeStr)); + } else { + OptionalClassMethodNames.push_back( + MakeConstantString((*iter)->getSelector().getAsString())); + OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr)); + } } llvm::Constant *ProtocolList = GenerateProtocolList(Protocols); @@ -765,27 +854,165 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes); llvm::Constant *ClassMethodList = GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes); + llvm::Constant *OptionalInstanceMethodList = + GenerateProtocolMethodList(OptionalInstanceMethodNames, + OptionalInstanceMethodTypes); + llvm::Constant *OptionalClassMethodList = + GenerateProtocolMethodList(OptionalClassMethodNames, + OptionalClassMethodTypes); + + // Property metadata: name, attributes, isSynthesized, setter name, setter + // types, getter name, getter types. + // The isSynthesized value is always set to 0 in a protocol. It exists to + // simplify the runtime library by allowing it to use the same data + // structures for protocol metadata everywhere. + llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext, + PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, + PtrToInt8Ty, NULL); + std::vector<llvm::Constant*> Properties; + std::vector<llvm::Constant*> OptionalProperties; + + // Add all of the property methods need adding to the method list and to the + // property metadata list. + for (ObjCContainerDecl::prop_iterator + iter = PD->prop_begin(), endIter = PD->prop_end(); + iter != endIter ; iter++) { + std::vector<llvm::Constant*> Fields; + ObjCPropertyDecl *property = (*iter); + + Fields.push_back(MakeConstantString(property->getNameAsString())); + Fields.push_back(llvm::ConstantInt::get(Int8Ty, + property->getPropertyAttributes())); + Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0)); + if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { + std::string TypeStr; + Context.getObjCEncodingForMethodDecl(getter,TypeStr); + llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); + InstanceMethodTypes.push_back(TypeEncoding); + Fields.push_back(MakeConstantString(getter->getSelector().getAsString())); + Fields.push_back(TypeEncoding); + } else { + Fields.push_back(NULLPtr); + Fields.push_back(NULLPtr); + } + if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) { + std::string TypeStr; + Context.getObjCEncodingForMethodDecl(setter,TypeStr); + llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); + InstanceMethodTypes.push_back(TypeEncoding); + Fields.push_back(MakeConstantString(setter->getSelector().getAsString())); + Fields.push_back(TypeEncoding); + } else { + Fields.push_back(NULLPtr); + Fields.push_back(NULLPtr); + } + if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) { + OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); + } else { + Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); + } + } + llvm::Constant *PropertyArray = llvm::ConstantArray::get( + llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties); + llvm::Constant* PropertyListInitFields[] = + {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray}; + + llvm::Constant *PropertyListInit = + llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false); + llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule, + PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage, + PropertyListInit, ".objc_property_list"); + + llvm::Constant *OptionalPropertyArray = + llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy, + OptionalProperties.size()) , OptionalProperties); + llvm::Constant* OptionalPropertyListInitFields[] = { + llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr, + OptionalPropertyArray }; + + llvm::Constant *OptionalPropertyListInit = + llvm::ConstantStruct::get(VMContext, OptionalPropertyListInitFields, 3, false); + llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule, + OptionalPropertyListInit->getType(), false, + llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit, + ".objc_property_list"); + // Protocols are objects containing lists of the methods implemented and // protocols adopted. - llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy, + llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy, PtrToInt8Ty, ProtocolList->getType(), InstanceMethodList->getType(), ClassMethodList->getType(), + OptionalInstanceMethodList->getType(), + OptionalClassMethodList->getType(), + PropertyList->getType(), + OptionalPropertyList->getType(), NULL); - std::vector<llvm::Constant*> Elements; + std::vector<llvm::Constant*> Elements; // The isa pointer must be set to a magic number so the runtime knows it's // the correct layout. + int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? + NonFragileProtocolVersion : ProtocolVersion; Elements.push_back(llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(llvm::Type::Int32Ty, ProtocolVersion), IdTy)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); Elements.push_back(ProtocolList); Elements.push_back(InstanceMethodList); Elements.push_back(ClassMethodList); - ExistingProtocols[ProtocolName] = + Elements.push_back(OptionalInstanceMethodList); + Elements.push_back(OptionalClassMethodList); + Elements.push_back(PropertyList); + Elements.push_back(OptionalPropertyList); + ExistingProtocols[ProtocolName] = llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements, ".objc_protocol"), IdTy); } +void CGObjCGNU::GenerateProtocolHolderCategory(void) { + // Collect information about instance methods + llvm::SmallVector<Selector, 1> MethodSels; + llvm::SmallVector<llvm::Constant*, 1> MethodTypes; + + std::vector<llvm::Constant*> Elements; + const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack"; + const std::string CategoryName = "AnotherHack"; + Elements.push_back(MakeConstantString(CategoryName)); + Elements.push_back(MakeConstantString(ClassName)); + // Instance method list + Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( + ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy)); + // Class method list + Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( + ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy)); + // Protocol list + llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy, + ExistingProtocols.size()); + llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext, + PtrTy, //Should be a recurisve pointer, but it's always NULL here. + LongTy,//FIXME: Should be size_t + ProtocolArrayTy, + NULL); + std::vector<llvm::Constant*> ProtocolElements; + for (llvm::StringMapIterator<llvm::Constant*> iter = + ExistingProtocols.begin(), endIter = ExistingProtocols.end(); + iter != endIter ; iter++) { + llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(), + PtrTy); + ProtocolElements.push_back(Ptr); + } + llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, + ProtocolElements); + ProtocolElements.clear(); + ProtocolElements.push_back(NULLPtr); + ProtocolElements.push_back(llvm::ConstantInt::get(LongTy, + ExistingProtocols.size())); + ProtocolElements.push_back(ProtocolArray); + Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy, + ProtocolElements, ".objc_protocol_list"), PtrTy)); + Categories.push_back(llvm::ConstantExpr::getBitCast( + MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, + PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy)); +} void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { std::string ClassName = OCD->getClassInterface()->getNameAsString(); @@ -799,19 +1026,19 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { InstanceMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); - InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); } // Collect information about class methods llvm::SmallVector<Selector, 16> ClassMethodSels; llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; - for (ObjCCategoryImplDecl::classmeth_iterator + for (ObjCCategoryImplDecl::classmeth_iterator iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end(); iter != endIter ; iter++) { ClassMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); - ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + ClassMethodTypes.push_back(MakeConstantString(TypeStr)); } // Collect the names of referenced protocols @@ -825,7 +1052,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { std::vector<llvm::Constant*> Elements; Elements.push_back(MakeConstantString(CategoryName)); Elements.push_back(MakeConstantString(ClassName)); - // Instance method list + // Instance method list Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes, false), PtrTy)); @@ -837,15 +1064,82 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Elements.push_back(llvm::ConstantExpr::getBitCast( GenerateProtocolList(Protocols), PtrTy)); Categories.push_back(llvm::ConstantExpr::getBitCast( - MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, PtrTy, - PtrTy, PtrTy, NULL), Elements), PtrTy)); + MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, + PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy)); +} + +llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID, + llvm::SmallVectorImpl<Selector> &InstanceMethodSels, + llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) { + ASTContext &Context = CGM.getContext(); + // + // Property metadata: name, attributes, isSynthesized, setter name, setter + // types, getter name, getter types. + llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext, + PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, + PtrToInt8Ty, NULL); + std::vector<llvm::Constant*> Properties; + + + // Add all of the property methods need adding to the method list and to the + // property metadata list. + for (ObjCImplDecl::propimpl_iterator + iter = OID->propimpl_begin(), endIter = OID->propimpl_end(); + iter != endIter ; iter++) { + std::vector<llvm::Constant*> Fields; + ObjCPropertyDecl *property = (*iter)->getPropertyDecl(); + + Fields.push_back(MakeConstantString(property->getNameAsString())); + Fields.push_back(llvm::ConstantInt::get(Int8Ty, + property->getPropertyAttributes())); + Fields.push_back(llvm::ConstantInt::get(Int8Ty, + (*iter)->getPropertyImplementation() == + ObjCPropertyImplDecl::Synthesize)); + if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { + InstanceMethodSels.push_back(getter->getSelector()); + std::string TypeStr; + Context.getObjCEncodingForMethodDecl(getter,TypeStr); + llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); + InstanceMethodTypes.push_back(TypeEncoding); + Fields.push_back(MakeConstantString(getter->getSelector().getAsString())); + Fields.push_back(TypeEncoding); + } else { + Fields.push_back(NULLPtr); + Fields.push_back(NULLPtr); + } + if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) { + InstanceMethodSels.push_back(setter->getSelector()); + std::string TypeStr; + Context.getObjCEncodingForMethodDecl(setter,TypeStr); + llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); + InstanceMethodTypes.push_back(TypeEncoding); + Fields.push_back(MakeConstantString(setter->getSelector().getAsString())); + Fields.push_back(TypeEncoding); + } else { + Fields.push_back(NULLPtr); + Fields.push_back(NULLPtr); + } + Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); + } + llvm::ArrayType *PropertyArrayTy = + llvm::ArrayType::get(PropertyMetadataTy, Properties.size()); + llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy, + Properties); + llvm::Constant* PropertyListInitFields[] = + {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray}; + + llvm::Constant *PropertyListInit = + llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false); + return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false, + llvm::GlobalValue::InternalLinkage, PropertyListInit, + ".objc_property_list"); } void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { ASTContext &Context = CGM.getContext(); // Get the superclass name. - const ObjCInterfaceDecl * SuperClassDecl = + const ObjCInterfaceDecl * SuperClassDecl = OID->getClassInterface()->getSuperClass(); std::string SuperClassName; if (SuperClassDecl) { @@ -860,14 +1154,15 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { // Emit the symbol that is used to generate linker errors if this class is // referenced in other modules but not declared. std::string classSymbolName = "__objc_class_name_" + ClassName; - if (llvm::GlobalVariable *symbol = + if (llvm::GlobalVariable *symbol = TheModule.getGlobalVariable(classSymbolName)) { symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0)); } else { - new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage, - llvm::ConstantInt::get(LongTy, 0), classSymbolName, &TheModule); + new llvm::GlobalVariable(TheModule, LongTy, false, + llvm::GlobalValue::ExternalLinkage, llvm::ConstantInt::get(LongTy, 0), + classSymbolName); } - + // Get the size of instances. int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8; @@ -875,8 +1170,10 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { llvm::SmallVector<llvm::Constant*, 16> IvarNames; llvm::SmallVector<llvm::Constant*, 16> IvarTypes; llvm::SmallVector<llvm::Constant*, 16> IvarOffsets; - - int superInstanceSize = !SuperClassDecl ? 0 : + + std::vector<llvm::Constant*> IvarOffsetValues; + + int superInstanceSize = !SuperClassDecl ? 0 : Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize() / 8; // For non-fragile ivars, set the instance size to 0 - {the size of just this // class}. The runtime will then set this to the correct value on load. @@ -886,54 +1183,49 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(), endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) { // Store the name - IvarNames.push_back(CGM.GetAddrOfConstantCString((*iter) - ->getNameAsString())); + IvarNames.push_back(MakeConstantString((*iter)->getNameAsString())); // Get the type encoding for this ivar std::string TypeStr; Context.getObjCEncodingForType((*iter)->getType(), TypeStr); - IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + IvarTypes.push_back(MakeConstantString(TypeStr)); // Get the offset - uint64_t Offset; + uint64_t Offset = 0; + uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter); if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { - Offset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter) - - superInstanceSize; - ObjCIvarOffsetVariable(ClassDecl, *iter); - } else { - Offset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter); + Offset = BaseOffset - superInstanceSize; } IvarOffsets.push_back( - llvm::ConstantInt::get(llvm::Type::Int32Ty, Offset)); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset)); + IvarOffsetValues.push_back(new llvm::GlobalVariable(TheModule, IntTy, + false, llvm::GlobalValue::ExternalLinkage, + llvm::ConstantInt::get(IntTy, BaseOffset), + "__objc_ivar_offset_value_" + ClassName +"." + + (*iter)->getNameAsString())); } + llvm::Constant *IvarOffsetArrayInit = + llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy, + IvarOffsetValues.size()), IvarOffsetValues); + llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule, + IvarOffsetArrayInit->getType(), false, + llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit, + ".ivar.offsets"); // Collect information about instance methods llvm::SmallVector<Selector, 16> InstanceMethodSels; llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; - for (ObjCImplementationDecl::instmeth_iterator + for (ObjCImplementationDecl::instmeth_iterator iter = OID->instmeth_begin(), endIter = OID->instmeth_end(); iter != endIter ; iter++) { InstanceMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; Context.getObjCEncodingForMethodDecl((*iter),TypeStr); - InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); - } - for (ObjCImplDecl::propimpl_iterator - iter = OID->propimpl_begin(), endIter = OID->propimpl_end(); - iter != endIter ; iter++) { - ObjCPropertyDecl *property = (*iter)->getPropertyDecl(); - if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { - InstanceMethodSels.push_back(getter->getSelector()); - std::string TypeStr; - Context.getObjCEncodingForMethodDecl(getter,TypeStr); - InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); - } - if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) { - InstanceMethodSels.push_back(setter->getSelector()); - std::string TypeStr; - Context.getObjCEncodingForMethodDecl(setter,TypeStr); - InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); - } + InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); } + llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels, + InstanceMethodTypes); + + // Collect information about class methods llvm::SmallVector<Selector, 16> ClassMethodSels; llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; @@ -943,7 +1235,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { ClassMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; Context.getObjCEncodingForMethodDecl((*iter),TypeStr); - ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + ClassMethodTypes.push_back(MakeConstantString(TypeStr)); } // Collect the names of referenced protocols llvm::SmallVector<std::string, 16> Protocols; @@ -970,17 +1262,55 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { ClassMethodSels, ClassMethodTypes, true); llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes, IvarOffsets); + // Irrespective of whether we are compiling for a fragile or non-fragile ABI, + // we emit a symbol containing the offset for each ivar in the class. This + // allows code compiled for the non-Fragile ABI to inherit from code compiled + // for the legacy ABI, without causing problems. The converse is also + // possible, but causes all ivar accesses to be fragile. + int i = 0; + // Offset pointer for getting at the correct field in the ivar list when + // setting up the alias. These are: The base address for the global, the + // ivar array (second field), the ivar in this list (set for each ivar), and + // the offset (third field in ivar structure) + const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext); + llvm::Constant *offsetPointerIndexes[] = {Zeros[0], + llvm::ConstantInt::get(IndexTy, 1), 0, + llvm::ConstantInt::get(IndexTy, 2) }; + + for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(), + endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) { + const std::string Name = "__objc_ivar_offset_" + ClassName + '.' + +(*iter)->getNameAsString(); + offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i++); + // Get the correct ivar field + llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr( + IvarList, offsetPointerIndexes, 4); + // Get the existing alias, if one exists. + llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name); + if (offset) { + offset->setInitializer(offsetValue); + // If this is the real definition, change its linkage type so that + // different modules will use this one, rather than their private + // copy. + offset->setLinkage(llvm::GlobalValue::ExternalLinkage); + } else { + // Add a new alias if there isn't one already. + offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(), + false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name); + } + } //Generate metaclass for class methods llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr, - NULLPtr, 0x2L, /*name*/"", 0, Zeros[0], GenerateIvarList( - empty, empty, empty), ClassMethodList, NULLPtr); + NULLPtr, 0x12L, /*name*/"", 0, Zeros[0], GenerateIvarList( + empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr); // Generate the class structure llvm::Constant *ClassStruct = - GenerateClassStructure(MetaClassStruct, SuperClass, 0x1L, + GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(), 0, llvm::ConstantInt::get(LongTy, instanceSize), IvarList, - MethodList, GenerateProtocolList(Protocols)); + MethodList, GenerateProtocolList(Protocols), IvarOffsetArray, + Properties); // Resolve the class aliases, if they exist. if (ClassPtrAlias) { @@ -999,23 +1329,24 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { Classes.push_back(ClassStruct); } -void CGObjCGNU::MergeMetadataGlobals( - std::vector<llvm::Constant*> &UsedArray) { -} -llvm::Function *CGObjCGNU::ModuleInitFunction() { +llvm::Function *CGObjCGNU::ModuleInitFunction() { // Only emit an ObjC load function if no Objective-C stuff has been called if (Classes.empty() && Categories.empty() && ConstantStrings.empty() && ExistingProtocols.empty() && TypedSelectors.empty() && UntypedSelectors.empty()) return NULL; + // Add all referenced protocols to a category. + GenerateProtocolHolderCategory(); + const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>( SelectorTy->getElementType()); const llvm::Type *SelStructPtrTy = SelectorTy; bool isSelOpaque = false; if (SelStructTy == 0) { - SelStructTy = llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, NULL); + SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty, + PtrToInt8Ty, NULL); SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy); isSelOpaque = true; } @@ -1032,13 +1363,17 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty, ConstantStrings.size() + 1); ConstantStrings.push_back(NULLPtr); - Elements.push_back(MakeConstantString("NSConstantString", - ".objc_static_class_name")); + + const char *StringClass = CGM.getLangOptions().ObjCConstantStringClass; + if (!StringClass) StringClass = "NXConstantString"; + Elements.push_back(MakeConstantString(StringClass, + ".objc_static_class_name")); Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, ConstantStrings)); - llvm::StructType *StaticsListTy = - llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, NULL); - llvm::Type *StaticsListPtrTy = llvm::PointerType::getUnqual(StaticsListTy); + llvm::StructType *StaticsListTy = + llvm::StructType::get(VMContext, PtrToInt8Ty, StaticsArrayTy, NULL); + llvm::Type *StaticsListPtrTy = + llvm::PointerType::getUnqual(StaticsListTy); Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics"); llvm::ArrayType *StaticsListArrayTy = llvm::ArrayType::get(StaticsListPtrTy, 2); @@ -1051,9 +1386,10 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { // Array of classes, categories, and constant objects llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty, Classes.size() + Categories.size() + 2); - llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelStructPtrTy, - llvm::Type::Int16Ty, - llvm::Type::Int16Ty, + llvm::StructType *SymTabTy = llvm::StructType::get(VMContext, + LongTy, SelStructPtrTy, + llvm::Type::getInt16Ty(VMContext), + llvm::Type::getInt16Ty(VMContext), ClassListTy, NULL); Elements.clear(); @@ -1062,7 +1398,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end(); iter != iterEnd ; ++iter) { - Elements.push_back(MakeConstantString(iter->first.first, ".objc_sel_name")); + Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name")); Elements.push_back(MakeConstantString(iter->first.second, ".objc_sel_types")); Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); @@ -1072,7 +1408,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); iter != iterEnd; ++iter) { Elements.push_back( - MakeConstantString(iter->getKeyData(), ".objc_sel_name")); + ExportUniqueString(iter->getKeyData(), ".objc_sel_name")); Elements.push_back(NULLPtr); Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); Elements.clear(); @@ -1086,7 +1422,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { llvm::Constant *SelectorList = MakeGlobal( llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors, ".objc_selector_list"); - Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, + Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, SelStructPtrTy)); // Now that all of the static selectors exist, create pointers to them. @@ -1095,11 +1431,11 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end(); iter != iterEnd; ++iter) { llvm::Constant *Idxs[] = {Zeros[0], - llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]}; - llvm::Constant *SelPtr = new llvm::GlobalVariable(SelStructPtrTy, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; + llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy, true, llvm::GlobalValue::InternalLinkage, llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), - ".objc_sel_ptr", &TheModule); + ".objc_sel_ptr"); // If selectors are defined as an opaque type, cast the pointer to this // type. if (isSelOpaque) { @@ -1112,11 +1448,12 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); iter != iterEnd; iter++) { llvm::Constant *Idxs[] = {Zeros[0], - llvm::ConstantInt::get(llvm::Type::Int32Ty, index++), Zeros[0]}; - llvm::Constant *SelPtr = new llvm::GlobalVariable(SelStructPtrTy, true, - llvm::GlobalValue::InternalLinkage, - llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), - ".objc_sel_ptr", &TheModule); + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; + llvm::Constant *SelPtr = new llvm::GlobalVariable + (TheModule, SelStructPtrTy, + true, llvm::GlobalValue::InternalLinkage, + llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), + ".objc_sel_ptr"); // If selectors are defined as an opaque type, cast the pointer to this // type. if (isSelOpaque) { @@ -1126,10 +1463,10 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { (*iter).second->setAliasee(SelPtr); } // Number of classes defined. - Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty, + Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), Classes.size())); // Number of categories defined - Elements.push_back(llvm::ConstantInt::get(llvm::Type::Int16Ty, + Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), Categories.size())); // Create an array of classes, then categories, then static object instances Classes.insert(Classes.end(), Categories.begin(), Categories.end()); @@ -1138,24 +1475,25 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { Classes.push_back(NULLPtr); llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes); Elements.push_back(ClassList); - // Construct the symbol table + // Construct the symbol table llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements); // The symbol table is contained in a module which has some version-checking // constants - llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy, + llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy, PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL); Elements.clear(); // Runtime version used for compatibility checking. if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { - Elements.push_back(llvm::ConstantInt::get(LongTy, + Elements.push_back(llvm::ConstantInt::get(LongTy, NonFragileRuntimeVersion)); } else { Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion)); } // sizeof(ModuleTy) llvm::TargetData td = llvm::TargetData::TargetData(&TheModule); - Elements.push_back(llvm::ConstantInt::get(LongTy, td.getTypeSizeInBits(ModuleTy)/8)); + Elements.push_back(llvm::ConstantInt::get(LongTy, + td.getTypeSizeInBits(ModuleTy)/8)); //FIXME: Should be the path to the file where this module was declared Elements.push_back(NULLPtr); Elements.push_back(SymTab); @@ -1164,17 +1502,18 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { // Create the load function calling the runtime entry point with the module // structure llvm::Function * LoadFunction = llvm::Function::Create( - llvm::FunctionType::get(llvm::Type::VoidTy, false), + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false), llvm::GlobalValue::InternalLinkage, ".objc_load_function", &TheModule); - llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction); - CGBuilderTy Builder; + llvm::BasicBlock *EntryBB = + llvm::BasicBlock::Create(VMContext, "entry", LoadFunction); + CGBuilderTy Builder(VMContext); Builder.SetInsertPoint(EntryBB); std::vector<const llvm::Type*> Params(1, llvm::PointerType::getUnqual(ModuleTy)); llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get( - llvm::Type::VoidTy, Params, true), "__objc_exec_class"); + llvm::Type::getVoidTy(VMContext), Params, true), "__objc_exec_class"); Builder.CreateCall(Register, Module); Builder.CreateRetVoid(); @@ -1182,8 +1521,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { } llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD) { - const ObjCCategoryImplDecl *OCD = + const ObjCContainerDecl *CD) { + const ObjCCategoryImplDecl *OCD = dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext()); std::string CategoryName = OCD ? OCD->getNameAsString() : ""; std::string ClassName = OMD->getClassInterface()->getNameAsString(); @@ -1191,71 +1530,76 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, bool isClassMethod = !OMD->isInstanceMethod(); CodeGenTypes &Types = CGM.getTypes(); - const llvm::FunctionType *MethodTy = + const llvm::FunctionType *MethodTy = Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName, MethodName, isClassMethod); - llvm::Function *Method = llvm::Function::Create(MethodTy, - llvm::GlobalValue::InternalLinkage, - FunctionName, - &TheModule); + llvm::Function *Method + = llvm::Function::Create(MethodTy, + llvm::GlobalValue::InternalLinkage, + FunctionName, + &TheModule); return Method; } llvm::Function *CGObjCGNU::GetPropertyGetFunction() { - std::vector<const llvm::Type*> Params; - const llvm::Type *BoolTy = - CGM.getTypes().ConvertType(CGM.getContext().BoolTy); - Params.push_back(IdTy); - Params.push_back(SelectorTy); - // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64 - Params.push_back(LongTy); - Params.push_back(BoolTy); - // void objc_getProperty (id, SEL, ptrdiff_t, bool) - const llvm::FunctionType *FTy = - llvm::FunctionType::get(IdTy, Params, false); - return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, - "objc_getProperty")); + std::vector<const llvm::Type*> Params; + const llvm::Type *BoolTy = + CGM.getTypes().ConvertType(CGM.getContext().BoolTy); + Params.push_back(IdTy); + Params.push_back(SelectorTy); + // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64 + Params.push_back(LongTy); + Params.push_back(BoolTy); + // void objc_getProperty (id, SEL, ptrdiff_t, bool) + const llvm::FunctionType *FTy = + llvm::FunctionType::get(IdTy, Params, false); + return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, + "objc_getProperty")); } llvm::Function *CGObjCGNU::GetPropertySetFunction() { - std::vector<const llvm::Type*> Params; - const llvm::Type *BoolTy = - CGM.getTypes().ConvertType(CGM.getContext().BoolTy); - Params.push_back(IdTy); - Params.push_back(SelectorTy); - // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64 - Params.push_back(LongTy); - Params.push_back(IdTy); - Params.push_back(BoolTy); - Params.push_back(BoolTy); - // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) - const llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Params, false); - return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, - "objc_setProperty")); + std::vector<const llvm::Type*> Params; + const llvm::Type *BoolTy = + CGM.getTypes().ConvertType(CGM.getContext().BoolTy); + Params.push_back(IdTy); + Params.push_back(SelectorTy); + // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64 + Params.push_back(LongTy); + Params.push_back(IdTy); + Params.push_back(BoolTy); + Params.push_back(BoolTy); + // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) + const llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); + return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, + "objc_setProperty")); } -llvm::Function *CGObjCGNU::EnumerationMutationFunction() { - std::vector<const llvm::Type*> Params(1, IdTy); - return cast<llvm::Function>(CGM.CreateRuntimeFunction( - llvm::FunctionType::get(llvm::Type::VoidTy, Params, true), - "objc_enumerationMutation")); +llvm::Constant *CGObjCGNU::EnumerationMutationFunction() { + CodeGen::CodeGenTypes &Types = CGM.getTypes(); + ASTContext &Ctx = CGM.getContext(); + // void objc_enumerationMutation (id) + llvm::SmallVector<QualType,16> Params; + Params.push_back(ASTIdTy); + const llvm::FunctionType *FTy = + Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false); + return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); } void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S) { // Pointer to the personality function llvm::Constant *Personality = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty, + CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), true), "__gnu_objc_personality_v0"); Personality = llvm::ConstantExpr::getBitCast(Personality, PtrTy); std::vector<const llvm::Type*> Params; Params.push_back(PtrTy); llvm::Value *RethrowFn = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, + CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false), "_Unwind_Resume_or_Rethrow"); bool isTry = isa<ObjCAtTryStmt>(S); @@ -1271,9 +1615,9 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, if (!isTry) { std::vector<const llvm::Type*> Args(1, IdTy); llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); - llvm::Value *SyncArg = + llvm::Value *SyncArg = CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); CGF.Builder.CreateCall(SyncEnter, SyncArg); @@ -1288,7 +1632,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.setInvokeDest(TryHandler); CGF.EmitBlock(TryBlock); - CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() + CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); // Jump to @finally if there is no exception @@ -1299,17 +1643,12 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Get the correct versions of the exception handling intrinsics llvm::TargetData td = llvm::TargetData::TargetData(&TheModule); - int PointerWidth = td.getTypeSizeInBits(PtrTy); - assert((PointerWidth == 32 || PointerWidth == 64) && - "Can't yet handle exceptions if pointers are not 32 or 64 bits"); - llvm::Value *llvm_eh_exception = + llvm::Value *llvm_eh_exception = CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); - llvm::Value *llvm_eh_selector = PointerWidth == 32 ? - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector_i32) : - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector_i64); - llvm::Value *llvm_eh_typeid_for = PointerWidth == 32 ? - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for_i32) : - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for_i64); + llvm::Value *llvm_eh_selector = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); + llvm::Value *llvm_eh_typeid_for = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); // Exception object llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); @@ -1330,23 +1669,25 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); - Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody())); + Handlers.push_back(std::make_pair(CatchDecl, + CatchStmt->getCatchBody())); // @catch() and @catch(id) both catch any ObjC exception - if (!CatchDecl || CGF.getContext().isObjCIdType(CatchDecl->getType()) + if (!CatchDecl || CatchDecl->getType()->isObjCIdType() || CatchDecl->getType()->isObjCQualifiedIdType()) { // Use i8* null here to signal this is a catch all, not a cleanup. ESelArgs.push_back(NULLPtr); HasCatchAll = true; // No further catches after this one will ever by reached break; - } + } // All other types should be Objective-C interface pointer types. - const PointerType *PT = CatchDecl->getType()->getAsPointerType(); - assert(PT && "Invalid @catch type."); - const ObjCInterfaceType *IT = - PT->getPointeeType()->getAsObjCInterfaceType(); + const ObjCObjectPointerType *OPT = + CatchDecl->getType()->getAs<ObjCObjectPointerType>(); + assert(OPT && "Invalid @catch type."); + const ObjCInterfaceType *IT = + OPT->getPointeeType()->getAs<ObjCInterfaceType>(); assert(IT && "Invalid @catch type."); llvm::Value *EHType = MakeConstantString(IT->getDecl()->getNameAsString()); @@ -1357,7 +1698,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // We use a cleanup unless there was already a catch all. if (!HasCatchAll) { - ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0)); + ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0)); } @@ -1386,11 +1727,11 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBlock(Match); } - + if (CatchBody) { llvm::Value *ExcObject = CGF.Builder.CreateBitCast(Exc, CGF.ConvertType(CatchParam->getType())); - + // Bind the catch parameter if it exists. if (CatchParam) { // CatchParam is a ParmVarDecl because of the grammar @@ -1422,7 +1763,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, ESelArgs.clear(); ESelArgs.push_back(Exc); ESelArgs.push_back(Personality); - ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0)); + ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(), "selector"); CGF.Builder.CreateCall(llvm_eh_typeid_for, @@ -1438,7 +1779,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, if (isTry) { - if (const ObjCAtFinallyStmt* FinallyStmt = + if (const ObjCAtFinallyStmt* FinallyStmt = cast<ObjCAtTryStmt>(S).getFinallyStmt()) CGF.EmitStmt(FinallyStmt->getFinallyBody()); } else { @@ -1446,9 +1787,9 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // @synchronized. std::vector<const llvm::Type*> Args(1, IdTy); llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); - llvm::Value *SyncArg = + llvm::Value *SyncArg = CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); CGF.Builder.CreateCall(SyncExit, SyncArg); @@ -1465,7 +1806,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBlock(FinallyRethrow); CGF.Builder.CreateCall(RethrowFn, CGF.Builder.CreateLoad(RethrowPtr)); CGF.Builder.CreateUnreachable(); - + CGF.EmitBlock(FinallyEnd); } @@ -1476,21 +1817,21 @@ void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, std::vector<const llvm::Type*> Args(1, IdTy); llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); - llvm::Value *ThrowFn = + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); + llvm::Value *ThrowFn = CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); - + if (const Expr *ThrowExpr = S.getThrowExpr()) { llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); ExceptionAsObject = Exception; } else { - assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && + assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && "Unexpected rethrow outside @catch block."); ExceptionAsObject = CGF.ObjCEHValueStack.back(); } ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy, "tmp"); - + // Note: This may have to be an invoke, if we want to support constructs like: // @try { // @throw(obj); @@ -1513,32 +1854,35 @@ void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, } llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - llvm::Value *AddrWeakObj) -{ + llvm::Value *AddrWeakObj) { return 0; } void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { return; } void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { return; } void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst, + llvm::Value *ivarOffset) { return; } void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { + return; +} + +void CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, + llvm::Value *DestPtr, + llvm::Value *SrcPtr, + QualType Ty) { return; } @@ -1550,15 +1894,29 @@ llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable( // Emit the variable and initialize it with what we think the correct value // is. This allows code compiled with non-fragile ivars to work correctly // when linked against code which isn't (most of the time). - llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name); - if (!IvarOffsetGV) { + llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name); + if (!IvarOffsetPointer) { uint64_t Offset = ComputeIvarBaseOffset(CGM, ID, Ivar); llvm::ConstantInt *OffsetGuess = llvm::ConstantInt::get(LongTy, Offset, "ivar"); - IvarOffsetGV = new llvm::GlobalVariable(LongTy, false, - llvm::GlobalValue::CommonLinkage, OffsetGuess, Name, &TheModule); + // Don't emit the guess in non-PIC code because the linker will not be able + // to replace it with the real version for a library. In non-PIC code you + // must compile with the fragile ABI if you want to use ivars from a + // GCC-compiled class. + if (CGM.getLangOptions().PICLevel) { + llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule, + llvm::Type::getInt32Ty(VMContext), false, + llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess"); + IvarOffsetPointer = new llvm::GlobalVariable(TheModule, + IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage, + IvarOffsetGV, Name); + } else { + IvarOffsetPointer = new llvm::GlobalVariable(TheModule, + llvm::Type::getInt32PtrTy(VMContext), false, + llvm::GlobalValue::ExternalLinkage, 0, Name); + } } - return IvarOffsetGV; + return IvarOffsetPointer; } LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, @@ -1566,10 +1924,11 @@ LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl(); + const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } + static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, const ObjCInterfaceDecl *OID, const ObjCIvarDecl *OIVD) { @@ -1579,27 +1938,27 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, if (OIVD == Ivars[k]) return OID; } - + // Otherwise check in the super class. if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) return FindIvarInterface(Context, Super, OIVD); - + return 0; } llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar) { - if (CGF.getContext().getLangOptions().ObjCNonFragileABI) - { + if (CGM.getLangOptions().ObjCNonFragileABI) { Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); - return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar), - false, "ivar"); + return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad( + ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar")); } uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar); return llvm::ConstantInt::get(LongTy, Offset, "ivar"); } -CodeGen::CGObjCRuntime *CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM){ +CodeGen::CGObjCRuntime * +CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) { return new CGObjCGNU(CGM); } diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index c3354574c7753..4485ed5aee757 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -23,10 +23,14 @@ #include "clang/Basic/LangOptions.h" #include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetData.h" -#include <sstream> +#include <cstdio> using namespace clang; using namespace CodeGen; @@ -35,7 +39,7 @@ using namespace CodeGen; // don't belong in CGObjCRuntime either so we will live with it for // now. -/// FindIvarInterface - Find the interface containing the ivar. +/// FindIvarInterface - Find the interface containing the ivar. /// /// FIXME: We shouldn't need to do this, the containing context should /// be fixed. @@ -54,11 +58,11 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, return OID; ++Index; } - + // Otherwise check in the super class. if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) return FindIvarInterface(Context, Super, OIVD, Index); - + return 0; } @@ -67,13 +71,13 @@ static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, const ObjCImplementationDecl *ID, const ObjCIvarDecl *Ivar) { unsigned Index; - const ObjCInterfaceDecl *Container = + const ObjCInterfaceDecl *Container = FindIvarInterface(CGM.getContext(), OID, Ivar, Index); assert(Container && "Unable to find ivar container"); // If we know have an implementation (and the ivar is in it) then // look up in the implementation layout. - const ASTRecordLayout *RL; + const ASTRecordLayout *RL; if (ID && ID->getClassInterface() == Container) RL = &CGM.getContext().getASTObjCImplementationLayout(ID); else @@ -100,13 +104,16 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, unsigned CVRQualifiers, llvm::Value *Offset) { // Compute (type*) ( (char *) BaseValue + Offset) - llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); QualType IvarTy = Ivar->getType(); const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr); V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); - + + Qualifiers Quals = CGF.MakeQualifiers(IvarTy); + Quals.addCVRQualifiers(CVRQualifiers); + if (Ivar->isBitField()) { // We need to compute the bit offset for the bit-field, the offset // is to the byte. Note, there is a subtle invariant here: we can @@ -119,12 +126,11 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); return LValue::MakeBitfield(V, BitOffset, BitFieldSize, IvarTy->isSignedIntegerType(), - IvarTy.getCVRQualifiers()|CVRQualifiers); + Quals.getCVRQualifiers()); } - LValue LV = LValue::MakeAddr(V, IvarTy.getCVRQualifiers()|CVRQualifiers, - CGF.CGM.getContext().getObjCGCAttrKind(IvarTy)); - LValue::SetObjCIvar(LV, true); + + LValue LV = LValue::MakeAddr(V, Quals); return LV; } @@ -132,12 +138,15 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, namespace { - typedef std::vector<llvm::Constant*> ConstantVector; +typedef std::vector<llvm::Constant*> ConstantVector; - // FIXME: We should find a nicer way to make the labels for metadata, string - // concatenation is lame. +// FIXME: We should find a nicer way to make the labels for metadata, string +// concatenation is lame. class ObjCCommonTypesHelper { +protected: + llvm::LLVMContext &VMContext; + private: llvm::Constant *getMessageSendFn() const { // id objc_msgSend (id, SEL, ...) @@ -145,23 +154,23 @@ private: Params.push_back(ObjectPtrTy); Params.push_back(SelectorPtrTy); return - CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - Params, true), - "objc_msgSend"); + CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, + Params, true), + "objc_msgSend"); } - + llvm::Constant *getMessageSendStretFn() const { // id objc_msgSend_stret (id, SEL, ...) std::vector<const llvm::Type*> Params; Params.push_back(ObjectPtrTy); Params.push_back(SelectorPtrTy); return - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, - Params, true), - "objc_msgSend_stret"); - + CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + Params, true), + "objc_msgSend_stret"); + } - + llvm::Constant *getMessageSendFpretFn() const { // FIXME: This should be long double on x86_64? // [double | long double] objc_msgSend_fpret(id self, SEL op, ...) @@ -169,13 +178,14 @@ private: Params.push_back(ObjectPtrTy); Params.push_back(SelectorPtrTy); return - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::DoubleTy, - Params, - true), - "objc_msgSend_fpret"); - + CGM.CreateRuntimeFunction(llvm::FunctionType::get( + llvm::Type::getDoubleTy(VMContext), + Params, + true), + "objc_msgSend_fpret"); + } - + llvm::Constant *getMessageSendSuperFn() const { // id objc_msgSendSuper(struct objc_super *super, SEL op, ...) const char *SuperName = "objc_msgSendSuper"; @@ -186,7 +196,7 @@ private: Params, true), SuperName); } - + llvm::Constant *getMessageSendSuperFn2() const { // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) const char *SuperName = "objc_msgSendSuper2"; @@ -197,7 +207,7 @@ private: Params, true), SuperName); } - + llvm::Constant *getMessageSendSuperStretFn() const { // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super, // SEL op, ...) @@ -205,11 +215,12 @@ private: Params.push_back(Int8PtrTy); Params.push_back(SuperPtrTy); Params.push_back(SelectorPtrTy); - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, - Params, true), - "objc_msgSendSuper_stret"); + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + Params, true), + "objc_msgSendSuper_stret"); } - + llvm::Constant *getMessageSendSuperStretFn2() const { // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, // SEL op, ...) @@ -217,68 +228,69 @@ private: Params.push_back(Int8PtrTy); Params.push_back(SuperPtrTy); Params.push_back(SelectorPtrTy); - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, - Params, true), - "objc_msgSendSuper2_stret"); + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + Params, true), + "objc_msgSendSuper2_stret"); } - + llvm::Constant *getMessageSendSuperFpretFn() const { // There is no objc_msgSendSuper_fpret? How can that work? return getMessageSendSuperFn(); } - + llvm::Constant *getMessageSendSuperFpretFn2() const { // There is no objc_msgSendSuper_fpret? How can that work? return getMessageSendSuperFn2(); } - + protected: CodeGen::CodeGenModule &CGM; - + public: const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy; const llvm::Type *Int8PtrTy; - + /// ObjectPtrTy - LLVM type for object handles (typeof(id)) const llvm::Type *ObjectPtrTy; - + /// PtrObjectPtrTy - LLVM type for id * const llvm::Type *PtrObjectPtrTy; - + /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL)) const llvm::Type *SelectorPtrTy; /// ProtocolPtrTy - LLVM type for external protocol handles /// (typeof(Protocol)) const llvm::Type *ExternalProtocolPtrTy; - + // SuperCTy - clang type for struct objc_super. QualType SuperCTy; // SuperPtrCTy - clang type for struct objc_super *. QualType SuperPtrCTy; - + /// SuperTy - LLVM type for struct objc_super. const llvm::StructType *SuperTy; /// SuperPtrTy - LLVM type for struct objc_super *. const llvm::Type *SuperPtrTy; - + /// PropertyTy - LLVM type for struct objc_property (struct _prop_t /// in GCC parlance). const llvm::StructType *PropertyTy; - + /// PropertyListTy - LLVM type for struct objc_property_list /// (_prop_list_t in GCC parlance). const llvm::StructType *PropertyListTy; /// PropertyListPtrTy - LLVM type for struct objc_property_list*. const llvm::Type *PropertyListPtrTy; - + // MethodTy - LLVM type for struct objc_method. const llvm::StructType *MethodTy; - + /// CacheTy - LLVM type for struct objc_cache. const llvm::Type *CacheTy; /// CachePtrTy - LLVM type for struct objc_cache *. const llvm::Type *CachePtrTy; - + llvm::Constant *getGetPropertyFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); @@ -294,7 +306,7 @@ public: Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false); return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); } - + llvm::Constant *getSetPropertyFn() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); @@ -312,25 +324,28 @@ public: Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false); return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); } - + llvm::Constant *getEnumerationMutationFn() { + CodeGen::CodeGenTypes &Types = CGM.getTypes(); + ASTContext &Ctx = CGM.getContext(); // void objc_enumerationMutation (id) - std::vector<const llvm::Type*> Args; - Args.push_back(ObjectPtrTy); - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::SmallVector<QualType,16> Params; + Params.push_back(Ctx.getObjCIdType()); + const llvm::FunctionType *FTy = + Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false); return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); } - + /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. llvm::Constant *getGcReadWeakFn() { // id objc_read_weak (id *) std::vector<const llvm::Type*> Args; Args.push_back(ObjectPtrTy->getPointerTo()); - llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, Args, false); + llvm::FunctionType *FTy = + llvm::FunctionType::get(ObjectPtrTy, Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); - } - + } + /// GcAssignWeakFn -- LLVM objc_assign_weak function. llvm::Constant *getGcAssignWeakFn() { // id objc_assign_weak (id, id *) @@ -340,31 +355,45 @@ public: llvm::FunctionType::get(ObjectPtrTy, Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); } - + /// GcAssignGlobalFn -- LLVM objc_assign_global function. llvm::Constant *getGcAssignGlobalFn() { // id objc_assign_global(id, id *) std::vector<const llvm::Type*> Args(1, ObjectPtrTy); Args.push_back(ObjectPtrTy->getPointerTo()); - llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, Args, false); + llvm::FunctionType *FTy = + llvm::FunctionType::get(ObjectPtrTy, Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); } - + /// GcAssignIvarFn -- LLVM objc_assign_ivar function. llvm::Constant *getGcAssignIvarFn() { - // id objc_assign_ivar(id, id *) + // id objc_assign_ivar(id, id *, ptrdiff_t) std::vector<const llvm::Type*> Args(1, ObjectPtrTy); Args.push_back(ObjectPtrTy->getPointerTo()); - llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, Args, false); + Args.push_back(LongTy); + llvm::FunctionType *FTy = + llvm::FunctionType::get(ObjectPtrTy, Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); } - + + /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. + llvm::Constant *GcMemmoveCollectableFn() { + // void *objc_memmove_collectable(void *dst, const void *src, size_t size) + std::vector<const llvm::Type*> Args(1, Int8PtrTy); + Args.push_back(Int8PtrTy); + Args.push_back(LongTy); + llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false); + return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); + } + /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. llvm::Constant *getGcAssignStrongCastFn() { // id objc_assign_global(id, id *) std::vector<const llvm::Type*> Args(1, ObjectPtrTy); Args.push_back(ObjectPtrTy->getPointerTo()); - llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, Args, false); + llvm::FunctionType *FTy = + llvm::FunctionType::get(ObjectPtrTy, Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); } @@ -373,52 +402,52 @@ public: // void objc_exception_throw(id) std::vector<const llvm::Type*> Args(1, ObjectPtrTy); llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); } - + /// SyncEnterFn - LLVM object_sync_enter function. llvm::Constant *getSyncEnterFn() { // void objc_sync_enter (id) std::vector<const llvm::Type*> Args(1, ObjectPtrTy); llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); } - + /// SyncExitFn - LLVM object_sync_exit function. llvm::Constant *getSyncExitFn() { // void objc_sync_exit (id) std::vector<const llvm::Type*> Args(1, ObjectPtrTy); llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::VoidTy, Args, false); + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); } - + llvm::Constant *getSendFn(bool IsSuper) const { return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); } - + llvm::Constant *getSendFn2(bool IsSuper) const { return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); } - + llvm::Constant *getSendStretFn(bool IsSuper) const { return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); } - + llvm::Constant *getSendStretFn2(bool IsSuper) const { return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); } - + llvm::Constant *getSendFpretFn(bool IsSuper) const { return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); } - + llvm::Constant *getSendFpretFn2(bool IsSuper) const { return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); } - + ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm); ~ObjCCommonTypesHelper(){} }; @@ -477,26 +506,28 @@ public: const llvm::Type *MethodListTy; /// MethodListPtrTy - LLVM type for struct objc_method_list *. const llvm::Type *MethodListPtrTy; - + /// ExceptionDataTy - LLVM type for struct _objc_exception_data. const llvm::Type *ExceptionDataTy; - + /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. llvm::Constant *getExceptionTryEnterFn() { std::vector<const llvm::Type*> Params; Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, - Params, false), - "objc_exception_try_enter"); + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + Params, false), + "objc_exception_try_enter"); } /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. llvm::Constant *getExceptionTryExitFn() { std::vector<const llvm::Type*> Params; Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, - Params, false), - "objc_exception_try_exit"); + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + Params, false), + "objc_exception_try_exit"); } /// ExceptionExtractFn - LLVM objc_exception_extract function. @@ -506,31 +537,32 @@ public: return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, Params, false), "objc_exception_extract"); - + } - + /// ExceptionMatchFn - LLVM objc_exception_match function. llvm::Constant *getExceptionMatchFn() { std::vector<const llvm::Type*> Params; Params.push_back(ClassPtrTy); Params.push_back(ObjectPtrTy); - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty, - Params, false), - "objc_exception_match"); - + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), + Params, false), + "objc_exception_match"); + } - + /// SetJmpFn - LLVM _setjmp function. llvm::Constant *getSetJmpFn() { std::vector<const llvm::Type*> Params; - Params.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty)); + Params.push_back(llvm::Type::getInt32PtrTy(VMContext)); return - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty, + CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), Params, false), "_setjmp"); - + } - + public: ObjCTypesHelper(CodeGen::CodeGenModule &cgm); ~ObjCTypesHelper() {} @@ -540,51 +572,51 @@ public: /// modern abi class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { public: - + // MethodListnfABITy - LLVM for struct _method_list_t const llvm::StructType *MethodListnfABITy; - + // MethodListnfABIPtrTy - LLVM for struct _method_list_t* const llvm::Type *MethodListnfABIPtrTy; - + // ProtocolnfABITy = LLVM for struct _protocol_t const llvm::StructType *ProtocolnfABITy; - + // ProtocolnfABIPtrTy = LLVM for struct _protocol_t* const llvm::Type *ProtocolnfABIPtrTy; // ProtocolListnfABITy - LLVM for struct _objc_protocol_list const llvm::StructType *ProtocolListnfABITy; - + // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list* const llvm::Type *ProtocolListnfABIPtrTy; - + // ClassnfABITy - LLVM for struct _class_t const llvm::StructType *ClassnfABITy; - + // ClassnfABIPtrTy - LLVM for struct _class_t* const llvm::Type *ClassnfABIPtrTy; - + // IvarnfABITy - LLVM for struct _ivar_t const llvm::StructType *IvarnfABITy; - + // IvarListnfABITy - LLVM for struct _ivar_list_t const llvm::StructType *IvarListnfABITy; - + // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t* const llvm::Type *IvarListnfABIPtrTy; - + // ClassRonfABITy - LLVM for struct _class_ro_t const llvm::StructType *ClassRonfABITy; - + // ImpnfABITy - LLVM for id (*)(id, SEL, ...) const llvm::Type *ImpnfABITy; - + // CategorynfABITy - LLVM for struct _category_t const llvm::StructType *CategorynfABITy; - + // New types for nonfragile abi messaging. - + // MessageRefTy - LLVM for: // struct _message_ref_t { // IMP messenger; @@ -593,22 +625,22 @@ public: const llvm::StructType *MessageRefTy; // MessageRefCTy - clang type for struct _message_ref_t QualType MessageRefCTy; - + // MessageRefPtrTy - LLVM for struct _message_ref_t* const llvm::Type *MessageRefPtrTy; // MessageRefCPtrTy - clang type for struct _message_ref_t* QualType MessageRefCPtrTy; - + // MessengerTy - Type of the messenger (shown as IMP above) const llvm::FunctionType *MessengerTy; - + // SuperMessageRefTy - LLVM for: // struct _super_message_ref_t { // SUPER_IMP messenger; // SEL name; // }; const llvm::StructType *SuperMessageRefTy; - + // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* const llvm::Type *SuperMessageRefPtrTy; @@ -621,7 +653,7 @@ public: Params, true), "objc_msgSend_fixup"); } - + llvm::Constant *getMessageSendFpretFixupFn() { // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) std::vector<const llvm::Type*> Params; @@ -631,7 +663,7 @@ public: Params, true), "objc_msgSend_fpret_fixup"); } - + llvm::Constant *getMessageSendStretFixupFn() { // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) std::vector<const llvm::Type*> Params; @@ -641,7 +673,7 @@ public: Params, true), "objc_msgSend_stret_fixup"); } - + llvm::Constant *getMessageSendIdFixupFn() { // id objc_msgSendId_fixup(id, struct message_ref_t*, ...) std::vector<const llvm::Type*> Params; @@ -651,7 +683,7 @@ public: Params, true), "objc_msgSendId_fixup"); } - + llvm::Constant *getMessageSendIdStretFixupFn() { // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...) std::vector<const llvm::Type*> Params; @@ -662,7 +694,7 @@ public: "objc_msgSendId_stret_fixup"); } llvm::Constant *getMessageSendSuper2FixupFn() { - // id objc_msgSendSuper2_fixup (struct objc_super *, + // id objc_msgSendSuper2_fixup (struct objc_super *, // struct _super_message_ref_t*, ...) std::vector<const llvm::Type*> Params; Params.push_back(SuperPtrTy); @@ -671,9 +703,9 @@ public: Params, true), "objc_msgSendSuper2_fixup"); } - + llvm::Constant *getMessageSendSuper2StretFixupFn() { - // id objc_msgSendSuper2_stret_fixup(struct objc_super *, + // id objc_msgSendSuper2_stret_fixup(struct objc_super *, // struct _super_message_ref_t*, ...) std::vector<const llvm::Type*> Params; Params.push_back(SuperPtrTy); @@ -682,34 +714,35 @@ public: Params, true), "objc_msgSendSuper2_stret_fixup"); } - - - + + + /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C /// exception personality function. llvm::Value *getEHPersonalityPtr() { - llvm::Constant *Personality = - CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty, + llvm::Constant *Personality = + CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), true), - "__objc_personality_v0"); + "__objc_personality_v0"); return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy); } llvm::Constant *getUnwindResumeOrRethrowFn() { std::vector<const llvm::Type*> Params; Params.push_back(Int8PtrTy); - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, - Params, false), - "_Unwind_Resume_or_Rethrow"); + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), + Params, false), + "_Unwind_Resume_or_Rethrow"); } - + llvm::Constant *getObjCEndCatchFn() { - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, + return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false), "objc_end_catch"); - + } - + llvm::Constant *getObjCBeginCatchFn() { std::vector<const llvm::Type*> Params; Params.push_back(Int8PtrTy); @@ -724,7 +757,7 @@ public: ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); ~ObjCNonFragileABITypesHelper(){} }; - + class CGObjCCommonMac : public CodeGen::CGObjCRuntime { public: // FIXME - accessibility @@ -733,129 +766,126 @@ public: unsigned ivar_bytepos; unsigned ivar_size; GC_IVAR(unsigned bytepos = 0, unsigned size = 0) - : ivar_bytepos(bytepos), ivar_size(size) {} + : ivar_bytepos(bytepos), ivar_size(size) {} // Allow sorting based on byte pos. bool operator<(const GC_IVAR &b) const { return ivar_bytepos < b.ivar_bytepos; } }; - + class SKIP_SCAN { public: unsigned skip; unsigned scan; - SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) + SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) : skip(_skip), scan(_scan) {} }; - + protected: CodeGen::CodeGenModule &CGM; + llvm::LLVMContext &VMContext; // FIXME! May not be needing this after all. unsigned ObjCABI; - + // gc ivar layout bitmap calculation helper caches. llvm::SmallVector<GC_IVAR, 16> SkipIvars; llvm::SmallVector<GC_IVAR, 16> IvarsInfo; - + /// LazySymbols - Symbols to generate a lazy reference for. See /// DefinedSymbols and FinishModule(). - std::set<IdentifierInfo*> LazySymbols; - + llvm::SetVector<IdentifierInfo*> LazySymbols; + /// DefinedSymbols - External symbols which are defined by this /// module. The symbols in this list and LazySymbols are used to add /// special linker symbols which ensure that Objective-C modules are /// linked properly. - std::set<IdentifierInfo*> DefinedSymbols; - + llvm::SetVector<IdentifierInfo*> DefinedSymbols; + /// ClassNames - uniqued class names. llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames; - + /// MethodVarNames - uniqued method variable names. llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; - + /// MethodVarTypes - uniqued method type signatures. We have to use /// a StringMap here because have no other unique reference. llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes; - + /// MethodDefinitions - map of methods which have been defined in /// this translation unit. llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions; - + /// PropertyNames - uniqued method variable names. llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames; - + /// ClassReferences - uniqued class references. llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences; - + /// SelectorReferences - uniqued selector references. llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; - + /// Protocols - Protocols for which an objc_protocol structure has /// been emitted. Forward declarations are handled by creating an /// empty structure whose initializer is filled in when/if defined. llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols; - + /// DefinedProtocols - Protocols which have actually been /// defined. We should not need this, see FIXME in GenerateProtocol. llvm::DenseSet<IdentifierInfo*> DefinedProtocols; - + /// DefinedClasses - List of defined classes. std::vector<llvm::GlobalValue*> DefinedClasses; /// DefinedNonLazyClasses - List of defined "non-lazy" classes. std::vector<llvm::GlobalValue*> DefinedNonLazyClasses; - + /// DefinedCategories - List of defined categories. std::vector<llvm::GlobalValue*> DefinedCategories; - + /// DefinedNonLazyCategories - List of defined "non-lazy" categories. std::vector<llvm::GlobalValue*> DefinedNonLazyCategories; - - /// UsedGlobals - List of globals to pack into the llvm.used metadata - /// to prevent them from being clobbered. - std::vector<llvm::GlobalVariable*> UsedGlobals; /// GetNameForMethod - Return a name for the given method. /// \param[out] NameOut - The return value. void GetNameForMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD, std::string &NameOut); - + /// GetMethodVarName - Return a unique constant for the given /// selector's name. The return value has type char *. llvm::Constant *GetMethodVarName(Selector Sel); llvm::Constant *GetMethodVarName(IdentifierInfo *Ident); llvm::Constant *GetMethodVarName(const std::string &Name); - + /// GetMethodVarType - Return a unique constant for the given /// selector's name. The return value has type char *. - + // FIXME: This is a horrible name. llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D); llvm::Constant *GetMethodVarType(const FieldDecl *D); - + /// GetPropertyName - Return a unique constant for the given /// name. The return value has type char *. llvm::Constant *GetPropertyName(IdentifierInfo *Ident); - + // FIXME: This can be dropped once string functions are unified. llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, const Decl *Container); - + /// GetClassName - Return a unique constant for the given selector's /// name. The return value has type char *. llvm::Constant *GetClassName(IdentifierInfo *Ident); - + /// BuildIvarLayout - Builds ivar layout bitmap for the class /// implementation for the __strong or __weak case. /// llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, bool ForStrongLayout); - + void BuildAggrIvarRecordLayout(const RecordType *RT, - unsigned int BytePos, bool ForStrongLayout, - bool &HasUnion); + unsigned int BytePos, bool ForStrongLayout, + bool &HasUnion); void BuildAggrIvarLayout(const ObjCImplementationDecl *OI, const llvm::StructLayout *Layout, const RecordDecl *RD, @@ -867,14 +897,14 @@ protected: /// ivar layout bitmap. llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident, const ObjCCommonTypesHelper &ObjCTypes); - + /// EmitPropertyList - Emit the given property list. The return /// value has type PropertyListPtrTy. llvm::Constant *EmitPropertyList(const std::string &Name, - const Decl *Container, + const Decl *Container, const ObjCContainerDecl *OCD, const ObjCCommonTypesHelper &ObjCTypes); - + /// GetProtocolRef - Return a reference to the internal protocol /// description, creating an empty one if it has not been /// defined. The return value has type ProtocolPtrTy. @@ -885,7 +915,7 @@ protected: /// /// This is a convenience wrapper which not only creates the /// variable, but also sets the section and alignment and adds the - /// global to the UsedGlobals list. + /// global to the "llvm.used" list. /// /// \param Name - The variable name. /// \param Init - The variable initializer; this is also used to @@ -907,33 +937,32 @@ protected: QualType Arg0Ty, bool IsSuper, const CallArgList &CallArgs, + const ObjCMethodDecl *OMD, const ObjCCommonTypesHelper &ObjCTypes); - virtual void MergeMetadataGlobals(std::vector<llvm::Constant*> &UsedArray); - public: - CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm) - { } - + CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : + CGM(cgm), VMContext(cgm.getLLVMContext()) { } + virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *SL); - + virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD=0); - + virtual void GenerateProtocol(const ObjCProtocolDecl *PD); - + /// GetOrEmitProtocol - Get the protocol object for the given /// declaration, emitting it if necessary. The return value has type /// ProtocolPtrTy. virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0; - + /// GetOrEmitProtocolRef - Get a forward reference to the protocol /// object for the given declaration, emitting it if needed. These /// forward references will be filled in with empty bodies if no /// definition is seen. The return value has type ProtocolPtrTy. virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; }; - + class CGObjCMac : public CGObjCCommonMac { private: ObjCTypesHelper ObjCTypes; @@ -942,7 +971,7 @@ private: void EmitImageInfo(); /// EmitModuleInfo - Another marker encoding module level - /// information. + /// information. void EmitModuleInfo(); /// EmitModuleSymols - Emit module symbols, the list of defined @@ -960,7 +989,7 @@ private: /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given class. - llvm::Value *EmitClassRef(CGBuilderTy &Builder, + llvm::Value *EmitClassRef(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, @@ -978,7 +1007,7 @@ private: /// IvarListPtrTy. llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, bool ForClass); - + /// EmitMetaClass - Emit a forward reference to the class structure /// for the metaclass of the given interface. The return value has /// type ClassPtrTy. @@ -989,9 +1018,9 @@ private: llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID, llvm::Constant *Protocols, const ConstantVector &Methods); - + llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); - + llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); /// EmitMethodList - Emit the method list for the given @@ -1001,7 +1030,7 @@ private: const ConstantVector &Methods); /// EmitMethodDescList - Emit a method description list for a list of - /// method declarations. + /// method declarations. /// - TypeName: The name for the type containing the methods. /// - IsProtocol: True iff these methods are for a protocol. /// - ClassMethds: True iff these are class methods. @@ -1044,12 +1073,12 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); - - public: + +public: CGObjCMac(CodeGen::CodeGenModule &cgm); virtual llvm::Function *ModuleInitFunction(); - + virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -1058,7 +1087,7 @@ private: const CallArgList &CallArgs, const ObjCMethodDecl *Method); - virtual CodeGen::RValue + virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -1066,8 +1095,9 @@ private: bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs); - + const CallArgList &CallArgs, + const ObjCMethodDecl *Method); + virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); @@ -1084,26 +1114,30 @@ private: virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD); - + virtual llvm::Constant *GetPropertyGetFunction(); virtual llvm::Constant *GetPropertySetFunction(); virtual llvm::Constant *EnumerationMutationFunction(); - + virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S); virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - llvm::Value *AddrWeakObj); + llvm::Value *AddrWeakObj); virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst); + llvm::Value *src, llvm::Value *dst); virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dest); + llvm::Value *src, llvm::Value *dest, + llvm::Value *ivarOffset); virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); - + virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, + llvm::Value *dest, llvm::Value *src, + QualType Ty); + virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, @@ -1113,30 +1147,30 @@ private: const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); }; - + class CGObjCNonFragileABIMac : public CGObjCCommonMac { private: ObjCNonFragileABITypesHelper ObjCTypes; llvm::GlobalVariable* ObjCEmptyCacheVar; llvm::GlobalVariable* ObjCEmptyVtableVar; - + /// SuperClassReferences - uniqued super class references. llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences; - + /// MetaClassReferences - uniqued meta class references. llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences; /// EHTypeReferences - uniqued class ehtype references. llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences; - + /// NonLegacyDispatchMethods - List of methods for which we do *not* generate /// legacy messaging dispatch. llvm::DenseSet<Selector> NonLegacyDispatchMethods; - + /// LegacyDispatchedSelector - Returns true if SEL is not in the list of /// NonLegacyDispatchMethods; false otherwise. bool LegacyDispatchedSelector(Selector Sel); - + /// FinishNonFragileABIModule - Write out global data structures at the end of /// processing a translation unit. void FinishNonFragileABIModule(); @@ -1147,20 +1181,20 @@ private: const char *SymbolName, const char *SectionName); - llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, - unsigned InstanceStart, - unsigned InstanceSize, - const ObjCImplementationDecl *ID); + llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, + unsigned InstanceStart, + unsigned InstanceSize, + const ObjCImplementationDecl *ID); llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName, - llvm::Constant *IsAGV, + llvm::Constant *IsAGV, llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV, bool HiddenVisibility); - + llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); - + llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); - + /// EmitMethodList - Emit the method list for the given /// implementation. The return value has type MethodListnfABITy. llvm::Constant *EmitMethodList(const std::string &Name, @@ -1172,28 +1206,28 @@ private: /// interface ivars will be emitted. The return value has type /// IvarListnfABIPtrTy. llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); - + llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, const ObjCIvarDecl *Ivar, unsigned long int offset); - + /// GetOrEmitProtocol - Get the protocol object for the given /// declaration, emitting it if necessary. The return value has type /// ProtocolPtrTy. virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); - + /// GetOrEmitProtocolRef - Get a forward reference to the protocol /// object for the given declaration, emitting it if needed. These /// forward references will be filled in with empty bodies if no /// definition is seen. The return value has type ProtocolPtrTy. virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); - + /// EmitProtocolList - Generate the list of referenced /// protocols. The return value has type ProtocolListPtrTy. llvm::Constant *EmitProtocolList(const std::string &Name, ObjCProtocolDecl::protocol_iterator begin, ObjCProtocolDecl::protocol_iterator end); - + CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -1205,29 +1239,29 @@ private: /// GetClassGlobal - Return the global variable for the Objective-C /// class of the given name. llvm::GlobalVariable *GetClassGlobal(const std::string &Name); - + /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given class reference. - llvm::Value *EmitClassRef(CGBuilderTy &Builder, + llvm::Value *EmitClassRef(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); - + /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given super class reference. - llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder, - const ObjCInterfaceDecl *ID); - + llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder, + const ObjCInterfaceDecl *ID); + /// EmitMetaClassRef - Return a Value * of the address of _class_t /// meta-data - llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder, + llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); /// ObjCIvarOffsetVariable - Returns the ivar offset variable for /// the given ivar. /// llvm::GlobalVariable * ObjCIvarOffsetVariable( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar); - + const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar); + /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); @@ -1237,10 +1271,10 @@ private: llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID, bool ForDefinition); - const char *getMetaclassSymbolPrefix() const { + const char *getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; } - + const char *getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; } @@ -1248,13 +1282,13 @@ private: void GetClassSizeInfo(const ObjCImplementationDecl *OID, uint32_t &InstanceStart, uint32_t &InstanceSize); - + // Shamelessly stolen from Analysis/CFRefCount.cpp Selector GetNullarySelector(const char* name) const { IdentifierInfo* II = &CGM.getContext().Idents.get(name); return CGM.getContext().Selectors.getSelector(0, &II); } - + Selector GetUnarySelector(const char* name) const { IdentifierInfo* II = &CGM.getContext().Idents.get(name); return CGM.getContext().Selectors.getSelector(1, &II); @@ -1268,7 +1302,7 @@ public: CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); // FIXME. All stubs for now! virtual llvm::Function *ModuleInitFunction(); - + virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -1276,8 +1310,8 @@ public: bool IsClassMessage, const CallArgList &CallArgs, const ObjCMethodDecl *Method); - - virtual CodeGen::RValue + + virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -1285,11 +1319,12 @@ public: bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, - const CallArgList &CallArgs); - + const CallArgList &CallArgs, + const ObjCMethodDecl *Method); + virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID); - + virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel) { return EmitSelector(Builder, Sel); } @@ -1298,23 +1333,23 @@ public: virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method) { return EmitSelector(Builder, Method->getSelector()); } - + virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); - + virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD); - - virtual llvm::Constant *GetPropertyGetFunction() { + + virtual llvm::Constant *GetPropertyGetFunction() { return ObjCTypes.getGetPropertyFn(); } - virtual llvm::Constant *GetPropertySetFunction() { - return ObjCTypes.getSetPropertyFn(); + virtual llvm::Constant *GetPropertySetFunction() { + return ObjCTypes.getSetPropertyFn(); } virtual llvm::Constant *EnumerationMutationFunction() { return ObjCTypes.getEnumerationMutationFn(); } - + virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, @@ -1326,9 +1361,13 @@ public: virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dest); + llvm::Value *src, llvm::Value *dest, + llvm::Value *ivarOffset); virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest); + virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, + llvm::Value *dest, llvm::Value *src, + QualType Ty); virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, @@ -1338,25 +1377,26 @@ public: const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); }; - + } // end anonymous namespace /* *** Helper Functions *** */ /// getConstantGEP() - Help routine to construct simple GEPs. -static llvm::Constant *getConstantGEP(llvm::Constant *C, +static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, + llvm::Constant *C, unsigned idx0, unsigned idx1) { llvm::Value *Idxs[] = { - llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0), - llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1) + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) }; return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2); } /// hasObjCExceptionAttribute - Return true if this class or any super /// class has the __objc_exception__ attribute. -static bool hasObjCExceptionAttribute(ASTContext &Context, +static bool hasObjCExceptionAttribute(ASTContext &Context, const ObjCInterfaceDecl *OID) { if (OID->hasAttr<ObjCExceptionAttr>()) return true; @@ -1366,12 +1406,11 @@ static bool hasObjCExceptionAttribute(ASTContext &Context, } /* *** CGObjCMac Public Interface *** */ - + CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), - ObjCTypes(cgm) -{ + ObjCTypes(cgm) { ObjCABI = 1; - EmitImageInfo(); + EmitImageInfo(); } /// GetClass - Return a reference to the class for the given interface @@ -1386,18 +1425,18 @@ llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) { return EmitSelector(Builder, Sel); } llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl - *Method) { + *Method) { return EmitSelector(Builder, Method->getSelector()); } /// Generate a constant CFString object. -/* - struct __builtin_CFString { - const int *isa; // point to __CFConstantStringClassReference - int flags; - const char *str; - long length; - }; +/* + struct __builtin_CFString { + const int *isa; // point to __CFConstantStringClassReference + int flags; + const char *str; + long length; + }; */ llvm::Constant *CGObjCCommonMac::GenerateConstantString( @@ -1416,14 +1455,15 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, - const CodeGen::CallArgList &CallArgs) { + const CodeGen::CallArgList &CallArgs, + const ObjCMethodDecl *Method) { // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - llvm::Value *ObjCSuper = + llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); - llvm::Value *ReceiverAsObject = + llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); - CGF.Builder.CreateStore(ReceiverAsObject, + CGF.Builder.CreateStore(ReceiverAsObject, CGF.Builder.CreateStructGEP(ObjCSuper, 0)); // If this is a class message the metaclass is passed as the target. @@ -1439,30 +1479,29 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); Target = CGF.Builder.CreateStructGEP(Target, 0); Target = CGF.Builder.CreateLoad(Target); - } - else { + } else { llvm::Value *MetaClassPtr = EmitMetaClassRef(Class); llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1); llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr); Target = Super; - } + } } else { Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); } // FIXME: We shouldn't need to do this cast, rectify the ASTContext and // ObjCTypes types. - const llvm::Type *ClassTy = + const llvm::Type *ClassTy = CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); Target = CGF.Builder.CreateBitCast(Target, ClassTy); - CGF.Builder.CreateStore(Target, + CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); - return EmitLegacyMessageSend(CGF, ResultType, + return EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel), ObjCSuper, ObjCTypes.SuperPtrCTy, - true, CallArgs, ObjCTypes); + true, CallArgs, Method, ObjCTypes); } - -/// Generate code for a message send expression. + +/// Generate code for a message send expression. CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, @@ -1473,18 +1512,19 @@ CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, return EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel), Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs, ObjCTypes); + false, CallArgs, Method, ObjCTypes); } -CodeGen::RValue CGObjCCommonMac::EmitLegacyMessageSend( - CodeGen::CodeGenFunction &CGF, - QualType ResultType, - llvm::Value *Sel, - llvm::Value *Arg0, - QualType Arg0Ty, - bool IsSuper, - const CallArgList &CallArgs, - const ObjCCommonTypesHelper &ObjCTypes) { +CodeGen::RValue +CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, + QualType ResultType, + llvm::Value *Sel, + llvm::Value *Arg0, + QualType Arg0Ty, + bool IsSuper, + const CallArgList &CallArgs, + const ObjCMethodDecl *Method, + const ObjCCommonTypesHelper &ObjCTypes) { CallArgList ActualArgs; if (!IsSuper) Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); @@ -1492,41 +1532,40 @@ CodeGen::RValue CGObjCCommonMac::EmitLegacyMessageSend( ActualArgs.push_back(std::make_pair(RValue::get(Sel), CGF.getContext().getObjCSelType())); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); - + CodeGenTypes &Types = CGM.getTypes(); const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs); - // In 64bit ABI, type must be assumed VARARG. In 32bit abi, - // it seems not to matter. - const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo, (ObjCABI == 2)); - + const llvm::FunctionType *FTy = + Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); + llvm::Constant *Fn = NULL; if (CGM.ReturnTypeUsesSret(FnInfo)) { Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) - : ObjCTypes.getSendStretFn(IsSuper); + : ObjCTypes.getSendStretFn(IsSuper); } else if (ResultType->isFloatingType()) { if (ObjCABI == 2) { - if (const BuiltinType *BT = ResultType->getAsBuiltinType()) { + if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) { BuiltinType::Kind k = BT->getKind(); Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper) - : ObjCTypes.getSendFn2(IsSuper); + : ObjCTypes.getSendFn2(IsSuper); } else { Fn = ObjCTypes.getSendFn2(IsSuper); } - } - else + } else // FIXME. This currently matches gcc's API for x86-32. May need to change // for others if we have their API. Fn = ObjCTypes.getSendFpretFn(IsSuper); } else { Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) - : ObjCTypes.getSendFn(IsSuper); + : ObjCTypes.getSendFn(IsSuper); } assert(Fn && "EmitLegacyMessageSend - unknown API"); - Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy)); + Fn = llvm::ConstantExpr::getBitCast(Fn, + llvm::PointerType::getUnqual(FTy)); return CGF.EmitCall(FnInfo, Fn, ActualArgs); } -llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, +llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD) { // FIXME: I don't understand why gcc generates this, or where it is // resolved. Investigate. Its also wasteful to look this up over and over. @@ -1544,7 +1583,7 @@ void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { // If we have generated a forward reference to this protocol, emit // it now. Otherwise do nothing, the protocol objects are lazily // emitted. - if (Protocols.count(PD->getIdentifier())) + if (Protocols.count(PD->getIdentifier())) GetOrEmitProtocol(PD); } @@ -1555,16 +1594,16 @@ llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { } /* - // APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions - struct _objc_protocol { - struct _objc_protocol_extension *isa; - char *protocol_name; - struct _objc_protocol_list *protocol_list; - struct _objc__method_prototype_list *instance_methods; - struct _objc__method_prototype_list *class_methods - }; +// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions +struct _objc_protocol { +struct _objc_protocol_extension *isa; +char *protocol_name; +struct _objc_protocol_list *protocol_list; +struct _objc__method_prototype_list *instance_methods; +struct _objc__method_prototype_list *class_methods +}; - See EmitProtocolExtension(). +See EmitProtocolExtension(). */ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; @@ -1582,7 +1621,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { // Construct method lists. std::vector<llvm::Constant*> InstanceMethods, ClassMethods; std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; - for (ObjCProtocolDecl::instmeth_iterator + for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); @@ -1590,10 +1629,10 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { OptInstanceMethods.push_back(C); } else { InstanceMethods.push_back(C); - } + } } - for (ObjCProtocolDecl::classmeth_iterator + for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); @@ -1601,46 +1640,45 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { OptClassMethods.push_back(C); } else { ClassMethods.push_back(C); - } + } } std::vector<llvm::Constant*> Values(5); Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods); Values[1] = GetClassName(PD->getIdentifier()); - Values[2] = + Values[2] = EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(), PD->protocol_begin(), PD->protocol_end()); - Values[3] = + Values[3] = EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" - + PD->getNameAsString(), + + PD->getNameAsString(), "__OBJC,__cat_inst_meth,regular,no_dead_strip", InstanceMethods); - Values[4] = - EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" - + PD->getNameAsString(), + Values[4] = + EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + + PD->getNameAsString(), "__OBJC,__cat_cls_meth,regular,no_dead_strip", ClassMethods); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, Values); - + if (Entry) { // Already created, fix the linkage and update the initializer. Entry->setLinkage(llvm::GlobalValue::InternalLinkage); Entry->setInitializer(Init); } else { - Entry = - new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false, + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, llvm::GlobalValue::InternalLinkage, - Init, - std::string("\01L_OBJC_PROTOCOL_")+ProtocolName, - &CGM.getModule()); + Init, + std::string("\01L_OBJC_PROTOCOL_")+ProtocolName); Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); Entry->setAlignment(4); - UsedGlobals.push_back(Entry); // FIXME: Is this necessary? Why only for protocol? Entry->setAlignment(4); } + CGM.AddUsedGlobal(Entry); return Entry; } @@ -1652,71 +1690,69 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { // We use the initializer as a marker of whether this is a forward // reference or not. At module finalization we add the empty // contents for protocols which were referenced but never defined. - Entry = - new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false, + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, llvm::GlobalValue::ExternalLinkage, 0, - "\01L_OBJC_PROTOCOL_" + PD->getNameAsString(), - &CGM.getModule()); + "\01L_OBJC_PROTOCOL_" + PD->getNameAsString()); Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); Entry->setAlignment(4); - UsedGlobals.push_back(Entry); // FIXME: Is this necessary? Why only for protocol? Entry->setAlignment(4); } - + return Entry; } /* struct _objc_protocol_extension { - uint32_t size; - struct objc_method_description_list *optional_instance_methods; - struct objc_method_description_list *optional_class_methods; - struct objc_property_list *instance_properties; + uint32_t size; + struct objc_method_description_list *optional_instance_methods; + struct objc_method_description_list *optional_class_methods; + struct objc_property_list *instance_properties; }; */ llvm::Constant * CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, const ConstantVector &OptInstanceMethods, const ConstantVector &OptClassMethods) { - uint64_t Size = + uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); std::vector<llvm::Constant*> Values(4); Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); - Values[1] = - EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" - + PD->getNameAsString(), + Values[1] = + EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" + + PD->getNameAsString(), "__OBJC,__cat_inst_meth,regular,no_dead_strip", OptInstanceMethods); - Values[2] = + Values[2] = EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" - + PD->getNameAsString(), + + PD->getNameAsString(), "__OBJC,__cat_cls_meth,regular,no_dead_strip", OptClassMethods); - Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + - PD->getNameAsString(), + Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + + PD->getNameAsString(), 0, PD, ObjCTypes); // Return null if no extension bits are used. - if (Values[1]->isNullValue() && Values[2]->isNullValue() && + if (Values[1]->isNullValue() && Values[2]->isNullValue() && Values[3]->isNullValue()) return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); - llvm::Constant *Init = + llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values); // No special section, but goes in llvm.used return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(), - Init, + Init, 0, 0, true); } /* struct objc_protocol_list { - struct objc_protocol_list *next; - long count; - Protocol *list[]; + struct objc_protocol_list *next; + long count; + Protocol *list[]; }; */ llvm::Constant * @@ -1729,7 +1765,7 @@ CGObjCMac::EmitProtocolList(const std::string &Name, ProtocolRefs.push_back(GetProtocolRef(*begin)); // Just return null for empty protocol lists - if (ProtocolRefs.empty()) + if (ProtocolRefs.empty()) return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); // This list is null terminated. @@ -1738,14 +1774,15 @@ CGObjCMac::EmitProtocolList(const std::string &Name, std::vector<llvm::Constant*> Values(3); // This field is only used by the runtime. Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); - Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1); - Values[2] = - llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy, - ProtocolRefs.size()), + Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, + ProtocolRefs.size() - 1); + Values[2] = + llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy, + ProtocolRefs.size()), ProtocolRefs); - - llvm::Constant *Init = llvm::ConstantStruct::get(Values); - llvm::GlobalVariable *GV = + + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); + llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip", 4, false); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy); @@ -1753,23 +1790,23 @@ CGObjCMac::EmitProtocolList(const std::string &Name, /* struct _objc_property { - const char * const name; - const char * const attributes; + const char * const name; + const char * const attributes; }; struct _objc_property_list { - uint32_t entsize; // sizeof (struct _objc_property) - uint32_t prop_count; - struct _objc_property[prop_count]; + uint32_t entsize; // sizeof (struct _objc_property) + uint32_t prop_count; + struct _objc_property[prop_count]; }; */ llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name, - const Decl *Container, - const ObjCContainerDecl *OCD, - const ObjCCommonTypesHelper &ObjCTypes) { + const Decl *Container, + const ObjCContainerDecl *OCD, + const ObjCCommonTypesHelper &ObjCTypes) { std::vector<llvm::Constant*> Properties, Prop(2); - for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(), - E = OCD->prop_end(); I != E; ++I) { + for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(), + E = OCD->prop_end(); I != E; ++I) { const ObjCPropertyDecl *PD = *I; Prop[0] = GetPropertyName(PD->getIdentifier()); Prop[1] = GetPropertyTypeString(PD, Container); @@ -1781,36 +1818,37 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name, if (Properties.empty()) return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); - unsigned PropertySize = + unsigned PropertySize = CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy); std::vector<llvm::Constant*> Values(3); Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize); Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size()); - llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy, + llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy, Properties.size()); Values[2] = llvm::ConstantArray::get(AT, Properties); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); - llvm::GlobalVariable *GV = - CreateMetadataVar(Name, Init, - (ObjCABI == 2) ? "__DATA, __objc_const" : + llvm::GlobalVariable *GV = + CreateMetadataVar(Name, Init, + (ObjCABI == 2) ? "__DATA, __objc_const" : "__OBJC,__property,regular,no_dead_strip", - (ObjCABI == 2) ? 8 : 4, + (ObjCABI == 2) ? 8 : 4, true); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy); } /* struct objc_method_description_list { - int count; - struct objc_method_description list[]; + int count; + struct objc_method_description list[]; }; */ llvm::Constant * CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { std::vector<llvm::Constant*> Desc(2); - Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), - ObjCTypes.SelectorPtrTy); + Desc[0] = + llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), + ObjCTypes.SelectorPtrTy); Desc[1] = GetMethodVarType(MD); return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy, Desc); @@ -1825,27 +1863,27 @@ llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name, std::vector<llvm::Constant*> Values(2); Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); - llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy, + llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy, Methods.size()); Values[1] = llvm::ConstantArray::get(AT, Methods); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); - return llvm::ConstantExpr::getBitCast(GV, + return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodDescriptionListPtrTy); } /* struct _objc_category { - char *category_name; - char *class_name; - struct _objc_method_list *instance_methods; - struct _objc_method_list *class_methods; - struct _objc_protocol_list *protocols; - uint32_t size; // <rdar://4585769> - struct _objc_property_list *instance_properties; + char *category_name; + char *class_name; + struct _objc_method_list *instance_methods; + struct _objc_method_list *class_methods; + struct _objc_protocol_list *protocols; + uint32_t size; // <rdar://4585769> + struct _objc_property_list *instance_properties; }; - */ +*/ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy); @@ -1854,18 +1892,18 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // w/o an @interface case. Sema should just create one for us as it does for // @implementation so everyone else can live life under a clear blue sky. const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); - const ObjCCategoryDecl *Category = + const ObjCCategoryDecl *Category = Interface->FindCategoryDeclaration(OCD->getIdentifier()); std::string ExtName(Interface->getNameAsString() + "_" + OCD->getNameAsString()); std::vector<llvm::Constant*> InstanceMethods, ClassMethods; - for (ObjCCategoryImplDecl::instmeth_iterator + for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. InstanceMethods.push_back(GetMethodConstant(*i)); } - for (ObjCCategoryImplDecl::classmeth_iterator + for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { // Class methods should always be defined. ClassMethods.push_back(GetMethodConstant(*i)); @@ -1875,17 +1913,17 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Values[0] = GetClassName(OCD->getIdentifier()); Values[1] = GetClassName(Interface->getIdentifier()); LazySymbols.insert(Interface->getIdentifier()); - Values[2] = - EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") + + Values[2] = + EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") + ExtName, "__OBJC,__cat_inst_meth,regular,no_dead_strip", InstanceMethods); - Values[3] = + Values[3] = EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName, "__OBJC,__cat_cls_meth,regular,no_dead_strip", ClassMethods); if (Category) { - Values[4] = + Values[4] = EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName, Category->protocol_begin(), Category->protocol_end()); @@ -1896,16 +1934,16 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // If there is no category @interface then there can be no properties. if (Category) { - Values[6] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName, + Values[6] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_")+ExtName, OCD, Category, ObjCTypes); } else { Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); } - + llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy, Values); - llvm::GlobalVariable *GV = + llvm::GlobalVariable *GV = CreateMetadataVar(std::string("\01L_OBJC_CATEGORY_")+ExtName, Init, "__OBJC,__category,regular,no_dead_strip", 4, true); @@ -1925,36 +1963,36 @@ enum ClassFlags { /* struct _objc_class { - Class isa; - Class super_class; - const char *name; - long version; - long info; - long instance_size; - struct _objc_ivar_list *ivars; - struct _objc_method_list *methods; - struct _objc_cache *cache; - struct _objc_protocol_list *protocols; - // Objective-C 1.0 extensions (<rdr://4585769>) - const char *ivar_layout; - struct _objc_class_ext *ext; + Class isa; + Class super_class; + const char *name; + long version; + long info; + long instance_size; + struct _objc_ivar_list *ivars; + struct _objc_method_list *methods; + struct _objc_cache *cache; + struct _objc_protocol_list *protocols; + // Objective-C 1.0 extensions (<rdr://4585769>) + const char *ivar_layout; + struct _objc_class_ext *ext; }; See EmitClassExtension(); - */ +*/ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { DefinedSymbols.insert(ID->getIdentifier()); std::string ClassName = ID->getNameAsString(); // FIXME: Gross - ObjCInterfaceDecl *Interface = + ObjCInterfaceDecl *Interface = const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); - llvm::Constant *Protocols = + llvm::Constant *Protocols = EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(), Interface->protocol_begin(), Interface->protocol_end()); unsigned Flags = eClassFlags_Factory; - unsigned Size = + unsigned Size = CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8; // FIXME: Set CXX-structors flag. @@ -1962,18 +2000,18 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { Flags |= eClassFlags_Hidden; std::vector<llvm::Constant*> InstanceMethods, ClassMethods; - for (ObjCImplementationDecl::instmeth_iterator + for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. InstanceMethods.push_back(GetMethodConstant(*i)); } - for (ObjCImplementationDecl::classmeth_iterator + for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { // Class methods should always be defined. ClassMethods.push_back(GetMethodConstant(*i)); } - for (ObjCImplementationDecl::propimpl_iterator + for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; @@ -1995,7 +2033,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { // Record a reference to the super class. LazySymbols.insert(Super->getIdentifier()); - Values[ 1] = + Values[ 1] = llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), ObjCTypes.ClassPtrTy); } else { @@ -2007,19 +2045,19 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); Values[ 6] = EmitIvarList(ID, false); - Values[ 7] = + Values[ 7] = EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(), "__OBJC,__inst_meth,regular,no_dead_strip", InstanceMethods); // cache is always NULL. Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); Values[ 9] = Protocols; - Values[10] = BuildIvarLayout(ID, true); + Values[10] = BuildIvarLayout(ID, true); Values[11] = EmitClassExtension(ID); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, Values); - llvm::GlobalVariable *GV = + llvm::GlobalVariable *GV = CreateMetadataVar(std::string("\01L_OBJC_CLASS_")+ClassName, Init, "__OBJC,__class,regular,no_dead_strip", 4, true); @@ -2034,20 +2072,20 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden) Flags |= eClassFlags_Hidden; - + std::vector<llvm::Constant*> Values(12); // The isa for the metaclass is the root of the hierarchy. const ObjCInterfaceDecl *Root = ID->getClassInterface(); while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) Root = Super; - Values[ 0] = + Values[ 0] = llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()), ObjCTypes.ClassPtrTy); // The super class for the metaclass is emitted as the name of the // super class. The runtime fixes this up to point to the // *metaclass* for the super class. if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { - Values[ 1] = + Values[ 1] = llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), ObjCTypes.ClassPtrTy); } else { @@ -2059,7 +2097,7 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); Values[ 6] = EmitIvarList(ID, true); - Values[ 7] = + Values[ 7] = EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(), "__OBJC,__cls_meth,regular,no_dead_strip", Methods); @@ -2084,19 +2122,18 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, GV->setLinkage(llvm::GlobalValue::InternalLinkage); GV->setInitializer(Init); } else { - GV = new llvm::GlobalVariable(ObjCTypes.ClassTy, false, + GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, llvm::GlobalValue::InternalLinkage, - Init, Name, - &CGM.getModule()); + Init, Name); } GV->setSection("__OBJC,__meta_class,regular,no_dead_strip"); GV->setAlignment(4); - UsedGlobals.push_back(GV); + CGM.AddUsedGlobal(GV); return GV; } -llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { +llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString(); // FIXME: Should we look these up somewhere other than the module. Its a bit @@ -2107,31 +2144,31 @@ llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { // Check for an existing forward reference. // Previously, metaclass with internal linkage may have been defined. // pass 'true' as 2nd argument so it is returned. - if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true)) { + if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, + true)) { assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && "Forward metaclass reference has incorrect type."); return GV; } else { // Generate as an external reference to keep a consistent // module. This will be patched up when we emit the metaclass. - return new llvm::GlobalVariable(ObjCTypes.ClassTy, false, + return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, llvm::GlobalValue::ExternalLinkage, 0, - Name, - &CGM.getModule()); + Name); } } /* struct objc_class_ext { - uint32_t size; - const char *weak_ivar_layout; - struct _objc_property_list *properties; + uint32_t size; + const char *weak_ivar_layout; + struct _objc_property_list *properties; }; */ llvm::Constant * CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { - uint64_t Size = + uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy); std::vector<llvm::Constant*> Values(3); @@ -2144,25 +2181,25 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { if (Values[1]->isNullValue() && Values[2]->isNullValue()) return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); - llvm::Constant *Init = + llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values); return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getNameAsString(), - Init, "__OBJC,__class_ext,regular,no_dead_strip", + Init, "__OBJC,__class_ext,regular,no_dead_strip", 4, true); } /* struct objc_ivar { - char *ivar_name; - char *ivar_type; - int ivar_offset; + char *ivar_name; + char *ivar_type; + int ivar_offset; }; struct objc_ivar_list { - int ivar_count; - struct objc_ivar list[count]; + int ivar_count; + struct objc_ivar list[count]; }; - */ +*/ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, bool ForClass) { std::vector<llvm::Constant*> Ivars, Ivar(3); @@ -2174,21 +2211,21 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, // for the class. if (ForClass) return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); - - ObjCInterfaceDecl *OID = + + ObjCInterfaceDecl *OID = const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); - + llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); - + for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { ObjCIvarDecl *IVD = OIvars[i]; // Ignore unnamed bit-fields. if (!IVD->getDeclName()) - continue; + continue; Ivar[0] = GetMethodVarName(IVD->getIdentifier()); Ivar[1] = GetMethodVarType(IVD); - Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, + Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD)); Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar)); } @@ -2202,12 +2239,12 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy, Ivars.size()); Values[1] = llvm::ConstantArray::get(AT, Ivars); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); llvm::GlobalVariable *GV; if (ForClass) GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getNameAsString(), - Init, "__OBJC,__class_vars,regular,no_dead_strip", + Init, "__OBJC,__class_vars,regular,no_dead_strip", 4, true); else GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" @@ -2219,15 +2256,15 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, /* struct objc_method { - SEL method_name; - char *method_types; - void *method; + SEL method_name; + char *method_types; + void *method; }; - + struct objc_method_list { - struct objc_method_list *obsolete; - int count; - struct objc_method methods_list[count]; + struct objc_method_list *obsolete; + int count; + struct objc_method methods_list[count]; }; */ @@ -2239,9 +2276,9 @@ llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) { llvm::Function *Fn = MethodDefinitions[MD]; if (!Fn) return 0; - + std::vector<llvm::Constant*> Method(3); - Method[0] = + Method[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), ObjCTypes.SelectorPtrTy); Method[1] = GetMethodVarType(MD); @@ -2262,7 +2299,7 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name, llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, Methods.size()); Values[2] = llvm::ConstantArray::get(AT, Methods); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); return llvm::ConstantExpr::getBitCast(GV, @@ -2270,14 +2307,14 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name, } llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD) { + const ObjCContainerDecl *CD) { std::string Name; GetNameForMethod(OMD, CD, Name); CodeGenTypes &Types = CGM.getTypes(); const llvm::FunctionType *MethodTy = Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); - llvm::Function *Method = + llvm::Function *Method = llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage, Name, @@ -2294,25 +2331,21 @@ CGObjCCommonMac::CreateMetadataVar(const std::string &Name, unsigned Align, bool AddToUsed) { const llvm::Type *Ty = Init->getType(); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(Ty, false, - llvm::GlobalValue::InternalLinkage, - Init, - Name, - &CGM.getModule()); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), Ty, false, + llvm::GlobalValue::InternalLinkage, Init, Name); if (Section) GV->setSection(Section); if (Align) GV->setAlignment(Align); if (AddToUsed) - UsedGlobals.push_back(GV); + CGM.AddUsedGlobal(GV); return GV; } -llvm::Function *CGObjCMac::ModuleInitFunction() { +llvm::Function *CGObjCMac::ModuleInitFunction() { // Abuse this interface function as a place to finalize. FinishModule(); - return NULL; } @@ -2328,92 +2361,92 @@ llvm::Constant *CGObjCMac::EnumerationMutationFunction() { return ObjCTypes.getEnumerationMutationFn(); } -/* +/* -Objective-C setjmp-longjmp (sjlj) Exception Handling --- + Objective-C setjmp-longjmp (sjlj) Exception Handling + -- -The basic framework for a @try-catch-finally is as follows: -{ + The basic framework for a @try-catch-finally is as follows: + { objc_exception_data d; id _rethrow = null; bool _call_try_exit = true; - + objc_exception_try_enter(&d); if (!setjmp(d.jmp_buf)) { - ... try body ... + ... try body ... } else { - // exception path - id _caught = objc_exception_extract(&d); - - // enter new try scope for handlers - if (!setjmp(d.jmp_buf)) { - ... match exception and execute catch blocks ... - - // fell off end, rethrow. - _rethrow = _caught; - ... jump-through-finally to finally_rethrow ... - } else { - // exception in catch block - _rethrow = objc_exception_extract(&d); - _call_try_exit = false; - ... jump-through-finally to finally_rethrow ... - } + // exception path + id _caught = objc_exception_extract(&d); + + // enter new try scope for handlers + if (!setjmp(d.jmp_buf)) { + ... match exception and execute catch blocks ... + + // fell off end, rethrow. + _rethrow = _caught; + ... jump-through-finally to finally_rethrow ... + } else { + // exception in catch block + _rethrow = objc_exception_extract(&d); + _call_try_exit = false; + ... jump-through-finally to finally_rethrow ... + } } ... jump-through-finally to finally_end ... -finally: + finally: if (_call_try_exit) - objc_exception_try_exit(&d); + objc_exception_try_exit(&d); ... finally block .... ... dispatch to finally destination ... -finally_rethrow: + finally_rethrow: objc_exception_throw(_rethrow); -finally_end: -} + finally_end: + } + + This framework differs slightly from the one gcc uses, in that gcc + uses _rethrow to determine if objc_exception_try_exit should be called + and if the object should be rethrown. This breaks in the face of + throwing nil and introduces unnecessary branches. + + We specialize this framework for a few particular circumstances: -This framework differs slightly from the one gcc uses, in that gcc -uses _rethrow to determine if objc_exception_try_exit should be called -and if the object should be rethrown. This breaks in the face of -throwing nil and introduces unnecessary branches. - -We specialize this framework for a few particular circumstances: - - - If there are no catch blocks, then we avoid emitting the second - exception handling context. - - - If there is a catch-all catch block (i.e. @catch(...) or @catch(id - e)) we avoid emitting the code to rethrow an uncaught exception. - - - FIXME: If there is no @finally block we can do a few more - simplifications. - -Rethrows and Jumps-Through-Finally --- - -Support for implicit rethrows and jumping through the finally block is -handled by storing the current exception-handling context in -ObjCEHStack. - -In order to implement proper @finally semantics, we support one basic -mechanism for jumping through the finally block to an arbitrary -destination. Constructs which generate exits from a @try or @catch -block use this mechanism to implement the proper semantics by chaining -jumps, as necessary. - -This mechanism works like the one used for indirect goto: we -arbitrarily assign an ID to each destination and store the ID for the -destination in a variable prior to entering the finally block. At the -end of the finally block we simply create a switch to the proper -destination. - -Code gen for @synchronized(expr) stmt; -Effectively generating code for: -objc_sync_enter(expr); -@try stmt @finally { objc_sync_exit(expr); } + - If there are no catch blocks, then we avoid emitting the second + exception handling context. + + - If there is a catch-all catch block (i.e. @catch(...) or @catch(id + e)) we avoid emitting the code to rethrow an uncaught exception. + + - FIXME: If there is no @finally block we can do a few more + simplifications. + + Rethrows and Jumps-Through-Finally + -- + + Support for implicit rethrows and jumping through the finally block is + handled by storing the current exception-handling context in + ObjCEHStack. + + In order to implement proper @finally semantics, we support one basic + mechanism for jumping through the finally block to an arbitrary + destination. Constructs which generate exits from a @try or @catch + block use this mechanism to implement the proper semantics by chaining + jumps, as necessary. + + This mechanism works like the one used for indirect goto: we + arbitrarily assign an ID to each destination and store the ID for the + destination in a variable prior to entering the finally block. At the + end of the finally block we simply create a switch to the proper + destination. + + Code gen for @synchronized(expr) stmt; + Effectively generating code for: + objc_sync_enter(expr); + @try stmt @finally { objc_sync_exit(expr); } */ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, @@ -2425,14 +2458,14 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit"); llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); - + // For @synchronized, call objc_sync_enter(sync.expr). The // evaluation of the expression must occur before we enter the // @synchronized. We can safely avoid a temp here because jumps into // @synchronized are illegal & this will dominate uses. llvm::Value *SyncArg = 0; if (!isTry) { - SyncArg = + SyncArg = CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg); @@ -2443,19 +2476,21 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.PushCleanupBlock(FinallyBlock); CGF.ObjCEHValueStack.push_back(0); - + // Allocate memory for the exception data and rethrow pointer. llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, "exceptiondata.ptr"); - llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy, + llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy, "_rethrow"); - llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca(llvm::Type::Int1Ty, + llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca( + llvm::Type::getInt1Ty(VMContext), "_call_try_exit"); - CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(), CallTryExitPtr); - + CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), + CallTryExitPtr); + // Enter a new try block and call setjmp. CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData); - llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0, + llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0, "jmpbufarray"); JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp"); llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), @@ -2463,15 +2498,15 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); - CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"), + CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"), TryHandler, TryBlock); // Emit the @try block. CGF.EmitBlock(TryBlock); - CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() - : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); + CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() + : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); CGF.EmitBranchThroughCleanup(FinallyEnd); - + // Emit the "exception in @try" block. CGF.EmitBlock(TryHandler); @@ -2481,19 +2516,17 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), ExceptionData, "caught"); CGF.ObjCEHValueStack.back() = Caught; - if (!isTry) - { + if (!isTry) { CGF.Builder.CreateStore(Caught, RethrowPtr); - CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr); + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), + CallTryExitPtr); CGF.EmitBranchThroughCleanup(FinallyRethrow); - } - else if (const ObjCAtCatchStmt* CatchStmt = - cast<ObjCAtTryStmt>(S).getCatchStmts()) - { + } else if (const ObjCAtCatchStmt* CatchStmt = + cast<ObjCAtTryStmt>(S).getCatchStmts()) { // Enter a new exception try block (in case a @catch block throws // an exception). CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData); - + llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), JmpBufPtr, "result"); llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"); @@ -2501,9 +2534,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch"); llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler"); CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock); - + CGF.EmitBlock(CatchBlock); - + // Handle catch list. As a special case we check if everything is // matched and avoid generating code for falling off the end if // so. @@ -2512,64 +2545,64 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch"); const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl(); - const PointerType *PT = 0; + const ObjCObjectPointerType *OPT = 0; // catch(...) always matches. if (!CatchParam) { AllMatched = true; } else { - PT = CatchParam->getType()->getAsPointerType(); - - // catch(id e) always matches. + OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>(); + + // catch(id e) always matches. // FIXME: For the time being we also match id<X>; this should // be rejected by Sema instead. - if ((PT && CGF.getContext().isObjCIdStructType(PT->getPointeeType())) || - CatchParam->getType()->isObjCQualifiedIdType()) + if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())) AllMatched = true; } - - if (AllMatched) { + + if (AllMatched) { if (CatchParam) { CGF.EmitLocalBlockVarDecl(*CatchParam); assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam)); } - + CGF.EmitStmt(CatchStmt->getCatchBody()); CGF.EmitBranchThroughCleanup(FinallyEnd); break; } - - assert(PT && "Unexpected non-pointer type in @catch"); - QualType T = PT->getPointeeType(); - const ObjCInterfaceType *ObjCType = T->getAsObjCInterfaceType(); + + assert(OPT && "Unexpected non-object pointer type in @catch"); + QualType T = OPT->getPointeeType(); + const ObjCInterfaceType *ObjCType = T->getAs<ObjCInterfaceType>(); assert(ObjCType && "Catch parameter must have Objective-C type!"); // Check if the @catch block matches the exception object. llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl()); - + llvm::Value *Match = CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(), Class, Caught, "match"); - + llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched"); - - CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), + + CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), MatchedBlock, NextCatchBlock); - + // Emit the @catch block. CGF.EmitBlock(MatchedBlock); CGF.EmitLocalBlockVarDecl(*CatchParam); assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); - llvm::Value *Tmp = - CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(CatchParam->getType()), + llvm::Value *Tmp = + CGF.Builder.CreateBitCast(Caught, + CGF.ConvertType(CatchParam->getType()), "tmp"); CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam)); - + CGF.EmitStmt(CatchStmt->getCatchBody()); CGF.EmitBranchThroughCleanup(FinallyEnd); - + CGF.EmitBlock(NextCatchBlock); } @@ -2579,41 +2612,43 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.Builder.CreateStore(Caught, RethrowPtr); CGF.EmitBranchThroughCleanup(FinallyRethrow); } - + // Emit the exception handler for the @catch blocks. - CGF.EmitBlock(CatchHandler); + CGF.EmitBlock(CatchHandler); CGF.Builder.CreateStore( - CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData), - RethrowPtr); - CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr); + CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), + ExceptionData), + RethrowPtr); + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), + CallTryExitPtr); CGF.EmitBranchThroughCleanup(FinallyRethrow); } else { CGF.Builder.CreateStore(Caught, RethrowPtr); - CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr); + CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), + CallTryExitPtr); CGF.EmitBranchThroughCleanup(FinallyRethrow); } - + // Pop the exception-handling stack entry. It is important to do // this now, because the code in the @finally block is not in this // context. CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); CGF.ObjCEHValueStack.pop_back(); - + // Emit the @finally block. CGF.EmitBlock(FinallyBlock); llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp"); - + CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit); - + CGF.EmitBlock(FinallyExit); CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData); CGF.EmitBlock(FinallyNoExit); if (isTry) { - if (const ObjCAtFinallyStmt* FinallyStmt = - cast<ObjCAtTryStmt>(S).getFinallyStmt()) + if (const ObjCAtFinallyStmt* FinallyStmt = + cast<ObjCAtTryStmt>(S).getFinallyStmt()) CGF.EmitStmt(FinallyStmt->getFinallyBody()); } else { // Emit objc_sync_exit(expr); as finally's sole statement for @@ -2626,29 +2661,29 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBlock(Info.SwitchBlock); if (Info.EndBlock) CGF.EmitBlock(Info.EndBlock); - + CGF.EmitBlock(FinallyRethrow); - CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), + CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), CGF.Builder.CreateLoad(RethrowPtr)); CGF.Builder.CreateUnreachable(); - + CGF.EmitBlock(FinallyEnd); } void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S) { llvm::Value *ExceptionAsObject; - + if (const Expr *ThrowExpr = S.getThrowExpr()) { llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); - ExceptionAsObject = + ExceptionAsObject = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp"); } else { - assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && + assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && "Unexpected rethrow outside @catch block."); ExceptionAsObject = CGF.ObjCEHValueStack.back(); } - + CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject); CGF.Builder.CreateUnreachable(); @@ -2660,11 +2695,11 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, /// object: objc_read_weak (id *src) /// llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - llvm::Value *AddrWeakObj) -{ + llvm::Value *AddrWeakObj) { const llvm::Type* DestTy = - cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); - AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); + cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); + AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, + ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObj, "weakread"); read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); @@ -2675,14 +2710,13 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, /// objc_assign_weak (id src, id *dst) /// void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); @@ -2696,14 +2730,13 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, /// objc_assign_global (id src, id *dst) /// void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); @@ -2714,23 +2747,24 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. -/// objc_assign_ivar (id src, id *dst) +/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset) /// void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst, + llvm::Value *ivarOffset) { + assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - CGF.Builder.CreateCall2(ObjCTypes.getGcAssignIvarFn(), - src, dst, "assignivar"); + CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), + src, dst, ivarOffset); return; } @@ -2738,14 +2772,13 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, /// objc_assign_strongCast (id src, id *dst) /// void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); @@ -2755,6 +2788,21 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, return; } +void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, + llvm::Value *DestPtr, + llvm::Value *SrcPtr, + QualType Ty) { + // Get size info for this aggregate. + std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); + unsigned long size = TypeInfo.first/8; + SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); + DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); + llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); + CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), + DestPtr, SrcPtr, N); + return; +} + /// EmitObjCValueForIvar - Code Gen for ivar reference. /// LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, @@ -2762,7 +2810,7 @@ LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl(); + const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } @@ -2772,8 +2820,8 @@ llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, const ObjCIvarDecl *Ivar) { uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); return llvm::ConstantInt::get( - CGM.getTypes().ConvertType(CGM.getContext().LongTy), - Offset); + CGM.getTypes().ConvertType(CGM.getContext().LongTy), + Offset); } /* *** Private Interface *** */ @@ -2789,8 +2837,8 @@ llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, enum ImageInfoFlags { eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what // this implies. - eImageInfo_GarbageCollected = (1 << 1), - eImageInfo_GCOnly = (1 << 2), + eImageInfo_GarbageCollected = (1 << 1), + eImageInfo_GCOnly = (1 << 2), eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set. // A flag indicating that the module has no instances of an @@ -2807,23 +2855,23 @@ void CGObjCMac::EmitImageInfo() { flags |= eImageInfo_GarbageCollected; if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) flags |= eImageInfo_GCOnly; - + // We never allow @synthesize of a superclass property. flags |= eImageInfo_CorrectedSynthesize; // Emitted as int[2]; llvm::Constant *values[2] = { - llvm::ConstantInt::get(llvm::Type::Int32Ty, version), - llvm::ConstantInt::get(llvm::Type::Int32Ty, flags) + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), version), + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags) }; - llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2); + llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 2); const char *Section; if (ObjCABI == 1) Section = "__OBJC, __image_info,regular"; else Section = "__DATA, __objc_imageinfo, regular, no_dead_strip"; - llvm::GlobalVariable *GV = + llvm::GlobalVariable *GV = CreateMetadataVar("\01L_OBJC_IMAGE_INFO", llvm::ConstantArray::get(AT, values, 2), Section, @@ -2845,14 +2893,14 @@ static const int ModuleVersion = 7; void CGObjCMac::EmitModuleInfo() { uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy); - + std::vector<llvm::Constant*> Values(4); Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion); Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); // This used to be the filename, now it is unused. <rdr://4327263> Values[2] = GetClassName(&CGM.getContext().Idents.get("")); Values[3] = EmitModuleSymbols(); - CreateMetadataVar("\01L_OBJC_MODULES", + CreateMetadataVar("\01L_OBJC_MODULES", llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values), "__OBJC,__module_info,regular,no_dead_strip", 4, true); @@ -2879,16 +2927,16 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() { Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy); for (unsigned i=0; i<NumCategories; i++) - Symbols[NumClasses + i] = + Symbols[NumClasses + i] = llvm::ConstantExpr::getBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy); - Values[4] = + Values[4] = llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, NumClasses + NumCategories), Symbols); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); llvm::GlobalVariable *GV = CreateMetadataVar("\01L_OBJC_SYMBOLS", Init, @@ -2897,17 +2945,17 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() { return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy); } -llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder, +llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID) { LazySymbols.insert(ID->getIdentifier()); llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; - + if (!Entry) { - llvm::Constant *Casted = + llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()), ObjCTypes.ClassPtrTy); - Entry = + Entry = CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted, "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 4, true); @@ -2918,12 +2966,12 @@ llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder, llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; - + if (!Entry) { - llvm::Constant *Casted = + llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), ObjCTypes.SelectorPtrTy); - Entry = + Entry = CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted, "__OBJC,__message_refs,literal_pointers,no_dead_strip", 4, true); @@ -2936,59 +2984,58 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { llvm::GlobalVariable *&Entry = ClassNames[Ident]; if (!Entry) - Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", - llvm::ConstantArray::get(Ident->getName()), + Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", + llvm::ConstantArray::get(VMContext, Ident->getName()), "__TEXT,__cstring,cstring_literals", 1, true); - return getConstantGEP(Entry, 0, 0); + return getConstantGEP(VMContext, Entry, 0, 0); } /// GetIvarLayoutName - Returns a unique constant for the given /// ivar layout bitmap. llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, - const ObjCCommonTypesHelper &ObjCTypes) { + const ObjCCommonTypesHelper &ObjCTypes) { return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); } -static QualType::GCAttrTypes GetGCAttrTypeForType(ASTContext &Ctx, - QualType FQT) { +static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) { if (FQT.isObjCGCStrong()) - return QualType::Strong; + return Qualifiers::Strong; if (FQT.isObjCGCWeak()) - return QualType::Weak; + return Qualifiers::Weak; - if (Ctx.isObjCObjectPointerType(FQT)) - return QualType::Strong; + if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) + return Qualifiers::Strong; - if (const PointerType *PT = FQT->getAsPointerType()) + if (const PointerType *PT = FQT->getAs<PointerType>()) return GetGCAttrTypeForType(Ctx, PT->getPointeeType()); - return QualType::GCNone; + return Qualifiers::GCNone; } void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, - unsigned int BytePos, + unsigned int BytePos, bool ForStrongLayout, bool &HasUnion) { const RecordDecl *RD = RT->getDecl(); // FIXME - Use iterator. llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end()); const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); - const llvm::StructLayout *RecLayout = + const llvm::StructLayout *RecLayout = CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty)); - + BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos, ForStrongLayout, HasUnion); } void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, - const llvm::StructLayout *Layout, - const RecordDecl *RD, + const llvm::StructLayout *Layout, + const RecordDecl *RD, const llvm::SmallVectorImpl<FieldDecl*> &RecFields, - unsigned int BytePos, bool ForStrongLayout, - bool &HasUnion) { + unsigned int BytePos, bool ForStrongLayout, + bool &HasUnion) { bool IsUnion = (RD && RD->isUnion()); uint64_t MaxUnionIvarSize = 0; uint64_t MaxSkippedUnionIvarSize = 0; @@ -2998,7 +3045,7 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, uint64_t MaxFieldOffset = 0; uint64_t MaxSkippedFieldOffset = 0; uint64_t LastBitfieldOffset = 0; - + if (RecFields.empty()) return; unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0); @@ -3007,10 +3054,19 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { FieldDecl *Field = RecFields[i]; uint64_t FieldOffset; - if (RD) - FieldOffset = - Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)); - else + if (RD) { + if (Field->isBitField()) { + CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field); + + const llvm::Type *Ty = + CGM.getTypes().ConvertTypeForMemRecursive(Field->getType()); + uint64_t TypeSize = + CGM.getTypes().getTargetData().getTypeAllocSize(Ty); + FieldOffset = Info.FieldNo * TypeSize; + } else + FieldOffset = + Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)); + } else FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)); // Skip over unnamed or bitfields @@ -3026,14 +3082,14 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, if (FQT->isUnionType()) HasUnion = true; - BuildAggrIvarRecordLayout(FQT->getAsRecordType(), + BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(), BytePos + FieldOffset, ForStrongLayout, HasUnion); continue; } - + if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { - const ConstantArrayType *CArray = + const ConstantArrayType *CArray = dyn_cast_or_null<ConstantArrayType>(Array); uint64_t ElCount = CArray->getSize().getZExtValue(); assert(CArray && "only array with known element size is supported"); @@ -3044,22 +3100,22 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, ElCount *= CArray->getSize().getZExtValue(); FQT = CArray->getElementType(); } - - assert(!FQT->isUnionType() && + + assert(!FQT->isUnionType() && "layout for array of unions not supported"); if (FQT->isRecordType()) { int OldIndex = IvarsInfo.size() - 1; int OldSkIndex = SkipIvars.size() -1; - - const RecordType *RT = FQT->getAsRecordType(); + + const RecordType *RT = FQT->getAs<RecordType>(); BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset, ForStrongLayout, HasUnion); - + // Replicate layout information for each array element. Note that // one element is already done. uint64_t ElIx = 1; - for (int FirstIndex = IvarsInfo.size() - 1, - FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) { + for (int FirstIndex = IvarsInfo.size() - 1, + FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) { uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits; for (int i = OldIndex+1; i <= FirstIndex; ++i) IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx, @@ -3073,11 +3129,11 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, } // At this point, we are done with Record/Union and array there of. // For other arrays we are down to its element type. - QualType::GCAttrTypes GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); + Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType()); - if ((ForStrongLayout && GCAttr == QualType::Strong) - || (!ForStrongLayout && GCAttr == QualType::Weak)) { + if ((ForStrongLayout && GCAttr == Qualifiers::Strong) + || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { if (IsUnion) { uint64_t UnionIvarSize = FieldSize / WordSizeInBits; if (UnionIvarSize > MaxUnionIvarSize) { @@ -3089,9 +3145,9 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset, FieldSize / WordSizeInBits)); } - } else if ((ForStrongLayout && - (GCAttr == QualType::GCNone || GCAttr == QualType::Weak)) - || (!ForStrongLayout && GCAttr != QualType::Weak)) { + } else if ((ForStrongLayout && + (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)) + || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) { if (IsUnion) { // FIXME: Why the asymmetry? We divide by word size in bits on other // side. @@ -3116,13 +3172,13 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); GC_IVAR skivar; skivar.ivar_bytepos = BytePos + LastBitfieldOffset; - skivar.ivar_size = (BitFieldSize / ByteSizeInBits) - + ((BitFieldSize % ByteSizeInBits) != 0); - SkipIvars.push_back(skivar); + skivar.ivar_size = (BitFieldSize / ByteSizeInBits) + + ((BitFieldSize % ByteSizeInBits) != 0); + SkipIvars.push_back(skivar); } - + if (MaxField) - IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset, + IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset, MaxUnionIvarSize)); if (MaxSkippedField) SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset, @@ -3131,60 +3187,60 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, /// BuildIvarLayout - Builds ivar layout bitmap for the class /// implementation for the __strong or __weak case. -/// The layout map displays which words in ivar list must be skipped -/// and which must be scanned by GC (see below). String is built of bytes. -/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count +/// The layout map displays which words in ivar list must be skipped +/// and which must be scanned by GC (see below). String is built of bytes. +/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count /// of words to skip and right nibble is count of words to scan. So, each -/// nibble represents up to 15 workds to skip or scan. Skipping the rest is +/// nibble represents up to 15 workds to skip or scan. Skipping the rest is /// represented by a 0x00 byte which also ends the string. /// 1. when ForStrongLayout is true, following ivars are scanned: /// - id, Class /// - object * /// - __strong anything -/// +/// /// 2. When ForStrongLayout is false, following ivars are scanned: /// - __weak anything /// llvm::Constant *CGObjCCommonMac::BuildIvarLayout( - const ObjCImplementationDecl *OMD, - bool ForStrongLayout) { + const ObjCImplementationDecl *OMD, + bool ForStrongLayout) { bool hasUnion = false; - + unsigned int WordsToScan, WordsToSkip; - const llvm::Type *PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) return llvm::Constant::getNullValue(PtrTy); - + llvm::SmallVector<FieldDecl*, 32> RecFields; const ObjCInterfaceDecl *OI = OMD->getClassInterface(); CGM.getContext().CollectObjCIvars(OI, RecFields); - + // Add this implementations synthesized ivars. llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; CGM.getContext().CollectSynthesizedIvars(OI, Ivars); for (unsigned k = 0, e = Ivars.size(); k != e; ++k) RecFields.push_back(cast<FieldDecl>(Ivars[k])); - + if (RecFields.empty()) return llvm::Constant::getNullValue(PtrTy); - - SkipIvars.clear(); + + SkipIvars.clear(); IvarsInfo.clear(); - + BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion); if (IvarsInfo.empty()) return llvm::Constant::getNullValue(PtrTy); - + // Sort on byte position in case we encounterred a union nested in // the ivar list. if (hasUnion && !IvarsInfo.empty()) std::sort(IvarsInfo.begin(), IvarsInfo.end()); if (hasUnion && !SkipIvars.empty()) std::sort(SkipIvars.begin(), SkipIvars.end()); - + // Build the string of skip/scan nibbles llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars; - unsigned int WordSize = + unsigned int WordSize = CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy); if (IvarsInfo[0].ivar_bytepos == 0) { WordsToSkip = 0; @@ -3194,7 +3250,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( WordsToScan = IvarsInfo[0].ivar_size; } for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) { - unsigned int TailPrevGCObjC = + unsigned int TailPrevGCObjC = IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize; if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) { // consecutive 'scanned' object pointers. @@ -3209,7 +3265,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( SkScan.skip = WordsToSkip; SkScan.scan = WordsToScan; SkipScanIvars.push_back(SkScan); - + // Skip the hole. SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize; SkScan.scan = 0; @@ -3224,16 +3280,16 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( SkScan.scan = WordsToScan; SkipScanIvars.push_back(SkScan); } - + bool BytesSkipped = false; if (!SkipIvars.empty()) { unsigned int LastIndex = SkipIvars.size()-1; - int LastByteSkipped = - SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size; + int LastByteSkipped = + SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size; LastIndex = IvarsInfo.size()-1; - int LastByteScanned = - IvarsInfo[LastIndex].ivar_bytepos + - IvarsInfo[LastIndex].ivar_size * WordSize; + int LastByteScanned = + IvarsInfo[LastIndex].ivar_bytepos + + IvarsInfo[LastIndex].ivar_size * WordSize; BytesSkipped = (LastByteSkipped > LastByteScanned); // Compute number of bytes to skip at the tail end of the last ivar scanned. if (BytesSkipped) { @@ -3257,7 +3313,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( --SkipScan; } } - + // Generate the string. std::string BitMap; for (int i = 0; i <= SkipScan; i++) { @@ -3272,7 +3328,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( // first skip big. for (unsigned int ix = 0; ix < skip_big; ix++) BitMap += (unsigned char)(0xf0); - + // next (skip small, scan) if (skip_small) { byte = skip_small << 4; @@ -3297,9 +3353,9 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( // null terminate string. unsigned char zero = 0; BitMap += zero; - + if (CGM.getLangOptions().ObjCGCBitmapPrint) { - printf("\n%s ivar layout for class '%s': ", + printf("\n%s ivar layout for class '%s': ", ForStrongLayout ? "strong" : "weak", OMD->getClassInterface()->getNameAsCString()); const unsigned char *s = (unsigned char*)BitMap.c_str(); @@ -3310,16 +3366,12 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); printf("\n"); } - - // if ivar_layout bitmap is all 1 bits (nothing skipped) then use NULL as - // final layout. - if (ForStrongLayout && !BytesSkipped) - return llvm::Constant::getNullValue(PtrTy); - llvm::GlobalVariable * Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", - llvm::ConstantArray::get(BitMap.c_str()), - "__TEXT,__cstring,cstring_literals", - 1, true); - return getConstantGEP(Entry, 0, 0); + llvm::GlobalVariable * Entry = + CreateMetadataVar("\01L_OBJC_CLASS_NAME_", + llvm::ConstantArray::get(VMContext, BitMap.c_str()), + "__TEXT,__cstring,cstring_literals", + 1, true); + return getConstantGEP(VMContext, Entry, 0, 0); } llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { @@ -3327,12 +3379,12 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { // FIXME: Avoid std::string copying. if (!Entry) - Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_", - llvm::ConstantArray::get(Sel.getAsString()), + Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_", + llvm::ConstantArray::get(VMContext, Sel.getAsString()), "__TEXT,__cstring,cstring_literals", 1, true); - return getConstantGEP(Entry, 0, 0); + return getConstantGEP(VMContext, Entry, 0, 0); } // FIXME: Merge into a single cstring creation function. @@ -3353,11 +3405,11 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { if (!Entry) Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", - llvm::ConstantArray::get(TypeStr), + llvm::ConstantArray::get(VMContext, TypeStr), "__TEXT,__cstring,cstring_literals", 1, true); - - return getConstantGEP(Entry, 0, 0); + + return getConstantGEP(VMContext, Entry, 0, 0); } llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) { @@ -3369,37 +3421,37 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) { if (!Entry) Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", - llvm::ConstantArray::get(TypeStr), + llvm::ConstantArray::get(VMContext, TypeStr), "__TEXT,__cstring,cstring_literals", 1, true); - return getConstantGEP(Entry, 0, 0); + return getConstantGEP(VMContext, Entry, 0, 0); } // FIXME: Merge into a single cstring creation function. llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) { llvm::GlobalVariable *&Entry = PropertyNames[Ident]; - + if (!Entry) - Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_", - llvm::ConstantArray::get(Ident->getName()), + Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_", + llvm::ConstantArray::get(VMContext, Ident->getName()), "__TEXT,__cstring,cstring_literals", 1, true); - return getConstantGEP(Entry, 0, 0); + return getConstantGEP(VMContext, Entry, 0, 0); } // FIXME: Merge into a single cstring creation function. // FIXME: This Decl should be more precise. llvm::Constant * - CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, - const Decl *Container) { +CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, + const Decl *Container) { std::string TypeStr; CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr); return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); } -void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, +void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, const ObjCContainerDecl *CD, std::string &NameOut) { NameOut = '\01'; @@ -3407,7 +3459,7 @@ void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, NameOut += '['; assert (CD && "Missing container decl in GetNameForMethod"); NameOut += CD->getNameAsString(); - if (const ObjCCategoryImplDecl *CID = + if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) { NameOut += '('; NameOut += CID->getNameAsString(); @@ -3418,64 +3470,55 @@ void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, NameOut += ']'; } -void CGObjCCommonMac::MergeMetadataGlobals( - std::vector<llvm::Constant*> &UsedArray) { - llvm::Type *i8PTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(), - e = UsedGlobals.end(); i != e; ++i) { - UsedArray.push_back(llvm::ConstantExpr::getBitCast(cast<llvm::Constant>(*i), - i8PTy)); - } -} - void CGObjCMac::FinishModule() { EmitModuleInfo(); // Emit the dummy bodies for any protocols which were referenced but // never defined. - for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator - i = Protocols.begin(), e = Protocols.end(); i != e; ++i) { - if (i->second->hasInitializer()) + for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator + I = Protocols.begin(), e = Protocols.end(); I != e; ++I) { + if (I->second->hasInitializer()) continue; std::vector<llvm::Constant*> Values(5); Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); - Values[1] = GetClassName(i->first); + Values[1] = GetClassName(I->first); Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); Values[3] = Values[4] = llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); - i->second->setLinkage(llvm::GlobalValue::InternalLinkage); - i->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, + I->second->setLinkage(llvm::GlobalValue::InternalLinkage); + I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, Values)); + CGM.AddUsedGlobal(I->second); } // Add assembler directives to add lazy undefined symbol references // for classes which are referenced but not defined. This is // important for correct linker interaction. - - // FIXME: Uh, this isn't particularly portable. - std::stringstream s; - - if (!CGM.getModule().getModuleInlineAsm().empty()) - s << "\n"; - - for (std::set<IdentifierInfo*>::iterator i = LazySymbols.begin(), - e = LazySymbols.end(); i != e; ++i) { - s << "\t.lazy_reference .objc_class_name_" << (*i)->getName() << "\n"; - } - for (std::set<IdentifierInfo*>::iterator i = DefinedSymbols.begin(), - e = DefinedSymbols.end(); i != e; ++i) { - s << "\t.objc_class_name_" << (*i)->getName() << "=0\n" - << "\t.globl .objc_class_name_" << (*i)->getName() << "\n"; - } - - CGM.getModule().appendModuleInlineAsm(s.str()); + // + // FIXME: It would be nice if we had an LLVM construct for this. + if (!LazySymbols.empty() || !DefinedSymbols.empty()) { + llvm::SmallString<256> Asm; + Asm += CGM.getModule().getModuleInlineAsm(); + if (!Asm.empty() && Asm.back() != '\n') + Asm += '\n'; + + llvm::raw_svector_ostream OS(Asm); + for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(), + e = LazySymbols.end(); I != e; ++I) + OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n"; + for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(), + e = DefinedSymbols.end(); I != e; ++I) + OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n" + << "\t.globl .objc_class_name_" << (*I)->getName() << "\n"; + + CGM.getModule().setModuleInlineAsm(OS.str()); + } } -CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) +CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), - ObjCTypes(cgm) -{ + ObjCTypes(cgm) { ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL; ObjCABI = 2; } @@ -3483,119 +3526,117 @@ CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) /* *** */ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) -: CGM(cgm) -{ + : VMContext(cgm.getLLVMContext()), CGM(cgm) { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); - + ShortTy = Types.ConvertType(Ctx.ShortTy); IntTy = Types.ConvertType(Ctx.IntTy); LongTy = Types.ConvertType(Ctx.LongTy); LongLongTy = Types.ConvertType(Ctx.LongLongTy); - Int8PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - + Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType()); PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy); SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType()); - + // FIXME: It would be nice to unify this with the opaque type, so that the IR // comes out a bit cleaner. const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType()); ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T); - + // I'm not sure I like this. The implicit coordination is a bit // gross. We should solve this in a reasonable fashion because this // is a pretty common task (match some runtime data structure with // an LLVM data structure). - + // FIXME: This is leaked. // FIXME: Merge with rewriter code? - + // struct _objc_super { // id self; // Class cls; // } RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, SourceLocation(), - &Ctx.Idents.get("_objc_super")); - RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, - Ctx.getObjCIdType(), 0, false)); + &Ctx.Idents.get("_objc_super")); + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + Ctx.getObjCIdType(), 0, 0, false)); RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, - Ctx.getObjCClassType(), 0, false)); + Ctx.getObjCClassType(), 0, 0, false)); RD->completeDefinition(Ctx); - + SuperCTy = Ctx.getTagDeclType(RD); SuperPtrCTy = Ctx.getPointerType(SuperCTy); - + SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy)); - SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); - + SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); + // struct _prop_t { // char *name; - // char *attributes; + // char *attributes; // } - PropertyTy = llvm::StructType::get(Int8PtrTy, Int8PtrTy, NULL); - CGM.getModule().addTypeName("struct._prop_t", + PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL); + CGM.getModule().addTypeName("struct._prop_t", PropertyTy); - + // struct _prop_list_t { // uint32_t entsize; // sizeof(struct _prop_t) // uint32_t count_of_properties; // struct _prop_t prop_list[count_of_properties]; // } - PropertyListTy = llvm::StructType::get(IntTy, + PropertyListTy = llvm::StructType::get(VMContext, IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0), NULL); - CGM.getModule().addTypeName("struct._prop_list_t", + CGM.getModule().addTypeName("struct._prop_list_t", PropertyListTy); // struct _prop_list_t * PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); - + // struct _objc_method { // SEL _cmd; // char *method_type; // char *_imp; // } - MethodTy = llvm::StructType::get(SelectorPtrTy, + MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy, Int8PtrTy, Int8PtrTy, NULL); CGM.getModule().addTypeName("struct._objc_method", MethodTy); - + // struct _objc_cache * - CacheTy = llvm::OpaqueType::get(); + CacheTy = llvm::OpaqueType::get(VMContext); CGM.getModule().addTypeName("struct._objc_cache", CacheTy); CachePtrTy = llvm::PointerType::getUnqual(CacheTy); } -ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) - : ObjCCommonTypesHelper(cgm) -{ +ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) + : ObjCCommonTypesHelper(cgm) { // struct _objc_method_description { // SEL name; // char *types; // } - MethodDescriptionTy = - llvm::StructType::get(SelectorPtrTy, + MethodDescriptionTy = + llvm::StructType::get(VMContext, SelectorPtrTy, Int8PtrTy, NULL); - CGM.getModule().addTypeName("struct._objc_method_description", + CGM.getModule().addTypeName("struct._objc_method_description", MethodDescriptionTy); // struct _objc_method_description_list { // int count; // struct _objc_method_description[1]; // } - MethodDescriptionListTy = - llvm::StructType::get(IntTy, + MethodDescriptionListTy = + llvm::StructType::get(VMContext, IntTy, llvm::ArrayType::get(MethodDescriptionTy, 0), NULL); - CGM.getModule().addTypeName("struct._objc_method_description_list", + CGM.getModule().addTypeName("struct._objc_method_description_list", MethodDescriptionListTy); - + // struct _objc_method_description_list * - MethodDescriptionListPtrTy = + MethodDescriptionListPtrTy = llvm::PointerType::getUnqual(MethodDescriptionListTy); // Protocol description structures @@ -3606,25 +3647,26 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // struct _objc_method_description_list *optional_class_methods; // struct _objc_property_list *instance_properties; // } - ProtocolExtensionTy = - llvm::StructType::get(IntTy, + ProtocolExtensionTy = + llvm::StructType::get(VMContext, IntTy, MethodDescriptionListPtrTy, MethodDescriptionListPtrTy, PropertyListPtrTy, NULL); - CGM.getModule().addTypeName("struct._objc_protocol_extension", + CGM.getModule().addTypeName("struct._objc_protocol_extension", ProtocolExtensionTy); - + // struct _objc_protocol_extension * ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); // Handle recursive construction of Protocol and ProtocolList types - llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(); - llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(); + llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext); + llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); - const llvm::Type *T = - llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolListTyHolder), + const llvm::Type *T = + llvm::StructType::get(VMContext, + llvm::PointerType::getUnqual(ProtocolListTyHolder), LongTy, llvm::ArrayType::get(ProtocolTyHolder, 0), NULL); @@ -3637,7 +3679,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // struct _objc_method_description_list *instance_methods; // struct _objc_method_description_list *class_methods; // } - T = llvm::StructType::get(ProtocolExtensionPtrTy, + T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy, Int8PtrTy, llvm::PointerType::getUnqual(ProtocolListTyHolder), MethodDescriptionListPtrTy, @@ -3646,7 +3688,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T); ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get()); - CGM.getModule().addTypeName("struct._objc_protocol_list", + CGM.getModule().addTypeName("struct._objc_protocol_list", ProtocolListTy); // struct _objc_protocol_list * ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); @@ -3662,32 +3704,32 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // char *ivar_type; // int ivar_offset; // } - IvarTy = llvm::StructType::get(Int8PtrTy, - Int8PtrTy, - IntTy, + IvarTy = llvm::StructType::get(VMContext, Int8PtrTy, + Int8PtrTy, + IntTy, NULL); CGM.getModule().addTypeName("struct._objc_ivar", IvarTy); // struct _objc_ivar_list * - IvarListTy = llvm::OpaqueType::get(); + IvarListTy = llvm::OpaqueType::get(VMContext); CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy); IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); // struct _objc_method_list * - MethodListTy = llvm::OpaqueType::get(); + MethodListTy = llvm::OpaqueType::get(VMContext); CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy); MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); // struct _objc_class_extension * - ClassExtensionTy = - llvm::StructType::get(IntTy, + ClassExtensionTy = + llvm::StructType::get(VMContext, IntTy, Int8PtrTy, PropertyListPtrTy, NULL); CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy); ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); - llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(); + llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); // struct _objc_class { // Class isa; @@ -3703,7 +3745,8 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // char *ivar_layout; // struct _objc_class_ext *ext; // }; - T = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder), + T = llvm::StructType::get(VMContext, + llvm::PointerType::getUnqual(ClassTyHolder), llvm::PointerType::getUnqual(ClassTyHolder), Int8PtrTy, LongTy, @@ -3717,7 +3760,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) ClassExtensionPtrTy, NULL); cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T); - + ClassTy = cast<llvm::StructType>(ClassTyHolder.get()); CGM.getModule().addTypeName("struct._objc_class", ClassTy); ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); @@ -3730,7 +3773,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // uint32_t size; // sizeof(struct _objc_category) // struct _objc_property_list *instance_properties;// category's @property // } - CategoryTy = llvm::StructType::get(Int8PtrTy, + CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, MethodListPtrTy, MethodListPtrTy, @@ -3749,7 +3792,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // short cat_def_cnt; // char *defs[cls_def_cnt + cat_def_cnt]; // } - SymtabTy = llvm::StructType::get(LongTy, + SymtabTy = llvm::StructType::get(VMContext, LongTy, SelectorPtrTy, ShortTy, ShortTy, @@ -3764,41 +3807,40 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // char *name; // struct _objc_symtab* symtab; // } - ModuleTy = - llvm::StructType::get(LongTy, + ModuleTy = + llvm::StructType::get(VMContext, LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL); CGM.getModule().addTypeName("struct._objc_module", ModuleTy); - + // FIXME: This is the size of the setjmp buffer and should be target // specific. 18 is what's used on 32-bit X86. uint64_t SetJmpBufferSize = 18; - + // Exceptions - const llvm::Type *StackPtrTy = - llvm::ArrayType::get(llvm::PointerType::getUnqual(llvm::Type::Int8Ty), 4); - - ExceptionDataTy = - llvm::StructType::get(llvm::ArrayType::get(llvm::Type::Int32Ty, - SetJmpBufferSize), + const llvm::Type *StackPtrTy = llvm::ArrayType::get( + llvm::Type::getInt8PtrTy(VMContext), 4); + + ExceptionDataTy = + llvm::StructType::get(VMContext, llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), + SetJmpBufferSize), StackPtrTy, NULL); - CGM.getModule().addTypeName("struct._objc_exception_data", + CGM.getModule().addTypeName("struct._objc_exception_data", ExceptionDataTy); } -ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) -: ObjCCommonTypesHelper(cgm) -{ +ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) + : ObjCCommonTypesHelper(cgm) { // struct _method_list_t { // uint32_t entsize; // sizeof(struct _objc_method) // uint32_t method_count; // struct _objc_method method_list[method_count]; // } - MethodListnfABITy = llvm::StructType::get(IntTy, + MethodListnfABITy = llvm::StructType::get(VMContext, IntTy, IntTy, llvm::ArrayType::get(MethodTy, 0), NULL); @@ -3806,7 +3848,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul MethodListnfABITy); // struct method_list_t * MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); - + // struct _protocol_t { // id isa; // NULL // const char * const protocol_name; @@ -3819,11 +3861,11 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // const uint32_t size; // sizeof(struct _protocol_t) // const uint32_t flags; // = 0 // } - + // Holder for struct _protocol_list_t * - llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(); - - ProtocolnfABITy = llvm::StructType::get(ObjectPtrTy, + llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); + + ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy, Int8PtrTy, llvm::PointerType::getUnqual( ProtocolListTyHolder), @@ -3840,23 +3882,23 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // struct _protocol_t* ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); - + // struct _protocol_list_t { // long protocol_count; // Note, this is 32/64 bit // struct _protocol_t *[protocol_count]; // } - ProtocolListnfABITy = llvm::StructType::get(LongTy, + ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy, llvm::ArrayType::get( ProtocolnfABIPtrTy, 0), NULL); CGM.getModule().addTypeName("struct._objc_protocol_list", ProtocolListnfABITy); cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo( - ProtocolListnfABITy); - + ProtocolListnfABITy); + // struct _objc_protocol_list* ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); - + // struct _ivar_t { // unsigned long int *offset; // pointer to ivar offset location // char *name; @@ -3864,28 +3906,29 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // uint32_t alignment; // uint32_t size; // } - IvarnfABITy = llvm::StructType::get(llvm::PointerType::getUnqual(LongTy), + IvarnfABITy = llvm::StructType::get(VMContext, + llvm::PointerType::getUnqual(LongTy), Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL); CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy); - + // struct _ivar_list_t { // uint32 entsize; // sizeof(struct _ivar_t) // uint32 count; // struct _iver_t list[count]; // } - IvarListnfABITy = llvm::StructType::get(IntTy, + IvarListnfABITy = llvm::StructType::get(VMContext, IntTy, IntTy, llvm::ArrayType::get( - IvarnfABITy, 0), + IvarnfABITy, 0), NULL); CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy); - + IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); - + // struct _class_ro_t { // uint32_t const flags; // uint32_t const instanceStart; @@ -3899,9 +3942,9 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // const uint8_t * const weakIvarLayout; // const struct _prop_list_t * const properties; // } - + // FIXME. Add 'reserved' field in 64bit abi mode! - ClassRonfABITy = llvm::StructType::get(IntTy, + ClassRonfABITy = llvm::StructType::get(VMContext, IntTy, IntTy, IntTy, Int8PtrTy, @@ -3914,14 +3957,14 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul NULL); CGM.getModule().addTypeName("struct._class_ro_t", ClassRonfABITy); - + // ImpnfABITy - LLVM for id (*)(id, SEL, ...) std::vector<const llvm::Type*> Params; Params.push_back(ObjectPtrTy); Params.push_back(SelectorPtrTy); ImpnfABITy = llvm::PointerType::getUnqual( - llvm::FunctionType::get(ObjectPtrTy, Params, false)); - + llvm::FunctionType::get(ObjectPtrTy, Params, false)); + // struct _class_t { // struct _class_t *isa; // struct _class_t * const superclass; @@ -3929,23 +3972,24 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // IMP *vtable; // struct class_ro_t *ro; // } - - llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(); - ClassnfABITy = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder), - llvm::PointerType::getUnqual(ClassTyHolder), - CachePtrTy, - llvm::PointerType::getUnqual(ImpnfABITy), - llvm::PointerType::getUnqual( - ClassRonfABITy), - NULL); + + llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); + ClassnfABITy = + llvm::StructType::get(VMContext, + llvm::PointerType::getUnqual(ClassTyHolder), + llvm::PointerType::getUnqual(ClassTyHolder), + CachePtrTy, + llvm::PointerType::getUnqual(ImpnfABITy), + llvm::PointerType::getUnqual(ClassRonfABITy), + NULL); CGM.getModule().addTypeName("struct._class_t", ClassnfABITy); cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo( - ClassnfABITy); - + ClassnfABITy); + // LLVM for struct _class_t * ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); - + // struct _category_t { // const char * const name; // struct _class_t *const cls; @@ -3954,7 +3998,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // const struct _protocol_list_t * const protocols; // const struct _prop_list_t * const properties; // } - CategorynfABITy = llvm::StructType::get(Int8PtrTy, + CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy, @@ -3962,54 +4006,55 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul PropertyListPtrTy, NULL); CGM.getModule().addTypeName("struct._category_t", CategorynfABITy); - + // New types for nonfragile abi messaging. CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); - + // MessageRefTy - LLVM for: // struct _message_ref_t { // IMP messenger; // SEL name; // }; - + // First the clang type for struct _message_ref_t RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, SourceLocation(), &Ctx.Idents.get("_message_ref_t")); RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, - Ctx.VoidPtrTy, 0, false)); + Ctx.VoidPtrTy, 0, 0, false)); RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, - Ctx.getObjCSelType(), 0, false)); + Ctx.getObjCSelType(), 0, 0, false)); RD->completeDefinition(Ctx); - + MessageRefCTy = Ctx.getTagDeclType(RD); MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy)); - + // MessageRefPtrTy - LLVM for struct _message_ref_t* MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy); - + // SuperMessageRefTy - LLVM for: // struct _super_message_ref_t { // SUPER_IMP messenger; // SEL name; // }; - SuperMessageRefTy = llvm::StructType::get(ImpnfABITy, + SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy, SelectorPtrTy, NULL); CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy); - + // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* - SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); - + SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); + // struct objc_typeinfo { // const void** vtable; // objc_ehtype_vtable + 2 // const char* name; // c++ typeinfo string // Class cls; // }; - EHTypeTy = llvm::StructType::get(llvm::PointerType::getUnqual(Int8PtrTy), + EHTypeTy = llvm::StructType::get(VMContext, + llvm::PointerType::getUnqual(Int8PtrTy), Int8PtrTy, ClassnfABIPtrTy, NULL); @@ -4017,63 +4062,62 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); } -llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { +llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { FinishNonFragileABIModule(); - + return NULL; } -void CGObjCNonFragileABIMac::AddModuleClassList(const - std::vector<llvm::GlobalValue*> - &Container, +void CGObjCNonFragileABIMac::AddModuleClassList(const + std::vector<llvm::GlobalValue*> + &Container, const char *SymbolName, const char *SectionName) { unsigned NumClasses = Container.size(); - + if (!NumClasses) return; - + std::vector<llvm::Constant*> Symbols(NumClasses); for (unsigned i=0; i<NumClasses; i++) Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i], ObjCTypes.Int8PtrTy); - llvm::Constant* Init = + llvm::Constant* Init = llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, NumClasses), Symbols); - + llvm::GlobalVariable *GV = - new llvm::GlobalVariable(Init->getType(), false, + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::InternalLinkage, Init, - SymbolName, - &CGM.getModule()); + SymbolName); GV->setAlignment(8); GV->setSection(SectionName); - UsedGlobals.push_back(GV); + CGM.AddUsedGlobal(GV); } - + void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { // nonfragile abi has no module definition. - + // Build list of all implemented class addresses in array // L_OBJC_LABEL_CLASS_$. - AddModuleClassList(DefinedClasses, + AddModuleClassList(DefinedClasses, "\01L_OBJC_LABEL_CLASS_$", "__DATA, __objc_classlist, regular, no_dead_strip"); - AddModuleClassList(DefinedNonLazyClasses, + AddModuleClassList(DefinedNonLazyClasses, "\01L_OBJC_LABEL_NONLAZY_CLASS_$", "__DATA, __objc_nlclslist, regular, no_dead_strip"); - + // Build list of all implemented category addresses in array // L_OBJC_LABEL_CATEGORY_$. - AddModuleClassList(DefinedCategories, + AddModuleClassList(DefinedCategories, "\01L_OBJC_LABEL_CATEGORY_$", "__DATA, __objc_catlist, regular, no_dead_strip"); - AddModuleClassList(DefinedNonLazyCategories, + AddModuleClassList(DefinedNonLazyCategories, "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$", "__DATA, __objc_nlcatlist, regular, no_dead_strip"); - + // static int L_OBJC_IMAGE_INFO[2] = { 0, flags }; // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0 std::vector<llvm::Constant*> Values(2); @@ -4086,22 +4130,21 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { flags |= eImageInfo_GCOnly; Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); llvm::Constant* Init = llvm::ConstantArray::get( - llvm::ArrayType::get(ObjCTypes.IntTy, 2), - Values); + llvm::ArrayType::get(ObjCTypes.IntTy, 2), + Values); llvm::GlobalVariable *IMGV = - new llvm::GlobalVariable(Init->getType(), false, + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::InternalLinkage, Init, - "\01L_OBJC_IMAGE_INFO", - &CGM.getModule()); + "\01L_OBJC_IMAGE_INFO"); IMGV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip"); IMGV->setConstant(true); - UsedGlobals.push_back(IMGV); + CGM.AddUsedGlobal(IMGV); } /// LegacyDispatchedSelector - Returns true if SEL is not in the list of /// NonLegacyDispatchMethods; false otherwise. What this means is that -/// except for the 19 selectors in the list, we generate 32bit-style +/// except for the 19 selectors in the list, we generate 32bit-style /// message dispatch call for all the rest. /// bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { @@ -4116,7 +4159,7 @@ bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { NonLegacyDispatchMethods.insert(GetNullarySelector("release")); NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease")); NonLegacyDispatchMethods.insert(GetNullarySelector("hash")); - + NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone")); NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass")); NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector")); @@ -4125,11 +4168,11 @@ bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString")); NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual")); NonLegacyDispatchMethods.insert(GetUnarySelector("addObject")); - // "countByEnumeratingWithState:objects:count" + // "countByEnumeratingWithState:objects:count" IdentifierInfo *KeyIdents[] = { - &CGM.getContext().Idents.get("countByEnumeratingWithState"), - &CGM.getContext().Idents.get("objects"), - &CGM.getContext().Idents.get("count") + &CGM.getContext().Idents.get("countByEnumeratingWithState"), + &CGM.getContext().Idents.get("objects"), + &CGM.getContext().Idents.get("count") }; NonLegacyDispatchMethods.insert( CGM.getContext().Selectors.getSelector(3, KeyIdents)); @@ -4161,43 +4204,43 @@ enum MetaDataDlags { /// } /// llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( - unsigned flags, - unsigned InstanceStart, - unsigned InstanceSize, - const ObjCImplementationDecl *ID) { + unsigned flags, + unsigned InstanceStart, + unsigned InstanceSize, + const ObjCImplementationDecl *ID) { std::string ClassName = ID->getNameAsString(); std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets! Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart); Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize); // FIXME. For 64bit targets add 0 here. - Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) - : BuildIvarLayout(ID, true); + Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) + : BuildIvarLayout(ID, true); Values[ 4] = GetClassName(ID->getIdentifier()); // const struct _method_list_t * const baseMethods; std::vector<llvm::Constant*> Methods; std::string MethodListName("\01l_OBJC_$_"); if (flags & CLS_META) { MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); - for (ObjCImplementationDecl::classmeth_iterator + for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { // Class methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } } else { MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString(); - for (ObjCImplementationDecl::instmeth_iterator + for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } - for (ObjCImplementationDecl::propimpl_iterator + for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; - + if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ ObjCPropertyDecl *PD = PID->getPropertyDecl(); - + if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) if (llvm::Constant *C = GetMethodConstant(MD)) Methods.push_back(C); @@ -4207,39 +4250,37 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( } } } - Values[ 5] = EmitMethodList(MethodListName, - "__DATA, __objc_const", Methods); - + Values[ 5] = EmitMethodList(MethodListName, + "__DATA, __objc_const", Methods); + const ObjCInterfaceDecl *OID = ID->getClassInterface(); assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); - Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" + Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" + OID->getNameAsString(), OID->protocol_begin(), OID->protocol_end()); - + if (flags & CLS_META) Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); else Values[ 7] = EmitIvarList(ID); - Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) - : BuildIvarLayout(ID, false); + Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) + : BuildIvarLayout(ID, false); if (flags & CLS_META) Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); else - Values[ 9] = - EmitPropertyList( - "\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(), + Values[ 9] = + EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(), ID, ID->getClassInterface(), ObjCTypes); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, Values); llvm::GlobalVariable *CLASS_RO_GV = - new llvm::GlobalVariable(ObjCTypes.ClassRonfABITy, false, - llvm::GlobalValue::InternalLinkage, - Init, - (flags & CLS_META) ? - std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName : - std::string("\01l_OBJC_CLASS_RO_$_")+ClassName, - &CGM.getModule()); + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false, + llvm::GlobalValue::InternalLinkage, + Init, + (flags & CLS_META) ? + std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName : + std::string("\01l_OBJC_CLASS_RO_$_")+ClassName); CLASS_RO_GV->setAlignment( CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassRonfABITy)); CLASS_RO_GV->setSection("__DATA, __objc_const"); @@ -4258,20 +4299,20 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( /// } /// llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( - std::string &ClassName, - llvm::Constant *IsAGV, - llvm::Constant *SuperClassGV, - llvm::Constant *ClassRoGV, - bool HiddenVisibility) { + std::string &ClassName, + llvm::Constant *IsAGV, + llvm::Constant *SuperClassGV, + llvm::Constant *ClassRoGV, + bool HiddenVisibility) { std::vector<llvm::Constant*> Values(5); Values[0] = IsAGV; - Values[1] = SuperClassGV - ? SuperClassGV - : llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy); + Values[1] = SuperClassGV; + if (!Values[1]) + Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy); Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar Values[4] = ClassRoGV; // &CLASS_RO_GV - llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, + llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, Values); llvm::GlobalVariable *GV = GetClassGlobal(ClassName); GV->setInitializer(Init); @@ -4283,7 +4324,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( return GV; } -bool +bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { return OD->getClassMethod(GetNullarySelector("load")) != 0; } @@ -4291,11 +4332,11 @@ CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, uint32_t &InstanceStart, uint32_t &InstanceSize) { - const ASTRecordLayout &RL = + const ASTRecordLayout &RL = CGM.getContext().getASTObjCImplementationLayout(OID); - + // InstanceSize is really instance end. - InstanceSize = llvm::RoundUpToAlignment(RL.getNextOffset(), 8) / 8; + InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8; // If there are no fields, the start is the same as the end. if (!RL.getFieldCount()) @@ -4308,34 +4349,34 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { std::string ClassName = ID->getNameAsString(); if (!ObjCEmptyCacheVar) { ObjCEmptyCacheVar = new llvm::GlobalVariable( - ObjCTypes.CacheTy, - false, - llvm::GlobalValue::ExternalLinkage, - 0, - "_objc_empty_cache", - &CGM.getModule()); - + CGM.getModule(), + ObjCTypes.CacheTy, + false, + llvm::GlobalValue::ExternalLinkage, + 0, + "_objc_empty_cache"); + ObjCEmptyVtableVar = new llvm::GlobalVariable( - ObjCTypes.ImpnfABITy, - false, - llvm::GlobalValue::ExternalLinkage, - 0, - "_objc_empty_vtable", - &CGM.getModule()); - } - assert(ID->getClassInterface() && + CGM.getModule(), + ObjCTypes.ImpnfABITy, + false, + llvm::GlobalValue::ExternalLinkage, + 0, + "_objc_empty_vtable"); + } + assert(ID->getClassInterface() && "CGObjCNonFragileABIMac::GenerateClass - class is 0"); // FIXME: Is this correct (that meta class size is never computed)? - uint32_t InstanceStart = + uint32_t InstanceStart = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy); uint32_t InstanceSize = InstanceStart; uint32_t flags = CLS_META; std::string ObjCMetaClassName(getMetaclassSymbolPrefix()); std::string ObjCClassName(getClassSymbolPrefix()); - + llvm::GlobalVariable *SuperClassGV, *IsAGV; - - bool classIsHidden = + + bool classIsHidden = CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden; if (classIsHidden) flags |= OBJC2_CLS_HIDDEN; @@ -4351,7 +4392,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { Root = Super; IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString()); // work on super class metadata symbol. - std::string SuperClassName = + std::string SuperClassName = ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString(); SuperClassGV = GetClassGlobal(SuperClassName); } @@ -4359,7 +4400,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { InstanceStart, InstanceSize,ID); std::string TClassName = ObjCMetaClassName + ClassName; - llvm::GlobalVariable *MetaTClass = + llvm::GlobalVariable *MetaTClass = BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden); @@ -4383,11 +4424,11 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { GetClassSizeInfo(ID, InstanceStart, InstanceSize); CLASS_RO_GV = BuildClassRoTInitializer(flags, InstanceStart, - InstanceSize, + InstanceSize, ID); - + TClassName = ObjCClassName + ClassName; - llvm::GlobalVariable *ClassMD = + llvm::GlobalVariable *ClassMD = BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden); DefinedClasses.push_back(ClassMD); @@ -4410,29 +4451,30 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { /// which will hold address of the protocol meta-data. /// llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder, - const ObjCProtocolDecl *PD) { - + const ObjCProtocolDecl *PD) { + // This routine is called for @protocol only. So, we must build definition // of protocol's meta-data (not a reference to it!) // - llvm::Constant *Init = llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), - ObjCTypes.ExternalProtocolPtrTy); - + llvm::Constant *Init = + llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), + ObjCTypes.ExternalProtocolPtrTy); + std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); ProtocolName += PD->getNameAsCString(); - + llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); if (PTGV) return Builder.CreateLoad(PTGV, false, "tmp"); PTGV = new llvm::GlobalVariable( - Init->getType(), false, - llvm::GlobalValue::WeakAnyLinkage, - Init, - ProtocolName, - &CGM.getModule()); + CGM.getModule(), + Init->getType(), false, + llvm::GlobalValue::WeakAnyLinkage, + Init, + ProtocolName); PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip"); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - UsedGlobals.push_back(PTGV); + CGM.AddUsedGlobal(PTGV); return Builder.CreateLoad(PTGV, false, "tmp"); } @@ -4449,11 +4491,11 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder, void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); const char *Prefix = "\01l_OBJC_$_CATEGORY_"; - std::string ExtCatName(Prefix + Interface->getNameAsString()+ - "_$_" + OCD->getNameAsString()); - std::string ExtClassName(getClassSymbolPrefix() + + std::string ExtCatName(Prefix + Interface->getNameAsString()+ + "_$_" + OCD->getNameAsString()); + std::string ExtClassName(getClassSymbolPrefix() + Interface->getNameAsString()); - + std::vector<llvm::Constant*> Values(6); Values[0] = GetClassName(OCD->getIdentifier()); // meta-class entry symbol @@ -4461,33 +4503,33 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Values[1] = ClassGV; std::vector<llvm::Constant*> Methods; std::string MethodListName(Prefix); - MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() + + MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() + "_$_" + OCD->getNameAsString(); - - for (ObjCCategoryImplDecl::instmeth_iterator + + for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } - - Values[2] = EmitMethodList(MethodListName, - "__DATA, __objc_const", + + Values[2] = EmitMethodList(MethodListName, + "__DATA, __objc_const", Methods); MethodListName = Prefix; MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" + OCD->getNameAsString(); Methods.clear(); - for (ObjCCategoryImplDecl::classmeth_iterator + for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { // Class methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } - - Values[3] = EmitMethodList(MethodListName, - "__DATA, __objc_const", + + Values[3] = EmitMethodList(MethodListName, + "__DATA, __objc_const", Methods); - const ObjCCategoryDecl *Category = + const ObjCCategoryDecl *Category = Interface->FindCategoryDeclaration(OCD->getIdentifier()); if (Category) { std::string ExtName(Interface->getNameAsString() + "_$_" + @@ -4500,26 +4542,24 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Values[5] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName, OCD, Category, ObjCTypes); - } - else { + } else { Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); } - - llvm::Constant *Init = - llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy, + + llvm::Constant *Init = + llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy, Values); llvm::GlobalVariable *GCATV - = new llvm::GlobalVariable(ObjCTypes.CategorynfABITy, + = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy, false, llvm::GlobalValue::InternalLinkage, Init, - ExtCatName, - &CGM.getModule()); + ExtCatName); GCATV->setAlignment( CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.CategorynfABITy)); GCATV->setSection("__DATA, __objc_const"); - UsedGlobals.push_back(GCATV); + CGM.AddUsedGlobal(GCATV); DefinedCategories.push_back(GCATV); // Determine if this category is also "non-lazy". @@ -4531,16 +4571,16 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { /// given method if it has been defined. The result is null if the /// method has not been defined. The return value has type MethodPtrTy. llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant( - const ObjCMethodDecl *MD) { + const ObjCMethodDecl *MD) { // FIXME: Use DenseMap::lookup llvm::Function *Fn = MethodDefinitions[MD]; if (!Fn) return 0; - + std::vector<llvm::Constant*> Method(3); - Method[0] = - llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), - ObjCTypes.SelectorPtrTy); + Method[0] = + llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), + ObjCTypes.SelectorPtrTy); Method[1] = GetMethodVarType(MD); Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy); return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); @@ -4554,13 +4594,13 @@ llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant( /// } /// llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList( - const std::string &Name, - const char *Section, - const ConstantVector &Methods) { + const std::string &Name, + const char *Section, + const ConstantVector &Methods) { // Return null for empty list. if (Methods.empty()) return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); - + std::vector<llvm::Constant*> Values(3); // sizeof(struct _objc_method) unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy); @@ -4570,18 +4610,17 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList( llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, Methods.size()); Values[2] = llvm::ConstantArray::get(AT, Methods); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); - + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); + llvm::GlobalVariable *GV = - new llvm::GlobalVariable(Init->getType(), false, + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::InternalLinkage, Init, - Name, - &CGM.getModule()); + Name); GV->setAlignment( CGM.getTargetData().getPrefTypeAlignment(Init->getType())); GV->setSection(Section); - UsedGlobals.push_back(GV); + CGM.AddUsedGlobal(GV); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy); } @@ -4589,34 +4628,33 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList( /// ObjCIvarOffsetVariable - Returns the ivar offset variable for /// the given ivar. llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar) { + const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar) { // FIXME: We shouldn't need to do this lookup. unsigned Index; - const ObjCInterfaceDecl *Container = + const ObjCInterfaceDecl *Container = FindIvarInterface(CGM.getContext(), ID, Ivar, Index); assert(Container && "Unable to find ivar container!"); std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() + '.' + Ivar->getNameAsString(); - llvm::GlobalVariable *IvarOffsetGV = + llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name); if (!IvarOffsetGV) - IvarOffsetGV = - new llvm::GlobalVariable(ObjCTypes.LongTy, + IvarOffsetGV = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy, false, llvm::GlobalValue::ExternalLinkage, 0, - Name, - &CGM.getModule()); + Name); return IvarOffsetGV; } llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar, - unsigned long int Offset) { + const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar, + unsigned long int Offset) { llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); - IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, + IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, Offset)); IvarOffsetGV->setAlignment( CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy)); @@ -4651,25 +4689,25 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( /// llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( - const ObjCImplementationDecl *ID) { - + const ObjCImplementationDecl *ID) { + std::vector<llvm::Constant*> Ivars, Ivar(5); - + const ObjCInterfaceDecl *OID = ID->getClassInterface(); assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); - + // FIXME. Consolidate this with similar code in GenerateClass. - + // Collect declared and synthesized ivars in a small vector. llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); - + for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { ObjCIvarDecl *IVD = OIvars[i]; // Ignore unnamed bit-fields. if (!IVD->getDeclName()) continue; - Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, + Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, ComputeIvarBaseOffset(CGM, ID, IVD)); Ivar[1] = GetMethodVarName(IVD->getIdentifier()); Ivar[2] = GetMethodVarType(IVD); @@ -4677,7 +4715,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( CGM.getTypes().ConvertTypeForMem(IVD->getType()); unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy); unsigned Align = CGM.getContext().getPreferredTypeAlign( - IVD->getType().getTypePtr()) >> 3; + IVD->getType().getTypePtr()) >> 3; Align = llvm::Log2_32(Align); Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align); // NOTE. Size of a bitfield does not match gcc's, because of the @@ -4698,41 +4736,37 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy, Ivars.size()); Values[2] = llvm::ConstantArray::get(AT, Ivars); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; llvm::GlobalVariable *GV = - new llvm::GlobalVariable(Init->getType(), false, + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::InternalLinkage, Init, - Prefix + OID->getNameAsString(), - &CGM.getModule()); + Prefix + OID->getNameAsString()); GV->setAlignment( CGM.getTargetData().getPrefTypeAlignment(Init->getType())); GV->setSection("__DATA, __objc_const"); - - UsedGlobals.push_back(GV); - return llvm::ConstantExpr::getBitCast(GV, - ObjCTypes.IvarListnfABIPtrTy); + + CGM.AddUsedGlobal(GV); + return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); } llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( - const ObjCProtocolDecl *PD) { + const ObjCProtocolDecl *PD) { llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; - + if (!Entry) { // We use the initializer as a marker of whether this is a forward // reference or not. At module finalization we add the empty // contents for protocols which were referenced but never defined. - Entry = - new llvm::GlobalVariable(ObjCTypes.ProtocolnfABITy, false, - llvm::GlobalValue::ExternalLinkage, - 0, - "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString(), - &CGM.getModule()); + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, + llvm::GlobalValue::ExternalLinkage, + 0, + "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString()); Entry->setSection("__DATA,__datacoal_nt,coalesced"); - UsedGlobals.push_back(Entry); } - + return Entry; } @@ -4754,19 +4788,19 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( /// llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( - const ObjCProtocolDecl *PD) { + const ObjCProtocolDecl *PD) { llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; - + // Early exit if a defining object has already been generated. if (Entry && Entry->hasInitializer()) return Entry; const char *ProtocolName = PD->getNameAsCString(); - + // Construct method lists. std::vector<llvm::Constant*> InstanceMethods, ClassMethods; std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; - for (ObjCProtocolDecl::instmeth_iterator + for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); @@ -4774,10 +4808,10 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( OptInstanceMethods.push_back(C); } else { InstanceMethods.push_back(C); - } + } } - - for (ObjCProtocolDecl::classmeth_iterator + + for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); @@ -4785,23 +4819,23 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( OptClassMethods.push_back(C); } else { ClassMethods.push_back(C); - } + } } - + std::vector<llvm::Constant*> Values(10); // isa is NULL Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy); Values[1] = GetClassName(PD->getIdentifier()); Values[2] = EmitProtocolList( - "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(), - PD->protocol_begin(), - PD->protocol_end()); - + "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(), + PD->protocol_begin(), + PD->protocol_end()); + Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_" + PD->getNameAsString(), "__DATA, __objc_const", InstanceMethods); - Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" + Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" + PD->getNameAsString(), "__DATA, __objc_const", ClassMethods); @@ -4809,50 +4843,50 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( + PD->getNameAsString(), "__DATA, __objc_const", OptInstanceMethods); - Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" + Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" + PD->getNameAsString(), "__DATA, __objc_const", OptClassMethods); Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(), 0, PD, ObjCTypes); - uint32_t Size = + uint32_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy, Values); - + if (Entry) { // Already created, fix the linkage and update the initializer. Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); Entry->setInitializer(Init); } else { - Entry = - new llvm::GlobalVariable(ObjCTypes.ProtocolnfABITy, false, - llvm::GlobalValue::WeakAnyLinkage, - Init, - std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName, - &CGM.getModule()); + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, + llvm::GlobalValue::WeakAnyLinkage, + Init, + std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName); Entry->setAlignment( CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy)); Entry->setSection("__DATA,__datacoal_nt,coalesced"); } Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); - + CGM.AddUsedGlobal(Entry); + // Use this protocol meta-data to build protocol list table in section // __DATA, __objc_protolist llvm::GlobalVariable *PTGV = new llvm::GlobalVariable( - ObjCTypes.ProtocolnfABIPtrTy, false, - llvm::GlobalValue::WeakAnyLinkage, - Entry, - std::string("\01l_OBJC_LABEL_PROTOCOL_$_") - +ProtocolName, - &CGM.getModule()); + CGM.getModule(), + ObjCTypes.ProtocolnfABIPtrTy, false, + llvm::GlobalValue::WeakAnyLinkage, + Entry, + std::string("\01l_OBJC_LABEL_PROTOCOL_$_") + +ProtocolName); PTGV->setAlignment( CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - UsedGlobals.push_back(PTGV); + CGM.AddUsedGlobal(PTGV); return Entry; } @@ -4866,45 +4900,46 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( /// llvm::Constant * CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name, - ObjCProtocolDecl::protocol_iterator begin, - ObjCProtocolDecl::protocol_iterator end) { + ObjCProtocolDecl::protocol_iterator begin, + ObjCProtocolDecl::protocol_iterator end) { std::vector<llvm::Constant*> ProtocolRefs; - + // Just return null for empty protocol lists - if (begin == end) + if (begin == end) return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); - + // FIXME: We shouldn't need to do this lookup here, should we? llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); if (GV) - return llvm::ConstantExpr::getBitCast(GV, + return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); - + for (; begin != end; ++begin) ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented??? // This list is null terminated. ProtocolRefs.push_back(llvm::Constant::getNullValue( - ObjCTypes.ProtocolnfABIPtrTy)); - + ObjCTypes.ProtocolnfABIPtrTy)); + std::vector<llvm::Constant*> Values(2); - Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1); - Values[1] = - llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy, - ProtocolRefs.size()), - ProtocolRefs); - - llvm::Constant *Init = llvm::ConstantStruct::get(Values); - GV = new llvm::GlobalVariable(Init->getType(), false, + Values[0] = + llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1); + Values[1] = + llvm::ConstantArray::get( + llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy, + ProtocolRefs.size()), + ProtocolRefs); + + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); + GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::InternalLinkage, Init, - Name, - &CGM.getModule()); + Name); GV->setSection("__DATA, __objc_const"); GV->setAlignment( CGM.getTargetData().getPrefTypeAlignment(Init->getType())); - UsedGlobals.push_back(GV); - return llvm::ConstantExpr::getBitCast(GV, + CGM.AddUsedGlobal(GV); + return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); } @@ -4918,8 +4953,9 @@ CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name, llvm::Constant * CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { std::vector<llvm::Constant*> Desc(3); - Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), - ObjCTypes.SelectorPtrTy); + Desc[0] = + llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), + ObjCTypes.SelectorPtrTy); Desc[1] = GetMethodVarType(MD); // Protocol methods have no implementation. So, this entry is always NULL. Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); @@ -4931,46 +4967,46 @@ CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { /// @code /// (type *)((char *)base + _OBJC_IVAR_$_.ivar; /// @encode -/// +/// LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( - CodeGen::CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) { - const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl(); + CodeGen::CodeGenFunction &CGF, + QualType ObjectTy, + llvm::Value *BaseValue, + const ObjCIvarDecl *Ivar, + unsigned CVRQualifiers) { + const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( - CodeGen::CodeGenFunction &CGF, - const ObjCInterfaceDecl *Interface, - const ObjCIvarDecl *Ivar) { - return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar), + CodeGen::CodeGenFunction &CGF, + const ObjCInterfaceDecl *Interface, + const ObjCIvarDecl *Ivar) { + return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar"); } CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( - CodeGen::CodeGenFunction &CGF, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - QualType Arg0Ty, - bool IsSuper, - const CallArgList &CallArgs) { + CodeGen::CodeGenFunction &CGF, + QualType ResultType, + Selector Sel, + llvm::Value *Receiver, + QualType Arg0Ty, + bool IsSuper, + const CallArgList &CallArgs) { // FIXME. Even though IsSuper is passes. This function doese not handle calls // to 'super' receivers. CodeGenTypes &Types = CGM.getTypes(); llvm::Value *Arg0 = Receiver; if (!IsSuper) Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); - + // Find the message function name. // FIXME. This is too much work to get the ABI-specific result type needed to // find the message name. - const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, - llvm::SmallVector<QualType, 16>()); + const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, + llvm::SmallVector<QualType, 16>()); llvm::Constant *Fn = 0; std::string Name("\01l_"); if (CGM.ReturnTypeUsesSret(FnInfo)) { @@ -4981,53 +5017,44 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( // FIXME. Is there a better way of getting these names. // They are available in RuntimeFunctions vector pair. Name += "objc_msgSendId_stret_fixup"; - } - else + } else #endif - if (IsSuper) { + if (IsSuper) { Fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); Name += "objc_msgSendSuper2_stret_fixup"; - } - else - { - Fn = ObjCTypes.getMessageSendStretFixupFn(); - Name += "objc_msgSend_stret_fixup"; - } - } - else if (!IsSuper && ResultType->isFloatingType()) { + } else { + Fn = ObjCTypes.getMessageSendStretFixupFn(); + Name += "objc_msgSend_stret_fixup"; + } + } else if (!IsSuper && ResultType->isFloatingType()) { if (ResultType->isSpecificBuiltinType(BuiltinType::LongDouble)) { Fn = ObjCTypes.getMessageSendFpretFixupFn(); Name += "objc_msgSend_fpret_fixup"; - } - else { + } else { Fn = ObjCTypes.getMessageSendFixupFn(); Name += "objc_msgSend_fixup"; } - } - else { + } else { #if 0 // unlike what is documented. gcc never generates this API!! if (Receiver->getType() == ObjCTypes.ObjectPtrTy) { Fn = ObjCTypes.getMessageSendIdFixupFn(); Name += "objc_msgSendId_fixup"; - } - else + } else #endif - if (IsSuper) { + if (IsSuper) { Fn = ObjCTypes.getMessageSendSuper2FixupFn(); Name += "objc_msgSendSuper2_fixup"; - } - else - { - Fn = ObjCTypes.getMessageSendFixupFn(); - Name += "objc_msgSend_fixup"; - } + } else { + Fn = ObjCTypes.getMessageSendFixupFn(); + Name += "objc_msgSend_fixup"; + } } assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend"); Name += '_'; std::string SelName(Sel.getAsString()); // Replace all ':' in selector name with '_' ouch! - for(unsigned i = 0; i < SelName.size(); i++) + for (unsigned i = 0; i < SelName.size(); i++) if (SelName[i] == ':') SelName[i] = '_'; Name += SelName; @@ -5037,21 +5064,20 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( std::vector<llvm::Constant*> Values(2); Values[0] = Fn; Values[1] = GetMethodVarName(Sel); - llvm::Constant *Init = llvm::ConstantStruct::get(Values); - GV = new llvm::GlobalVariable(Init->getType(), false, + llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); + GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::WeakAnyLinkage, Init, - Name, - &CGM.getModule()); + Name); GV->setVisibility(llvm::GlobalValue::HiddenVisibility); GV->setAlignment(16); GV->setSection("__DATA, __objc_msgrefs, coalesced"); } llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy); - + CallArgList ActualArgs; ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); - ActualArgs.push_back(std::make_pair(RValue::get(Arg1), + ActualArgs.push_back(std::make_pair(RValue::get(Arg1), ObjCTypes.MessageRefCPtrTy)); ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs); @@ -5064,21 +5090,21 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( } /// Generate code for a message send expression in the nonfragile abi. -CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend( - CodeGen::CodeGenFunction &CGF, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - bool IsClassMessage, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method) { +CodeGen::RValue +CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, + QualType ResultType, + Selector Sel, + llvm::Value *Receiver, + bool IsClassMessage, + const CallArgList &CallArgs, + const ObjCMethodDecl *Method) { return LegacyDispatchedSelector(Sel) - ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel), - Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs, ObjCTypes) - : EmitMessageSend(CGF, ResultType, Sel, - Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs); + ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel), + Receiver, CGF.getContext().getObjCIdType(), + false, CallArgs, Method, ObjCTypes) + : EmitMessageSend(CGF, ResultType, Sel, + Receiver, CGF.getContext().getObjCIdType(), + false, CallArgs); } llvm::GlobalVariable * @@ -5086,85 +5112,82 @@ CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) { llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); if (!GV) { - GV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, - llvm::GlobalValue::ExternalLinkage, - 0, Name, &CGM.getModule()); + GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy, + false, llvm::GlobalValue::ExternalLinkage, + 0, Name); } return GV; } -llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder, - const ObjCInterfaceDecl *ID) { +llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder, + const ObjCInterfaceDecl *ID) { llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; - + if (!Entry) { std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); - Entry = - new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false, - llvm::GlobalValue::InternalLinkage, - ClassGV, - "\01L_OBJC_CLASSLIST_REFERENCES_$_", - &CGM.getModule()); + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, + false, llvm::GlobalValue::InternalLinkage, + ClassGV, + "\01L_OBJC_CLASSLIST_REFERENCES_$_"); Entry->setAlignment( - CGM.getTargetData().getPrefTypeAlignment( - ObjCTypes.ClassnfABIPtrTy)); + CGM.getTargetData().getPrefTypeAlignment( + ObjCTypes.ClassnfABIPtrTy)); Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip"); - UsedGlobals.push_back(Entry); + CGM.AddUsedGlobal(Entry); } - + return Builder.CreateLoad(Entry, false, "tmp"); } llvm::Value * -CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder, +CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder, const ObjCInterfaceDecl *ID) { llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; - + if (!Entry) { std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); - Entry = - new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false, - llvm::GlobalValue::InternalLinkage, - ClassGV, - "\01L_OBJC_CLASSLIST_SUP_REFS_$_", - &CGM.getModule()); + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, + false, llvm::GlobalValue::InternalLinkage, + ClassGV, + "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); Entry->setAlignment( - CGM.getTargetData().getPrefTypeAlignment( - ObjCTypes.ClassnfABIPtrTy)); + CGM.getTargetData().getPrefTypeAlignment( + ObjCTypes.ClassnfABIPtrTy)); Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); - UsedGlobals.push_back(Entry); + CGM.AddUsedGlobal(Entry); } - + return Builder.CreateLoad(Entry, false, "tmp"); } /// EmitMetaClassRef - Return a Value * of the address of _class_t /// meta-data /// -llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, - const ObjCInterfaceDecl *ID) { +llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, + const ObjCInterfaceDecl *ID) { llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; if (Entry) return Builder.CreateLoad(Entry, false, "tmp"); - + std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString()); llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName); - Entry = - new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false, + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, llvm::GlobalValue::InternalLinkage, - MetaClassGV, - "\01L_OBJC_CLASSLIST_SUP_REFS_$_", - &CGM.getModule()); + MetaClassGV, + "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); Entry->setAlignment( - CGM.getTargetData().getPrefTypeAlignment( - ObjCTypes.ClassnfABIPtrTy)); - + CGM.getTargetData().getPrefTypeAlignment( + ObjCTypes.ClassnfABIPtrTy)); + Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); - UsedGlobals.push_back(Entry); - + CGM.AddUsedGlobal(Entry); + return Builder.CreateLoad(Entry, false, "tmp"); } @@ -5180,24 +5203,25 @@ llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, /// which class's method should be called. CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Receiver, - bool IsClassMessage, - const CodeGen::CallArgList &CallArgs) { + QualType ResultType, + Selector Sel, + const ObjCInterfaceDecl *Class, + bool isCategoryImpl, + llvm::Value *Receiver, + bool IsClassMessage, + const CodeGen::CallArgList &CallArgs, + const ObjCMethodDecl *Method) { // ... // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); - + llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, CGF.Builder.CreateStructGEP(ObjCSuper, 0)); - + // If this is a class message the metaclass is passed as the target. llvm::Value *Target; if (IsClassMessage) { @@ -5207,13 +5231,11 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, Target = EmitClassRef(CGF.Builder, Class); Target = CGF.Builder.CreateStructGEP(Target, 0); Target = CGF.Builder.CreateLoad(Target); - } - else + } else Target = EmitMetaClassRef(CGF.Builder, Class); - } - else + } else Target = EmitSuperClassRef(CGF.Builder, Class); - + // FIXME: We shouldn't need to do this cast, rectify the ASTContext and // ObjCTypes types. const llvm::Type *ClassTy = @@ -5221,42 +5243,41 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, Target = CGF.Builder.CreateBitCast(Target, ClassTy); CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); - + return (LegacyDispatchedSelector(Sel)) - ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel), - ObjCSuper, ObjCTypes.SuperPtrCTy, - true, CallArgs, - ObjCTypes) - : EmitMessageSend(CGF, ResultType, Sel, - ObjCSuper, ObjCTypes.SuperPtrCTy, - true, CallArgs); + ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel), + ObjCSuper, ObjCTypes.SuperPtrCTy, + true, CallArgs, Method, ObjCTypes) + : EmitMessageSend(CGF, ResultType, Sel, + ObjCSuper, ObjCTypes.SuperPtrCTy, + true, CallArgs); } -llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, +llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; - + if (!Entry) { - llvm::Constant *Casted = - llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), - ObjCTypes.SelectorPtrTy); - Entry = - new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false, - llvm::GlobalValue::InternalLinkage, - Casted, "\01L_OBJC_SELECTOR_REFERENCES_", - &CGM.getModule()); + llvm::Constant *Casted = + llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), + ObjCTypes.SelectorPtrTy); + Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false, + llvm::GlobalValue::InternalLinkage, + Casted, "\01L_OBJC_SELECTOR_REFERENCES_"); Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip"); - UsedGlobals.push_back(Entry); + CGM.AddUsedGlobal(Entry); } - + return Builder.CreateLoad(Entry, false, "tmp"); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. -/// objc_assign_ivar (id src, id *dst) +/// objc_assign_ivar (id src, id *dst, ptrdiff_t) /// void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, + llvm::Value *dst, + llvm::Value *ivarOffset) { const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); @@ -5267,8 +5288,8 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); - CGF.Builder.CreateCall2(ObjCTypes.getGcAssignIvarFn(), - src, dst, "assignivar"); + CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), + src, dst, ivarOffset); return; } @@ -5276,15 +5297,14 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, /// objc_assign_strongCast (id src, id *dst) /// void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( - CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + CodeGen::CodeGenFunction &CGF, + llvm::Value *src, llvm::Value *dst) { const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); @@ -5294,16 +5314,31 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( return; } +void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( + CodeGen::CodeGenFunction &CGF, + llvm::Value *DestPtr, + llvm::Value *SrcPtr, + QualType Ty) { + // Get size info for this aggregate. + std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); + unsigned long size = TypeInfo.first/8; + SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); + DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); + llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); + CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), + DestPtr, SrcPtr, N); + return; +} + /// EmitObjCWeakRead - Code gen for loading value of a __weak /// object: objc_read_weak (id *src) /// llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( - CodeGen::CodeGenFunction &CGF, - llvm::Value *AddrWeakObj) -{ + CodeGen::CodeGenFunction &CGF, + llvm::Value *AddrWeakObj) { const llvm::Type* DestTy = - cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); - AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); + cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); + AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObj, "weakread"); read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); @@ -5314,8 +5349,7 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( /// objc_assign_weak (id src, id *dst) /// void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); @@ -5335,8 +5369,7 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, /// objc_assign_global (id src, id *dst) /// void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dst) -{ + llvm::Value *src, llvm::Value *dst) { const llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); @@ -5352,7 +5385,7 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, return; } -void +void CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S) { bool isTry = isa<ObjCAtTryStmt>(S); @@ -5369,7 +5402,7 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // @synchronized are illegal & this will dominate uses. llvm::Value *SyncArg = 0; if (!isTry) { - SyncArg = + SyncArg = CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg); @@ -5382,20 +5415,20 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.setInvokeDest(TryHandler); CGF.EmitBlock(TryBlock); - CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() - : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); + CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() + : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); CGF.EmitBranchThroughCleanup(FinallyEnd); - + // Emit the exception handler. CGF.EmitBlock(TryHandler); - llvm::Value *llvm_eh_exception = + llvm::Value *llvm_eh_exception = CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); - llvm::Value *llvm_eh_selector_i64 = - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector_i64); - llvm::Value *llvm_eh_typeid_for_i64 = - CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for_i64); + llvm::Value *llvm_eh_selector = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); + llvm::Value *llvm_eh_typeid_for = + CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow"); @@ -5422,40 +5455,42 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, break; } - if (CGF.getContext().isObjCIdType(CatchDecl->getType()) || + if (CatchDecl->getType()->isObjCIdType() || CatchDecl->getType()->isObjCQualifiedIdType()) { - llvm::Value *IDEHType = + llvm::Value *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); if (!IDEHType) - IDEHType = - new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false, + IDEHType = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, + false, llvm::GlobalValue::ExternalLinkage, - 0, "OBJC_EHTYPE_id", &CGM.getModule()); + 0, "OBJC_EHTYPE_id"); SelectorArgs.push_back(IDEHType); - HasCatchAll = true; - break; - } - - // All other types should be Objective-C interface pointer types. - const PointerType *PT = CatchDecl->getType()->getAsPointerType(); - assert(PT && "Invalid @catch type."); - const ObjCInterfaceType *IT = - PT->getPointeeType()->getAsObjCInterfaceType(); - assert(IT && "Invalid @catch type."); - llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false); - SelectorArgs.push_back(EHType); + } else { + // All other types should be Objective-C interface pointer types. + const ObjCObjectPointerType *PT = + CatchDecl->getType()->getAs<ObjCObjectPointerType>(); + assert(PT && "Invalid @catch type."); + const ObjCInterfaceType *IT = PT->getInterfaceType(); + assert(IT && "Invalid @catch type."); + llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false); + SelectorArgs.push_back(EHType); + } } } } // We use a cleanup unless there was already a catch all. if (!HasCatchAll) { - SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0)); + // Even though this is a cleanup, treat it as a catch all to avoid the C++ + // personality behavior of terminating the process if only cleanups are + // found in the exception handling stack. + SelectorArgs.push_back(llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy)); Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0)); } - - llvm::Value *Selector = - CGF.Builder.CreateCall(llvm_eh_selector_i64, + + llvm::Value *Selector = + CGF.Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(), SelectorArgs.end(), "selector"); for (unsigned i = 0, e = Handlers.size(); i != e; ++i) { @@ -5470,8 +5505,8 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *Match = CGF.createBasicBlock("match"); Next = CGF.createBasicBlock("catch.next"); - llvm::Value *Id = - CGF.Builder.CreateCall(llvm_eh_typeid_for_i64, + llvm::Value *Id = + CGF.Builder.CreateCall(llvm_eh_typeid_for, CGF.Builder.CreateBitCast(SelectorArgs[i+2], ObjCTypes.Int8PtrTy)); CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(Selector, Id), @@ -5479,25 +5514,25 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBlock(Match); } - + if (CatchBody) { llvm::BasicBlock *MatchEnd = CGF.createBasicBlock("match.end"); llvm::BasicBlock *MatchHandler = CGF.createBasicBlock("match.handler"); // Cleanups must call objc_end_catch. - // + // // FIXME: It seems incorrect for objc_begin_catch to be inside this // context, but this matches gcc. CGF.PushCleanupBlock(MatchEnd); CGF.setInvokeDest(MatchHandler); - - llvm::Value *ExcObject = + + llvm::Value *ExcObject = CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), Exc); // Bind the catch parameter if it exists. if (CatchParam) { - ExcObject = - CGF.Builder.CreateBitCast(ExcObject, + ExcObject = + CGF.Builder.CreateBitCast(ExcObject, CGF.ConvertType(CatchParam->getType())); // CatchParam is a ParmVarDecl because of the grammar // construction used to handle this, but for codegen purposes @@ -5520,22 +5555,22 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::SmallVector<llvm::Value*, 8> Args; Args.push_back(Exc); Args.push_back(ObjCTypes.getEHPersonalityPtr()); - Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, + Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); - CGF.Builder.CreateCall(llvm_eh_selector_i64, Args.begin(), Args.end()); + CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); CGF.Builder.CreateStore(Exc, RethrowPtr); CGF.EmitBranchThroughCleanup(FinallyRethrow); CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); - + CGF.EmitBlock(MatchEnd); // Unfortunately, we also have to generate another EH frame here // in case this throws. - llvm::BasicBlock *MatchEndHandler = + llvm::BasicBlock *MatchEndHandler = CGF.createBasicBlock("match.end.handler"); llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); - CGF.Builder.CreateInvoke(ObjCTypes.getObjCEndCatchFn(), + CGF.Builder.CreateInvoke(ObjCTypes.getObjCEndCatchFn(), Cont, MatchEndHandler, Args.begin(), Args.begin()); @@ -5552,9 +5587,9 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, Args.clear(); Args.push_back(Exc); Args.push_back(ObjCTypes.getEHPersonalityPtr()); - Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, + Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); - CGF.Builder.CreateCall(llvm_eh_selector_i64, Args.begin(), Args.end()); + CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); CGF.Builder.CreateStore(Exc, RethrowPtr); CGF.EmitBranchThroughCleanup(FinallyRethrow); @@ -5576,7 +5611,7 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBlock(FinallyBlock); if (isTry) { - if (const ObjCAtFinallyStmt* FinallyStmt = + if (const ObjCAtFinallyStmt* FinallyStmt = cast<ObjCAtTryStmt>(S).getFinallyStmt()) CGF.EmitStmt(FinallyStmt->getFinallyBody()); } else { @@ -5594,26 +5629,26 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitBranch(FinallyEnd); CGF.EmitBlock(FinallyRethrow); - CGF.Builder.CreateCall(ObjCTypes.getUnwindResumeOrRethrowFn(), + CGF.Builder.CreateCall(ObjCTypes.getUnwindResumeOrRethrowFn(), CGF.Builder.CreateLoad(RethrowPtr)); CGF.Builder.CreateUnreachable(); - + CGF.EmitBlock(FinallyEnd); } /// EmitThrowStmt - Generate code for a throw statement. void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S) { - llvm::Value *Exception; + llvm::Value *Exception; if (const Expr *ThrowExpr = S.getThrowExpr()) { Exception = CGF.EmitScalarExpr(ThrowExpr); } else { - assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && + assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && "Unexpected rethrow outside @catch block."); Exception = CGF.ObjCEHValueStack.back(); } - llvm::Value *ExceptionAsObject = + llvm::Value *ExceptionAsObject = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp"); llvm::BasicBlock *InvokeDest = CGF.getInvokeDest(); if (InvokeDest) { @@ -5623,7 +5658,7 @@ void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, &ExceptionAsObject, &ExceptionAsObject + 1); CGF.EmitBlock(Cont); } else - CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject); + CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject); CGF.Builder.CreateUnreachable(); // Clear the insertion point to indicate we are in unreachable code. @@ -5631,7 +5666,7 @@ void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, } llvm::Value * -CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, +CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, bool ForDefinition) { llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; @@ -5644,44 +5679,44 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, // If this type (or a super class) has the __objc_exception__ // attribute, emit an external reference. if (hasObjCExceptionAttribute(CGM.getContext(), ID)) - return Entry = - new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false, + return Entry = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, llvm::GlobalValue::ExternalLinkage, - 0, - (std::string("OBJC_EHTYPE_$_") + - ID->getIdentifier()->getName()), - &CGM.getModule()); + 0, + (std::string("OBJC_EHTYPE_$_") + + ID->getIdentifier()->getName())); } - + // Otherwise we need to either make a new entry or fill in the // initializer. assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); std::string VTableName = "objc_ehtype_vtable"; - llvm::GlobalVariable *VTableGV = + llvm::GlobalVariable *VTableGV = CGM.getModule().getGlobalVariable(VTableName); if (!VTableGV) - VTableGV = new llvm::GlobalVariable(ObjCTypes.Int8PtrTy, false, + VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, + false, llvm::GlobalValue::ExternalLinkage, - 0, VTableName, &CGM.getModule()); + 0, VTableName); - llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, 2); + llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2); std::vector<llvm::Constant*> Values(3); Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1); Values[1] = GetClassName(ID->getIdentifier()); Values[2] = GetClassGlobal(ClassName); - llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); + llvm::Constant *Init = + llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); if (Entry) { Entry->setInitializer(Init); } else { - Entry = new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false, + Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, llvm::GlobalValue::WeakAnyLinkage, - Init, - (std::string("OBJC_EHTYPE_$_") + - ID->getIdentifier()->getName()), - &CGM.getModule()); + Init, + (std::string("OBJC_EHTYPE_$_") + + ID->getIdentifier()->getName())); } if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden) @@ -5697,7 +5732,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, return Entry; } - + /* *** */ CodeGen::CGObjCRuntime * diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 0f9cf0606d36e..6b4556239723d 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -86,7 +86,7 @@ protected: llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers, - llvm::Value *Offset); + llvm::Value *Offset); public: virtual ~CGObjCRuntime(); @@ -95,16 +95,13 @@ public: /// this compilation unit with the runtime library. virtual llvm::Function *ModuleInitFunction() = 0; - /// Add metadata globals to the 'used' globals for final output. - virtual void MergeMetadataGlobals(std::vector<llvm::Constant*> &UsedArray) = 0; - /// Get a selector for the specified name and type values. The /// return value should have the LLVM type for pointer-to /// ASTContext::getObjCSelType(). virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel) = 0; - /// Get a typed selector. + /// Get a typed selector. virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl *Method) = 0; @@ -117,20 +114,26 @@ public: /// Generate a class stucture for this class. virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; - - /// Generate an Objective-C message send operation. - virtual CodeGen::RValue + + /// Generate an Objective-C message send operation. + /// + /// \param Method - The method being called, this may be null if synthesizing + /// a property setter or getter. + virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, llvm::Value *Receiver, bool IsClassMessage, const CallArgList &CallArgs, - const ObjCMethodDecl *Method=0) = 0; + const ObjCMethodDecl *Method = 0) = 0; /// Generate an Objective-C message send operation to the super /// class initiated in a method for Class and with the given Self /// object. + /// + /// \param Method - The method being called, this may be null if synthesizing + /// a property setter or getter. virtual CodeGen::RValue GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, @@ -139,41 +142,42 @@ public: bool isCategoryImpl, llvm::Value *Self, bool IsClassMessage, - const CallArgList &CallArgs) = 0; + const CallArgList &CallArgs, + const ObjCMethodDecl *Method = 0) = 0; /// Emit the code to return the named protocol as an object, as in a /// @protocol expression. virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *OPD) = 0; - /// Generate the named protocol. Protocols contain method metadata but no - /// implementations. + /// Generate the named protocol. Protocols contain method metadata but no + /// implementations. virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0; /// Generate a function preamble for a method with the specified - /// types. + /// types. // FIXME: Current this just generates the Function definition, but really this // should also be generating the loads of the parameters, as the runtime // should have full control over how parameters are passed. - virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, + virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD) = 0; /// Return the runtime function for getting properties. virtual llvm::Constant *GetPropertyGetFunction() = 0; - + /// Return the runtime function for setting properties. virtual llvm::Constant *GetPropertySetFunction() = 0; /// GetClass - Return a reference to the class for the given /// interface decl. - virtual llvm::Value *GetClass(CGBuilderTy &Builder, + virtual llvm::Value *GetClass(CGBuilderTy &Builder, const ObjCInterfaceDecl *OID) = 0; /// EnumerationMutationFunction - Return the function that's called by the /// compiler when a mutation is detected during foreach iteration. virtual llvm::Constant *EnumerationMutationFunction() = 0; - + virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S) = 0; virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, @@ -185,10 +189,11 @@ public: virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest) = 0; virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, llvm::Value *dest) = 0; + llvm::Value *src, llvm::Value *dest, + llvm::Value *ivarOffset) = 0; virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dest) = 0; - + virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, @@ -197,9 +202,13 @@ public: virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar) = 0; + virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, + llvm::Value *DestPtr, + llvm::Value *SrcPtr, + QualType Ty) = 0; }; -/// Creates an instance of an Objective-C runtime class. +/// Creates an instance of an Objective-C runtime class. //TODO: This should include some way of selecting which runtime to target. CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM); CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM); diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp new file mode 100644 index 0000000000000..7baf69d87689f --- /dev/null +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -0,0 +1,386 @@ +//===--- CGRecordLayoutBuilder.cpp - Record builder helper ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a helper class used to build CGRecordLayout objects and LLVM types. +// +//===----------------------------------------------------------------------===// + +#include "CGRecordLayoutBuilder.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecordLayout.h" +#include "CodeGenTypes.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Target/TargetData.h" + + +using namespace clang; +using namespace CodeGen; + +void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { + Alignment = Types.getContext().getASTRecordLayout(D).getAlignment() / 8; + Packed = D->hasAttr<PackedAttr>(); + + if (D->isUnion()) { + LayoutUnion(D); + return; + } + + if (LayoutFields(D)) + return; + + // We weren't able to layout the struct. Try again with a packed struct + Packed = true; + AlignmentAsLLVMStruct = 1; + NextFieldOffsetInBytes = 0; + FieldTypes.clear(); + LLVMFields.clear(); + LLVMBitFields.clear(); + + LayoutFields(D); +} + +void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, + uint64_t FieldOffset) { + uint64_t FieldSize = + D->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue(); + + if (FieldSize == 0) + return; + + uint64_t NextFieldOffset = NextFieldOffsetInBytes * 8; + unsigned NumBytesToAppend; + + if (FieldOffset < NextFieldOffset) { + assert(BitsAvailableInLastField && "Bitfield size mismatch!"); + assert(NextFieldOffsetInBytes && "Must have laid out at least one byte!"); + + // The bitfield begins in the previous bit-field. + NumBytesToAppend = + llvm::RoundUpToAlignment(FieldSize - BitsAvailableInLastField, 8) / 8; + } else { + assert(FieldOffset % 8 == 0 && "Field offset not aligned correctly"); + + // Append padding if necessary. + AppendBytes((FieldOffset - NextFieldOffset) / 8); + + NumBytesToAppend = + llvm::RoundUpToAlignment(FieldSize, 8) / 8; + + assert(NumBytesToAppend && "No bytes to append!"); + } + + const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType()); + uint64_t TypeSizeInBits = getTypeSizeInBytes(Ty) * 8; + + LLVMBitFields.push_back(LLVMBitFieldInfo(D, FieldOffset / TypeSizeInBits, + FieldOffset % TypeSizeInBits, + FieldSize)); + + AppendBytes(NumBytesToAppend); + + AlignmentAsLLVMStruct = std::max(AlignmentAsLLVMStruct, getTypeAlignment(Ty)); + + BitsAvailableInLastField = + NextFieldOffsetInBytes * 8 - (FieldOffset + FieldSize); +} + +bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, + uint64_t FieldOffset) { + // If the field is packed, then we need a packed struct. + if (!Packed && D->hasAttr<PackedAttr>()) + return false; + + if (D->isBitField()) { + // We must use packed structs for unnamed bit fields since they + // don't affect the struct alignment. + if (!Packed && !D->getDeclName()) + return false; + + LayoutBitField(D, FieldOffset); + return true; + } + + assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!"); + uint64_t FieldOffsetInBytes = FieldOffset / 8; + + const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType()); + unsigned TypeAlignment = getTypeAlignment(Ty); + + // If the type alignment is larger then the struct alignment, we must use + // a packed struct. + if (TypeAlignment > Alignment) { + assert(!Packed && "Alignment is wrong even with packed struct!"); + return false; + } + + if (const RecordType *RT = D->getType()->getAs<RecordType>()) { + const RecordDecl *RD = cast<RecordDecl>(RT->getDecl()); + if (const PragmaPackAttr *PPA = RD->getAttr<PragmaPackAttr>()) { + if (PPA->getAlignment() != TypeAlignment * 8 && !Packed) + return false; + } + } + + // Round up the field offset to the alignment of the field type. + uint64_t AlignedNextFieldOffsetInBytes = + llvm::RoundUpToAlignment(NextFieldOffsetInBytes, TypeAlignment); + + if (FieldOffsetInBytes < AlignedNextFieldOffsetInBytes) { + assert(!Packed && "Could not place field even with packed struct!"); + return false; + } + + if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) { + // Even with alignment, the field offset is not at the right place, + // insert padding. + uint64_t PaddingInBytes = FieldOffsetInBytes - NextFieldOffsetInBytes; + + AppendBytes(PaddingInBytes); + } + + // Now append the field. + LLVMFields.push_back(LLVMFieldInfo(D, FieldTypes.size())); + AppendField(FieldOffsetInBytes, Ty); + + return true; +} + +void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) { + assert(D->isUnion() && "Can't call LayoutUnion on a non-union record!"); + + const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D); + + const llvm::Type *Ty = 0; + uint64_t Size = 0; + unsigned Align = 0; + + unsigned FieldNo = 0; + for (RecordDecl::field_iterator Field = D->field_begin(), + FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { + assert(Layout.getFieldOffset(FieldNo) == 0 && + "Union field offset did not start at the beginning of record!"); + + if (Field->isBitField()) { + uint64_t FieldSize = + Field->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue(); + + // Ignore zero sized bit fields. + if (FieldSize == 0) + continue; + + // Add the bit field info. + Types.addBitFieldInfo(*Field, 0, 0, FieldSize); + } else + Types.addFieldInfo(*Field, 0); + + const llvm::Type *FieldTy = + Types.ConvertTypeForMemRecursive(Field->getType()); + unsigned FieldAlign = Types.getTargetData().getABITypeAlignment(FieldTy); + uint64_t FieldSize = Types.getTargetData().getTypeAllocSize(FieldTy); + + if (FieldAlign < Align) + continue; + + if (FieldAlign > Align || FieldSize > Size) { + Ty = FieldTy; + Align = FieldAlign; + Size = FieldSize; + } + } + + // Now add our field. + if (Ty) { + AppendField(0, Ty); + + if (getTypeAlignment(Ty) > Layout.getAlignment() / 8) { + // We need a packed struct. + Packed = true; + Align = 1; + } + } + + // Append tail padding. + if (Layout.getSize() / 8 > Size) + AppendPadding(Layout.getSize() / 8, Align); +} + +bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { + assert(!D->isUnion() && "Can't call LayoutFields on a union!"); + assert(Alignment && "Did not set alignment!"); + + const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(D); + + unsigned FieldNo = 0; + + for (RecordDecl::field_iterator Field = D->field_begin(), + FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { + if (!LayoutField(*Field, Layout.getFieldOffset(FieldNo))) { + assert(!Packed && + "Could not layout fields even with a packed LLVM struct!"); + return false; + } + } + + // Append tail padding if necessary. + AppendTailPadding(Layout.getSize()); + + return true; +} + +void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) { + assert(RecordSize % 8 == 0 && "Invalid record size!"); + + uint64_t RecordSizeInBytes = RecordSize / 8; + assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!"); + + unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes; + AppendBytes(NumPadBytes); +} + +void CGRecordLayoutBuilder::AppendField(uint64_t FieldOffsetInBytes, + const llvm::Type *FieldTy) { + AlignmentAsLLVMStruct = std::max(AlignmentAsLLVMStruct, + getTypeAlignment(FieldTy)); + + uint64_t FieldSizeInBytes = getTypeSizeInBytes(FieldTy); + + FieldTypes.push_back(FieldTy); + + NextFieldOffsetInBytes = FieldOffsetInBytes + FieldSizeInBytes; + BitsAvailableInLastField = 0; +} + +void +CGRecordLayoutBuilder::AppendPadding(uint64_t FieldOffsetInBytes, + const llvm::Type *FieldTy) { + AppendPadding(FieldOffsetInBytes, getTypeAlignment(FieldTy)); +} + +void CGRecordLayoutBuilder::AppendPadding(uint64_t FieldOffsetInBytes, + unsigned FieldAlignment) { + assert(NextFieldOffsetInBytes <= FieldOffsetInBytes && + "Incorrect field layout!"); + + // Round up the field offset to the alignment of the field type. + uint64_t AlignedNextFieldOffsetInBytes = + llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment); + + if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) { + // Even with alignment, the field offset is not at the right place, + // insert padding. + uint64_t PaddingInBytes = FieldOffsetInBytes - NextFieldOffsetInBytes; + + AppendBytes(PaddingInBytes); + } +} + +void CGRecordLayoutBuilder::AppendBytes(uint64_t NumBytes) { + if (NumBytes == 0) + return; + + const llvm::Type *Ty = llvm::Type::getInt8Ty(Types.getLLVMContext()); + if (NumBytes > 1) + Ty = llvm::ArrayType::get(Ty, NumBytes); + + // Append the padding field + AppendField(NextFieldOffsetInBytes, Ty); +} + +unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const { + if (Packed) + return 1; + + return Types.getTargetData().getABITypeAlignment(Ty); +} + +uint64_t CGRecordLayoutBuilder::getTypeSizeInBytes(const llvm::Type *Ty) const { + return Types.getTargetData().getTypeAllocSize(Ty); +} + +void CGRecordLayoutBuilder::CheckForMemberPointer(const FieldDecl *FD) { + // This record already contains a member pointer. + if (ContainsMemberPointer) + return; + + // Can only have member pointers if we're compiling C++. + if (!Types.getContext().getLangOptions().CPlusPlus) + return; + + QualType Ty = FD->getType(); + + if (Ty->isMemberPointerType()) { + // We have a member pointer! + ContainsMemberPointer = true; + return; + } + +} + +static const CXXMethodDecl *GetKeyFunction(const RecordDecl *D) { + const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D); + if (!RD || !RD->isDynamicClass()) + return 0; + + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + const CXXMethodDecl *MD = *I; + + if (!MD->isVirtual()) + continue; + + if (MD->isPure()) + continue; + + if (MD->getBody()) + continue; + + // We found it. + return MD; + } + + return 0; +} + +CGRecordLayout * +CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types, + const RecordDecl *D) { + CGRecordLayoutBuilder Builder(Types); + + Builder.Layout(D); + + const llvm::Type *Ty = llvm::StructType::get(Types.getLLVMContext(), + Builder.FieldTypes, + Builder.Packed); + assert(Types.getContext().getASTRecordLayout(D).getSize() / 8 == + Types.getTargetData().getTypeAllocSize(Ty) && + "Type size mismatch!"); + + // Add all the field numbers. + for (unsigned i = 0, e = Builder.LLVMFields.size(); i != e; ++i) { + const FieldDecl *FD = Builder.LLVMFields[i].first; + unsigned FieldNo = Builder.LLVMFields[i].second; + + Types.addFieldInfo(FD, FieldNo); + } + + // Add bitfield info. + for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i) { + const LLVMBitFieldInfo &Info = Builder.LLVMBitFields[i]; + + Types.addBitFieldInfo(Info.FD, Info.FieldNo, Info.Start, Info.Size); + } + + const CXXMethodDecl *KeyFunction = GetKeyFunction(D); + + return new CGRecordLayout(Ty, Builder.ContainsMemberPointer, KeyFunction); +} diff --git a/lib/CodeGen/CGRecordLayoutBuilder.h b/lib/CodeGen/CGRecordLayoutBuilder.h new file mode 100644 index 0000000000000..d1a13aa29711e --- /dev/null +++ b/lib/CodeGen/CGRecordLayoutBuilder.h @@ -0,0 +1,134 @@ +//===--- CGRecordLayoutBuilder.h - Record builder helper --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is a helper class used to build CGRecordLayout objects and LLVM types. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H +#define CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include <vector> + +namespace llvm { + class Type; +} + +namespace clang { + class FieldDecl; + class RecordDecl; + +namespace CodeGen { + class CGRecordLayout; + class CodeGenTypes; + +class CGRecordLayoutBuilder { + CodeGenTypes &Types; + + /// Packed - Whether the resulting LLVM struct will be packed or not. + bool Packed; + + /// ContainsMemberPointer - Whether one of the fields is a member pointer + /// or is a struct that contains a member pointer. + bool ContainsMemberPointer; + + /// Alignment - Contains the alignment of the RecordDecl. + unsigned Alignment; + + /// AlignmentAsLLVMStruct - Will contain the maximum alignment of all the + /// LLVM types. + unsigned AlignmentAsLLVMStruct; + + /// BitsAvailableInLastField - If a bit field spans only part of a LLVM field, + /// this will have the number of bits still available in the field. + char BitsAvailableInLastField; + + /// NextFieldOffsetInBytes - Holds the next field offset in bytes. + uint64_t NextFieldOffsetInBytes; + + /// FieldTypes - Holds the LLVM types that the struct is created from. + std::vector<const llvm::Type *> FieldTypes; + + /// LLVMFieldInfo - Holds a field and its corresponding LLVM field number. + typedef std::pair<const FieldDecl *, unsigned> LLVMFieldInfo; + llvm::SmallVector<LLVMFieldInfo, 16> LLVMFields; + + /// LLVMBitFieldInfo - Holds location and size information about a bit field. + struct LLVMBitFieldInfo { + LLVMBitFieldInfo(const FieldDecl *FD, unsigned FieldNo, unsigned Start, + unsigned Size) + : FD(FD), FieldNo(FieldNo), Start(Start), Size(Size) { } + + const FieldDecl *FD; + + unsigned FieldNo; + unsigned Start; + unsigned Size; + }; + llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields; + + CGRecordLayoutBuilder(CodeGenTypes &Types) + : Types(Types), Packed(false), ContainsMemberPointer(false) + , Alignment(0), AlignmentAsLLVMStruct(1) + , BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { } + + /// Layout - Will layout a RecordDecl. + void Layout(const RecordDecl *D); + + /// LayoutUnion - Will layout a union RecordDecl. + void LayoutUnion(const RecordDecl *D); + + /// LayoutField - try to layout all fields in the record decl. + /// Returns false if the operation failed because the struct is not packed. + bool LayoutFields(const RecordDecl *D); + + /// LayoutField - layout a single field. Returns false if the operation failed + /// because the current struct is not packed. + bool LayoutField(const FieldDecl *D, uint64_t FieldOffset); + + /// LayoutBitField - layout a single bit field. + void LayoutBitField(const FieldDecl *D, uint64_t FieldOffset); + + /// AppendField - Appends a field with the given offset and type. + void AppendField(uint64_t FieldOffsetInBytes, const llvm::Type *FieldTy); + + /// AppendPadding - Appends enough padding bytes so that the total struct + /// size matches the alignment of the passed in type. + void AppendPadding(uint64_t FieldOffsetInBytes, const llvm::Type *FieldTy); + + /// AppendPadding - Appends enough padding bytes so that the total + /// struct size is a multiple of the field alignment. + void AppendPadding(uint64_t FieldOffsetInBytes, unsigned FieldAlignment); + + /// AppendBytes - Append a given number of bytes to the record. + void AppendBytes(uint64_t NumBytes); + + /// AppendTailPadding - Append enough tail padding so that the type will have + /// the passed size. + void AppendTailPadding(uint64_t RecordSize); + + unsigned getTypeAlignment(const llvm::Type *Ty) const; + uint64_t getTypeSizeInBytes(const llvm::Type *Ty) const; + + /// CheckForMemberPointer - Check if the field contains a member pointer. + void CheckForMemberPointer(const FieldDecl *FD); + +public: + /// ComputeLayout - Return the right record layout for a given record decl. + static CGRecordLayout *ComputeLayout(CodeGenTypes &Types, + const RecordDecl *D); +}; + +} // end namespace CodeGen +} // end namespace clang + + +#endif diff --git a/lib/CodeGen/CGRtti.cpp b/lib/CodeGen/CGRtti.cpp new file mode 100644 index 0000000000000..7bc774fce75bc --- /dev/null +++ b/lib/CodeGen/CGRtti.cpp @@ -0,0 +1,47 @@ +//===--- CGCXXRtti.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===// +// +// 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 of RTTI descriptors. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenModule.h" +using namespace clang; +using namespace CodeGen; + +llvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) { + llvm::Type *Ptr8Ty; + Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); + llvm::Constant *Rtti = llvm::Constant::getNullValue(Ptr8Ty); + + if (!getContext().getLangOptions().Rtti) + return Rtti; + + llvm::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + mangleCXXRtti(getMangleContext(), RD, Out); + + llvm::GlobalVariable::LinkageTypes linktype; + linktype = llvm::GlobalValue::WeakAnyLinkage; + std::vector<llvm::Constant *> info; + // assert(0 && "FIXME: implement rtti descriptor"); + // FIXME: descriptor + info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); + // assert(0 && "FIXME: implement rtti ts"); + // FIXME: TS + info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); + + llvm::Constant *C; + llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, info.size()); + C = llvm::ConstantArray::get(type, info); + Rtti = new llvm::GlobalVariable(getModule(), type, true, linktype, C, + Out.str()); + Rtti = llvm::ConstantExpr::getBitCast(Rtti, Ptr8Ty); + return Rtti; +} diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index b67996c676307..f58b579267873 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -43,13 +43,24 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { if (EmitSimpleStmt(S)) return; - // If we happen to be at an unreachable point just create a dummy - // basic block to hold the code. We could change parts of irgen to - // simply not generate this code, but this situation is rare and - // probably not worth the effort. - // FIXME: Verify previous performance/effort claim. - EnsureInsertPoint(); - + // Check if we are generating unreachable code. + if (!HaveInsertPoint()) { + // If so, and the statement doesn't contain a label, then we do not need to + // generate actual code. This is safe because (1) the current point is + // unreachable, so we don't need to execute the code, and (2) we've already + // handled the statements which update internal data structures (like the + // local variable map) which could be used by subsequent statements. + if (!ContainsLabel(S)) { + // Verify that any decl statements were handled as simple, they may be in + // scope of subsequent reachable statements. + assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!"); + return; + } + + // Otherwise, make a new block to hold the code. + EnsureInsertPoint(); + } + // Generate a stoppoint if we are emitting debug info. EmitStopPoint(S); @@ -57,29 +68,37 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { default: // Must be an expression in a stmt context. Emit the value (to get // side-effects) and ignore the result. - if (const Expr *E = dyn_cast<Expr>(S)) { - EmitAnyExpr(E, 0, false, true); - } else { + if (!isa<Expr>(S)) ErrorUnsupported(S, "statement"); + + EmitAnyExpr(cast<Expr>(S), 0, false, true); + + // Expression emitters don't handle unreachable blocks yet, so look for one + // explicitly here. This handles the common case of a call to a noreturn + // function. + if (llvm::BasicBlock *CurBB = Builder.GetInsertBlock()) { + if (CurBB->empty() && CurBB->use_empty()) { + CurBB->eraseFromParent(); + Builder.ClearInsertionPoint(); + } } break; - case Stmt::IndirectGotoStmtClass: + case Stmt::IndirectGotoStmtClass: EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break; case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break; case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break; case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S)); break; case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break; - + case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break; - case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break; case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break; case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break; case Stmt::ObjCAtTryStmtClass: EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S)); - break; + break; case Stmt::ObjCAtCatchStmtClass: assert(0 && "@catch statements should be handled by EmitObjCAtTryStmt"); break; @@ -92,9 +111,13 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::ObjCAtSynchronizedStmtClass: EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S)); break; - case Stmt::ObjCForCollectionStmtClass: + case Stmt::ObjCForCollectionStmtClass: EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S)); break; + + case Stmt::CXXTryStmtClass: + EmitCXXTryStmt(cast<CXXTryStmt>(*S)); + break; } } @@ -103,6 +126,7 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) { default: return false; case Stmt::NullStmtClass: break; case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break; + case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break; case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break; case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break; case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break; @@ -121,41 +145,42 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, llvm::Value *AggLoc, bool isAggVol) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(), "LLVM IR generation of compound statement ('{}')"); - + CGDebugInfo *DI = getDebugInfo(); if (DI) { +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + DI->setLocation(S.getLBracLoc()); + DI->EmitRegionStart(CurFn, Builder); +#else EnsureInsertPoint(); DI->setLocation(S.getLBracLoc()); - // FIXME: The llvm backend is currently not ready to deal with region_end - // for block scoping. In the presence of always_inline functions it gets so - // confused that it doesn't emit any debug info. Just disable this for now. - //DI->EmitRegionStart(CurFn, Builder); +#endif } // Keep track of the current cleanup stack depth. size_t CleanupStackDepth = CleanupEntries.size(); bool OldDidCallStackSave = DidCallStackSave; DidCallStackSave = false; - + for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end()-GetLast; I != E; ++I) EmitStmt(*I); if (DI) { +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + DI->setLocation(S.getLBracLoc()); + DI->EmitRegionEnd(CurFn, Builder); +#else EnsureInsertPoint(); - DI->setLocation(S.getRBracLoc()); - - // FIXME: The llvm backend is currently not ready to deal with region_end - // for block scoping. In the presence of always_inline functions it gets so - // confused that it doesn't emit any debug info. Just disable this for now. - //DI->EmitRegionEnd(CurFn, Builder); + DI->setLocation(S.getLBracLoc()); +#endif } RValue RV; - if (!GetLast) + if (!GetLast) RV = RValue::get(0); else { - // We have to special case labels here. They are statements, but when put + // We have to special case labels here. They are statements, but when put // at the end of a statement expression, they yield the value of their // subexpression. Handle this by walking through all labels we encounter, // emitting them before we evaluate the subexpr. @@ -164,22 +189,22 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, EmitLabel(*LS); LastStmt = LS->getSubStmt(); } - + EnsureInsertPoint(); - + RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); } DidCallStackSave = OldDidCallStackSave; - + EmitCleanupBlocks(CleanupStackDepth); - + return RV; } void CodeGenFunction::SimplifyForwardingBlocks(llvm::BasicBlock *BB) { llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(BB->getTerminator()); - + // If there is a cleanup stack, then we it isn't worth trying to // simplify this block (we would need to remove it from the scope map // and cleanup entry). @@ -215,7 +240,7 @@ void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) { CleanupEntries.back().Blocks.push_back(BB); } } - + CurFn->getBasicBlockList().push_back(BB); Builder.SetInsertPoint(BB); } @@ -257,24 +282,31 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) { EmitBranchThroughCleanup(getBasicBlockForLabel(S.getLabel())); } + void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { // Emit initial switch which will be patched up later by // EmitIndirectSwitches(). We need a default dest, so we use the // current BB, but this is overwritten. llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()), - llvm::Type::Int32Ty, + llvm::Type::getInt32Ty(VMContext), "addr"); - llvm::SwitchInst *I = Builder.CreateSwitch(V, Builder.GetInsertBlock()); - IndirectSwitches.push_back(I); + llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); + - // Clear the insertion point to indicate we are in unreachable code. - Builder.ClearInsertionPoint(); + // Get the basic block for the indirect goto. + llvm::BasicBlock *IndGotoBB = GetIndirectGotoBlock(); + + // The first instruction in the block has to be the PHI for the switch dest, + // add an entry for this branch. + cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB); + + EmitBranch(IndGotoBB); } void CodeGenFunction::EmitIfStmt(const IfStmt &S) { // C99 6.8.4.1: The first substatement is executed if the expression compares // unequal to 0. The condition must be a scalar type. - + // If the condition constant folds and can be elided, try to avoid emitting // the condition and the dead arm of the if/else. if (int Cond = ConstantFoldsToSimpleInteger(S.getCond())) { @@ -282,7 +314,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { const Stmt *Executed = S.getThen(), *Skipped = S.getElse(); if (Cond == -1) // Condition false? std::swap(Executed, Skipped); - + // If the skipped block has no labels in it, just emit the executed block. // This avoids emitting dead code and simplifies the CFG substantially. if (!ContainsLabel(Skipped)) { @@ -300,19 +332,19 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { if (S.getElse()) ElseBlock = createBasicBlock("if.else"); EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock); - + // Emit the 'then' code. EmitBlock(ThenBlock); EmitStmt(S.getThen()); EmitBranch(ContBlock); - + // Emit the 'else' code if present. if (const Stmt *Else = S.getElse()) { EmitBlock(ElseBlock); EmitStmt(Else); EmitBranch(ContBlock); } - + // Emit the continuation block for code after the if. EmitBlock(ContBlock, true); } @@ -330,7 +362,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { // Store the blocks to use for break and continue. BreakContinueStack.push_back(BreakContinue(ExitBlock, LoopHeader)); - + // Evaluate the conditional in the while header. C99 6.8.5.1: The // evaluation of the controlling expression takes place before each // execution of the loop body. @@ -339,23 +371,23 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) { // while(1) is common, avoid extra exit blocks. Be sure // to correctly handle break/continue though. bool EmitBoolCondBranch = true; - if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) + if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) if (C->isOne()) EmitBoolCondBranch = false; - + // As long as the condition is true, go to the loop body. if (EmitBoolCondBranch) Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); - + // Emit the loop body. EmitBlock(LoopBody); EmitStmt(S.getBody()); - BreakContinueStack.pop_back(); - + BreakContinueStack.pop_back(); + // Cycle to the condition. EmitBranch(LoopHeader); - + // Emit the exit block. EmitBlock(ExitBlock, true); @@ -373,20 +405,20 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) { EmitBlock(LoopBody); llvm::BasicBlock *DoCond = createBasicBlock("do.cond"); - + // Store the blocks to use for break and continue. BreakContinueStack.push_back(BreakContinue(AfterDo, DoCond)); - + // Emit the body of the loop into the block. EmitStmt(S.getBody()); - + BreakContinueStack.pop_back(); - + EmitBlock(DoCond); - + // C99 6.8.5.2: "The evaluation of the controlling expression takes place // after each execution of the loop body." - + // Evaluate the conditional in the while header. // C99 6.8.5p2/p4: The first substatement is executed if the expression // compares unequal to 0. The condition must be a scalar type. @@ -395,14 +427,14 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) { // "do {} while (0)" is common in macros, avoid extra blocks. Be sure // to correctly handle break/continue though. bool EmitBoolCondBranch = true; - if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) + if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) if (C->isZero()) EmitBoolCondBranch = false; // As long as the condition is true, iterate the loop. if (EmitBoolCondBranch) Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo); - + // Emit the exit block. EmitBlock(AfterDo); @@ -431,41 +463,54 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) { if (S.getCond()) { // As long as the condition is true, iterate the loop. llvm::BasicBlock *ForBody = createBasicBlock("for.body"); - + // C99 6.8.5p2/p4: The first substatement is executed if the expression // compares unequal to 0. The condition must be a scalar type. EmitBranchOnBoolExpr(S.getCond(), ForBody, AfterFor); - - EmitBlock(ForBody); + + EmitBlock(ForBody); } else { // Treat it as a non-zero constant. Don't even create a new block for the // body, just fall into it. } - // If the for loop doesn't have an increment we can just use the + // If the for loop doesn't have an increment we can just use the // condition as the continue block. llvm::BasicBlock *ContinueBlock; if (S.getInc()) ContinueBlock = createBasicBlock("for.inc"); else - ContinueBlock = CondBlock; - + ContinueBlock = CondBlock; + // Store the blocks to use for break and continue. BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock)); // If the condition is true, execute the body of the for stmt. +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + CGDebugInfo *DI = getDebugInfo(); + if (DI) { + DI->setLocation(S.getSourceRange().getBegin()); + DI->EmitRegionStart(CurFn, Builder); + } +#endif EmitStmt(S.getBody()); BreakContinueStack.pop_back(); - + // If there is an increment, emit it next. if (S.getInc()) { EmitBlock(ContinueBlock); EmitStmt(S.getInc()); } - + // Finally, branch back up to the condition for the next iteration. EmitBranch(CondBlock); +#ifdef ATTACH_DEBUG_INFO_TO_AN_INSN + if (DI) { + DI->setLocation(S.getSourceRange().getEnd()); + DI->EmitRegionEnd(CurFn, Builder); + } +#endif // Emit the fall-through block. EmitBlock(AfterFor, true); @@ -488,7 +533,7 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) { void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { // Emit the result value, even if unused, to evalute the side effects. const Expr *RV = S.getRetValue(); - + // FIXME: Clean this up by using an LValue for ReturnTemp, // EmitStoreThroughLValue, and EmitAnyExpr. if (!ReturnValue) { @@ -514,6 +559,13 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { } void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) { + // As long as debug info is modeled with instructions, we have to ensure we + // have a place to insert here and write the stop point here. + if (getDebugInfo()) { + EnsureInsertPoint(); + EmitStopPoint(&S); + } + for (DeclStmt::const_decl_iterator I = S.decl_begin(), E = S.decl_end(); I != E; ++I) EmitDecl(**I); @@ -570,12 +622,12 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) { // Range is small enough to add multiple switch instruction cases. for (unsigned i = 0, e = Range.getZExtValue() + 1; i != e; ++i) { - SwitchInsn->addCase(llvm::ConstantInt::get(LHS), CaseDest); + SwitchInsn->addCase(llvm::ConstantInt::get(VMContext, LHS), CaseDest); LHS++; } return; - } - + } + // The range is too big. Emit "if" condition into a new block, // making sure to save and restore the current insertion point. llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock(); @@ -590,11 +642,12 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) { Builder.SetInsertPoint(CaseRangeBlock); // Emit range check. - llvm::Value *Diff = - Builder.CreateSub(SwitchInsn->getCondition(), llvm::ConstantInt::get(LHS), - "tmp"); - llvm::Value *Cond = - Builder.CreateICmpULE(Diff, llvm::ConstantInt::get(Range), "tmp"); + llvm::Value *Diff = + Builder.CreateSub(SwitchInsn->getCondition(), + llvm::ConstantInt::get(VMContext, LHS), "tmp"); + llvm::Value *Cond = + Builder.CreateICmpULE(Diff, + llvm::ConstantInt::get(VMContext, Range), "tmp"); Builder.CreateCondBr(Cond, CaseDest, FalseDest); // Restore the appropriate insertion point. @@ -609,12 +662,12 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { EmitCaseStmtRange(S); return; } - + EmitBlock(createBasicBlock("sw.bb")); llvm::BasicBlock *CaseDest = Builder.GetInsertBlock(); llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext()); - SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal), CaseDest); - + SwitchInsn->addCase(llvm::ConstantInt::get(VMContext, CaseVal), CaseDest); + // Recursively emitting the statement is acceptable, but is not wonderful for // code where we have many case statements nested together, i.e.: // case 1: @@ -631,18 +684,18 @@ void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) { while (NextCase && NextCase->getRHS() == 0) { CurCase = NextCase; CaseVal = CurCase->getLHS()->EvaluateAsInt(getContext()); - SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal), CaseDest); + SwitchInsn->addCase(llvm::ConstantInt::get(VMContext, CaseVal), CaseDest); NextCase = dyn_cast<CaseStmt>(CurCase->getSubStmt()); } - + // Normal default recursion for non-cases. EmitStmt(CurCase->getSubStmt()); } void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) { llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest(); - assert(DefaultBlock->empty() && + assert(DefaultBlock->empty() && "EmitDefaultStmt: Default block already defined?"); EmitBlock(DefaultBlock); EmitStmt(S.getSubStmt()); @@ -678,13 +731,13 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { // Emit switch body. EmitStmt(S.getBody()); - + BreakContinueStack.pop_back(); // Update the default block in case explicit case range tests have // been chained on top. SwitchInsn->setSuccessor(0, CaseRangeBlock); - + // If a default was never emitted then reroute any jumps to it and // discard. if (!DefaultBlock->getParent()) { @@ -703,7 +756,7 @@ static std::string SimplifyConstraint(const char *Constraint, TargetInfo &Target, llvm::SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=0) { std::string Result; - + while (*Constraint) { switch (*Constraint) { default: @@ -721,7 +774,7 @@ SimplifyConstraint(const char *Constraint, TargetInfo &Target, assert(OutCons && "Must pass output names to constraints with a symbolic name"); unsigned Index; - bool result = Target.resolveSymbolicName(Constraint, + bool result = Target.resolveSymbolicName(Constraint, &(*OutCons)[0], OutCons->size(), Index); assert(result && "Could not resolve symbolic name"); result=result; @@ -729,10 +782,10 @@ SimplifyConstraint(const char *Constraint, TargetInfo &Target, break; } } - + Constraint++; } - + return Result; } @@ -741,9 +794,9 @@ llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S, const Expr *InputExpr, std::string &ConstraintStr) { llvm::Value *Arg; - if (Info.allowsRegister() || !Info.allowsMemory()) { + if (Info.allowsRegister() || !Info.allowsMemory()) { const llvm::Type *Ty = ConvertType(InputExpr->getType()); - + if (Ty->isSingleValueType()) { Arg = EmitScalarExpr(InputExpr); } else { @@ -752,9 +805,9 @@ llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S, uint64_t Size = CGM.getTargetData().getTypeSizeInBits(Ty); if (Size <= 64 && llvm::isPowerOf2_64(Size)) { - Ty = llvm::IntegerType::get(Size); + Ty = llvm::IntegerType::get(VMContext, Size); Ty = llvm::PointerType::getUnqual(Ty); - + Arg = Builder.CreateLoad(Builder.CreateBitCast(Dest.getAddress(), Ty)); } else { Arg = Dest.getAddress(); @@ -767,7 +820,7 @@ llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S, Arg = Dest.getAddress(); ConstraintStr += '*'; } - + return Arg; } @@ -777,7 +830,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { llvm::SmallVector<AsmStmt::AsmStringPiece, 4> Pieces; unsigned DiagOffs; S.AnalyzeAsmString(Pieces, getContext(), DiagOffs); - + // Assemble the pieces into the final asm string. std::string AsmString; for (unsigned i = 0, e = Pieces.size(); i != e; ++i) { @@ -789,19 +842,19 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { AsmString += "${" + llvm::utostr(Pieces[i].getOperandNo()) + ':' + Pieces[i].getModifier() + '}'; } - + // Get all the output and input constraints together. llvm::SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; llvm::SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; - for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { + for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), S.getOutputName(i)); bool result = Target.validateOutputConstraint(Info); assert(result && "Failed to parse output constraint"); result=result; OutputConstraintInfos.push_back(Info); - } - + } + for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), S.getInputName(i)); @@ -811,9 +864,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { assert(result && "Failed to parse input constraint"); InputConstraintInfos.push_back(Info); } - + std::string Constraints; - + std::vector<LValue> ResultRegDests; std::vector<QualType> ResultRegQualTys; std::vector<const llvm::Type *> ResultRegTypes; @@ -826,16 +879,16 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { std::vector<llvm::Value*> InOutArgs; std::vector<const llvm::Type*> InOutArgTypes; - for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { + for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; // Simplify the output constraint. std::string OutputConstraint(S.getOutputConstraint(i)); OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target); - + const Expr *OutExpr = S.getOutputExpr(i); OutExpr = OutExpr->IgnoreParenNoopCasts(getContext()); - + LValue Dest = EmitLValue(OutExpr); if (!Constraints.empty()) Constraints += ','; @@ -848,7 +901,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { ResultRegDests.push_back(Dest); ResultRegTypes.push_back(ConvertTypeForMem(OutExpr->getType())); ResultTruncRegTypes.push_back(ResultRegTypes.back()); - + // If this output is tied to an input, and if the input is larger, then // we need to set the actual result type of the inline asm node to be the // same as the input type. @@ -861,30 +914,29 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { break; } assert(InputNo != S.getNumInputs() && "Didn't find matching input!"); - + QualType InputTy = S.getInputExpr(InputNo)->getType(); QualType OutputTy = OutExpr->getType(); - + uint64_t InputSize = getContext().getTypeSize(InputTy); if (getContext().getTypeSize(OutputTy) < InputSize) { // Form the asm to return the value as a larger integer type. - ResultRegTypes.back() = llvm::IntegerType::get((unsigned)InputSize); + ResultRegTypes.back() = llvm::IntegerType::get(VMContext, (unsigned)InputSize); } } - } else { ArgTypes.push_back(Dest.getAddress()->getType()); Args.push_back(Dest.getAddress()); Constraints += "=*"; Constraints += OutputConstraint; } - + if (Info.isReadWrite()) { InOutConstraints += ','; const Expr *InputExpr = S.getOutputExpr(i); llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, InOutConstraints); - + if (Info.allowsRegister()) InOutConstraints += llvm::utostr(i); else @@ -894,9 +946,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { InOutArgs.push_back(Arg); } } - + unsigned NumConstraints = S.getNumOutputs() + S.getNumInputs(); - + for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { const Expr *InputExpr = S.getInputExpr(i); @@ -904,14 +956,14 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { if (!Constraints.empty()) Constraints += ','; - + // Simplify the input constraint. std::string InputConstraint(S.getInputConstraint(i)); InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target, &OutputConstraintInfos); llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, Constraints); - + // If this input argument is tied to a larger output result, extend the // input to be the same size as the output. The LLVM backend wants to see // the input and output of a matching constraint be the same size. Note @@ -921,46 +973,46 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { unsigned Output = Info.getTiedOperand(); QualType OutputTy = S.getOutputExpr(Output)->getType(); QualType InputTy = InputExpr->getType(); - + if (getContext().getTypeSize(OutputTy) > getContext().getTypeSize(InputTy)) { // Use ptrtoint as appropriate so that we can do our extension. if (isa<llvm::PointerType>(Arg->getType())) Arg = Builder.CreatePtrToInt(Arg, - llvm::IntegerType::get(LLVMPointerWidth)); + llvm::IntegerType::get(VMContext, LLVMPointerWidth)); unsigned OutputSize = (unsigned)getContext().getTypeSize(OutputTy); - Arg = Builder.CreateZExt(Arg, llvm::IntegerType::get(OutputSize)); + Arg = Builder.CreateZExt(Arg, llvm::IntegerType::get(VMContext, OutputSize)); } } - - + + ArgTypes.push_back(Arg->getType()); Args.push_back(Arg); Constraints += InputConstraint; } - + // Append the "input" part of inout constraints last. for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) { ArgTypes.push_back(InOutArgTypes[i]); Args.push_back(InOutArgs[i]); } Constraints += InOutConstraints; - + // Clobbers for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { std::string Clobber(S.getClobber(i)->getStrData(), S.getClobber(i)->getByteLength()); Clobber = Target.getNormalizedGCCRegisterName(Clobber.c_str()); - + if (i != 0 || NumConstraints != 0) Constraints += ','; - + Constraints += "~{"; Constraints += Clobber; Constraints += '}'; } - + // Add machine specific clobbers std::string MachineClobbers = Target.getClobbers(); if (!MachineClobbers.empty()) { @@ -971,22 +1023,22 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { const llvm::Type *ResultType; if (ResultRegTypes.empty()) - ResultType = llvm::Type::VoidTy; + ResultType = llvm::Type::getVoidTy(VMContext); else if (ResultRegTypes.size() == 1) ResultType = ResultRegTypes[0]; else - ResultType = llvm::StructType::get(ResultRegTypes); - - const llvm::FunctionType *FTy = + ResultType = llvm::StructType::get(VMContext, ResultRegTypes); + + const llvm::FunctionType *FTy = llvm::FunctionType::get(ResultType, ArgTypes, false); - - llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, AsmString, Constraints, + + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, AsmString, Constraints, S.isVolatile() || S.getNumOutputs() == 0); llvm::CallInst *Result = Builder.CreateCall(IA, Args.begin(), Args.end()); Result->addAttribute(~0, llvm::Attribute::NoUnwind); - - + + // Extract all of the register value results from the asm. std::vector<llvm::Value*> RegResults; if (ResultRegTypes.size() == 1) { @@ -997,10 +1049,10 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { RegResults.push_back(Tmp); } } - + for (unsigned i = 0, e = RegResults.size(); i != e; ++i) { llvm::Value *Tmp = RegResults[i]; - + // If the result type of the LLVM IR asm doesn't match the result type of // the expression, do the conversion. if (ResultRegTypes[i] != ResultTruncRegTypes[i]) { @@ -1008,14 +1060,14 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { // Truncate the integer result to the right size, note that // ResultTruncRegTypes can be a pointer. uint64_t ResSize = CGM.getTargetData().getTypeSizeInBits(TruncTy); - Tmp = Builder.CreateTrunc(Tmp, llvm::IntegerType::get((unsigned)ResSize)); - + Tmp = Builder.CreateTrunc(Tmp, llvm::IntegerType::get(VMContext, (unsigned)ResSize)); + if (Tmp->getType() != TruncTy) { assert(isa<llvm::PointerType>(TruncTy)); Tmp = Builder.CreateIntToPtr(Tmp, TruncTy); } } - + EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i], ResultRegQualTys[i]); } diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 820e1bd6c3ec5..2a06f51f6685d 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -24,7 +24,7 @@ namespace llvm { namespace clang { class ObjCPropertyRefExpr; - class ObjCKVCRefExpr; + class ObjCImplicitSetterGetterRefExpr; namespace CodeGen { @@ -37,14 +37,14 @@ class RValue { // TODO: Encode this into the low bit of pointer for more efficient // return-by-value. enum { Scalar, Complex, Aggregate } Flavor; - + bool Volatile:1; public: - + bool isScalar() const { return Flavor == Scalar; } bool isComplex() const { return Flavor == Complex; } bool isAggregate() const { return Flavor == Aggregate; } - + bool isVolatileQualified() const { return Volatile; } /// getScalar() - Return the Value* of this scalar value. @@ -58,13 +58,13 @@ public: std::pair<llvm::Value *, llvm::Value *> getComplexVal() const { return std::pair<llvm::Value *, llvm::Value *>(V1, V2); } - + /// getAggregateAddr() - Return the Value* of the address of the aggregate. llvm::Value *getAggregateAddr() const { assert(isAggregate() && "Not an aggregate!"); return V1; } - + static RValue get(llvm::Value *V) { RValue ER; ER.V1 = V; @@ -106,7 +106,7 @@ public: /// bitrange. class LValue { // FIXME: alignment? - + enum { Simple, // This is a normal l-value, use getAddress(). VectorElt, // This is a vector element l-value (V[i]), use getVector* @@ -118,21 +118,15 @@ class LValue { // use getKVCRefExpr } LVType; - enum ObjCType { - None = 0, // object with no gc attribute. - Weak, // __weak object expression - Strong // __strong object expression - }; - llvm::Value *V; - + union { // Index into a vector subscript: V[i] llvm::Value *VectorIdx; // ExtVector element subset: V.xyx llvm::Constant *VectorElts; - + // BitField start bit and size struct { unsigned short StartBit; @@ -143,16 +137,18 @@ class LValue { // Obj-C property reference expression const ObjCPropertyRefExpr *PropertyRefExpr; // ObjC 'implicit' property reference expression - const ObjCKVCRefExpr *KVCRefExpr; + const ObjCImplicitSetterGetterRefExpr *KVCRefExpr; }; - bool Volatile:1; - // FIXME: set but never used, what effect should it have? - bool Restrict:1; + // 'const' is unused here + Qualifiers Quals; // objective-c's ivar bool Ivar:1; + // objective-c's ivar is an array + bool ObjIsArray:1; + // LValue is non-gc'able for any reason, including being a parameter or local // variable. bool NonGC: 1; @@ -160,21 +156,17 @@ class LValue { // Lvalue is a global reference of an objective-c object bool GlobalObjCRef : 1; - // objective-c's gc attributes - unsigned ObjCType : 2; - - - + Expr *BaseIvarExp; private: - static void SetQualifiers(unsigned Qualifiers, LValue& R) { - R.Volatile = (Qualifiers&QualType::Volatile)!=0; - R.Restrict = (Qualifiers&QualType::Restrict)!=0; + void SetQualifiers(Qualifiers Quals) { + this->Quals = Quals; + // FIXME: Convenient place to set objc flags to 0. This should really be // done in a user-defined constructor instead. - R.ObjCType = None; - R.Ivar = R.NonGC = R.GlobalObjCRef = false; + this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false; + this->BaseIvarExp = 0; } - + public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } @@ -183,39 +175,38 @@ public: bool isPropertyRef() const { return LVType == PropertyRef; } bool isKVCRef() const { return LVType == KVCRef; } - bool isVolatileQualified() const { return Volatile; } - bool isRestrictQualified() const { return Restrict; } - unsigned getQualifiers() const { - return (Volatile ? QualType::Volatile : 0) | - (Restrict ? QualType::Restrict : 0); + bool isVolatileQualified() const { return Quals.hasVolatile(); } + bool isRestrictQualified() const { return Quals.hasRestrict(); } + unsigned getVRQualifiers() const { + return Quals.getCVRQualifiers() & ~Qualifiers::Const; } - + bool isObjCIvar() const { return Ivar; } + bool isObjCArray() const { return ObjIsArray; } bool isNonGC () const { return NonGC; } bool isGlobalObjCRef() const { return GlobalObjCRef; } - bool isObjCWeak() const { return ObjCType == Weak; } - bool isObjCStrong() const { return ObjCType == Strong; } + bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; } + bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; } + Expr *getBaseIvarExp() const { return BaseIvarExp; } + void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } + + unsigned getAddressSpace() const { return Quals.getAddressSpace(); } + static void SetObjCIvar(LValue& R, bool iValue) { R.Ivar = iValue; } - + static void SetObjCArray(LValue& R, bool iValue) { + R.ObjIsArray = iValue; + } static void SetGlobalObjCRef(LValue& R, bool iValue) { R.GlobalObjCRef = iValue; } - + static void SetObjCNonGC(LValue& R, bool iValue) { R.NonGC = iValue; } - static void SetObjCType(QualType::GCAttrTypes GCAttrs, LValue& R) { - if (GCAttrs == QualType::Weak) - R.ObjCType = Weak; - else if (GCAttrs == QualType::Strong) - R.ObjCType = Strong; - else - R.ObjCType = None; - } - + // simple lvalue llvm::Value *getAddress() const { assert(isSimple()); return V; } // vector elt lvalue @@ -248,51 +239,49 @@ public: } // 'implicit' property ref lvalue - const ObjCKVCRefExpr *getKVCRefExpr() const { + const ObjCImplicitSetterGetterRefExpr *getKVCRefExpr() const { assert(isKVCRef()); return KVCRefExpr; } - static LValue MakeAddr(llvm::Value *V, unsigned Qualifiers, - QualType::GCAttrTypes GCAttrs = QualType::GCNone) { + static LValue MakeAddr(llvm::Value *V, Qualifiers Quals) { LValue R; R.LVType = Simple; R.V = V; - SetQualifiers(Qualifiers,R); - SetObjCType(GCAttrs, R); + R.SetQualifiers(Quals); return R; } - + static LValue MakeVectorElt(llvm::Value *Vec, llvm::Value *Idx, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = VectorElt; R.V = Vec; R.VectorIdx = Idx; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } - + static LValue MakeExtVectorElt(llvm::Value *Vec, llvm::Constant *Elts, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = ExtVectorElt; R.V = Vec; R.VectorElts = Elts; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } static LValue MakeBitfield(llvm::Value *V, unsigned short StartBit, unsigned short Size, bool IsSigned, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = BitField; R.V = V; R.BitfieldData.StartBit = StartBit; R.BitfieldData.Size = Size; R.BitfieldData.IsSigned = IsSigned; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } @@ -300,19 +289,20 @@ public: // the lvalue. However, this complicates the code a bit, and I haven't figured // out how to make it go wrong yet. static LValue MakePropertyRef(const ObjCPropertyRefExpr *E, - unsigned Qualifiers) { + unsigned CVR) { LValue R; R.LVType = PropertyRef; R.PropertyRefExpr = E; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } - - static LValue MakeKVCRef(const ObjCKVCRefExpr *E, unsigned Qualifiers) { + + static LValue MakeKVCRef(const ObjCImplicitSetterGetterRefExpr *E, + unsigned CVR) { LValue R; R.LVType = KVCRef; R.KVCRefExpr = E; - SetQualifiers(Qualifiers,R); + R.SetQualifiers(Qualifiers::fromCVRMask(CVR)); return R; } }; diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp new file mode 100644 index 0000000000000..41f7eefbe82be --- /dev/null +++ b/lib/CodeGen/CGVtable.cpp @@ -0,0 +1,557 @@ +//===--- CGVtable.cpp - Emit LLVM Code for C++ vtables --------------------===// +// +// 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 of virtual tables. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenModule.h" +#include "CodeGenFunction.h" + +#include "clang/AST/RecordLayout.h" + +using namespace clang; +using namespace CodeGen; + +class VtableBuilder { +public: + /// Index_t - Vtable index type. + typedef uint64_t Index_t; +private: + std::vector<llvm::Constant *> &methods; + std::vector<llvm::Constant *> submethods; + llvm::Type *Ptr8Ty; + /// Class - The most derived class that this vtable is being built for. + const CXXRecordDecl *Class; + /// BLayout - Layout for the most derived class that this vtable is being + /// built for. + const ASTRecordLayout &BLayout; + llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary; + llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase; + llvm::Constant *rtti; + llvm::LLVMContext &VMContext; + CodeGenModule &CGM; // Per-module state. + /// Index - Maps a method decl into a vtable index. Useful for virtual + /// dispatch codegen. + llvm::DenseMap<const CXXMethodDecl *, Index_t> Index; + llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall; + llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset; + llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex; + typedef std::pair<Index_t, Index_t> CallOffset; + typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t; + Thunks_t Thunks; + typedef llvm::DenseMap<const CXXMethodDecl *, + std::pair<std::pair<CallOffset, CallOffset>, + CanQualType> > CovariantThunks_t; + CovariantThunks_t CovariantThunks; + std::vector<Index_t> VCalls; + typedef CXXRecordDecl::method_iterator method_iter; + // FIXME: Linkage should follow vtable + const bool Extern; + const uint32_t LLVMPointerWidth; + Index_t extra; +public: + VtableBuilder(std::vector<llvm::Constant *> &meth, + const CXXRecordDecl *c, + CodeGenModule &cgm) + : methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)), + rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()), + CGM(cgm), Extern(true), + LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { + Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); + } + + llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; } + llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex() + { return VBIndex; } + + llvm::Constant *wrap(Index_t i) { + llvm::Constant *m; + m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i); + return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); + } + + llvm::Constant *wrap(llvm::Constant *m) { + return llvm::ConstantExpr::getBitCast(m, Ptr8Ty); + } + + void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets, + const CXXRecordDecl *RD, uint64_t Offset, + bool updateVBIndex, Index_t current_vbindex) { + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + Index_t next_vbindex = current_vbindex; + if (i->isVirtual() && !SeenVBase.count(Base)) { + SeenVBase.insert(Base); + int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8; + llvm::Constant *m = wrap(BaseOffset); + m = wrap((0?700:0) + BaseOffset); + if (updateVBIndex) { + next_vbindex = (ssize_t)(-(offsets.size()*LLVMPointerWidth/8) + - 3*LLVMPointerWidth/8); + VBIndex[Base] = next_vbindex; + } + offsets.push_back(m); + } + // We also record offsets for non-virtual bases to closest enclosing + // virtual base. We do this so that we don't have to search + // for the nearst virtual base class when generating thunks. + if (updateVBIndex && VBIndex.count(Base) == 0) + VBIndex[Base] = next_vbindex; + GenerateVBaseOffsets(offsets, Base, Offset, updateVBIndex, next_vbindex); + } + } + + void StartNewTable() { + SeenVBase.clear(); + } + + Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B); + + /// getVbaseOffset - Returns the index into the vtable for the virtual base + /// offset for the given (B) virtual base of the derived class D. + Index_t getVbaseOffset(QualType qB, QualType qD) { + qD = qD->getAs<PointerType>()->getPointeeType(); + qB = qB->getAs<PointerType>()->getPointeeType(); + CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl()); + CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl()); + if (D != Class) + return VBlookup(D, B); + llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i; + i = VBIndex.find(B); + if (i != VBIndex.end()) + return i->second; + + assert(false && "FIXME: Base not found"); + return 0; + } + + bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m, + bool MorallyVirtual, Index_t Offset) { + typedef CXXMethodDecl::method_iterator meth_iter; + + // FIXME: Don't like the nested loops. For very large inheritance + // heirarchies we could have a table on the side with the final overridder + // and just replace each instance of an overridden method once. Would be + // nice to measure the cost/benefit on real code. + + for (meth_iter mi = MD->begin_overridden_methods(), + e = MD->end_overridden_methods(); + mi != e; ++mi) { + const CXXMethodDecl *OMD = *mi; + llvm::Constant *om; + om = CGM.GetAddrOfFunction(OMD, Ptr8Ty); + om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty); + + for (Index_t i = 0, e = submethods.size(); + i != e; ++i) { + // FIXME: begin_overridden_methods might be too lax, covariance */ + if (submethods[i] != om) + continue; + QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType(); + CanQualType oret = CGM.getContext().getCanonicalType(nc_oret); + QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType(); + CanQualType ret = CGM.getContext().getCanonicalType(nc_ret); + CallOffset ReturnOffset = std::make_pair(0, 0); + if (oret != ret) { + // FIXME: calculate offsets for covariance + Index_t nv = 0; + if (CovariantThunks.count(OMD)) { + oret = CovariantThunks[OMD].second; + CovariantThunks.erase(OMD); + } + ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret)); + } + Index[MD] = i; + submethods[i] = m; + + Thunks.erase(OMD); + if (MorallyVirtual) { + Index_t &idx = VCall[OMD]; + if (idx == 0) { + VCallOffset[MD] = Offset/8; + idx = VCalls.size()+1; + VCalls.push_back(0); + } else { + VCallOffset[MD] = VCallOffset[OMD]; + VCalls[idx-1] = -VCallOffset[OMD] + Offset/8; + } + VCall[MD] = idx; + CallOffset ThisOffset; + // FIXME: calculate non-virtual offset + ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8)); + if (ReturnOffset.first || ReturnOffset.second) + CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset, + ReturnOffset), + oret); + else + Thunks[MD] = ThisOffset; + return true; + } + + // FIXME: finish off + int64_t O = VCallOffset[OMD] - Offset/8; + if (O || ReturnOffset.first || ReturnOffset.second) { + CallOffset ThisOffset = std::make_pair(O, 0); + + if (ReturnOffset.first || ReturnOffset.second) + CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset, + ReturnOffset), + oret); + else + Thunks[MD] = ThisOffset; + } + return true; + } + } + + return false; + } + + void InstallThunks() { + for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end(); + i != e; ++i) { + const CXXMethodDecl *MD = i->first; + Index_t idx = Index[MD]; + Index_t nv_O = i->second.first; + Index_t v_O = i->second.second; + submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O); + } + Thunks.clear(); + for (CovariantThunks_t::iterator i = CovariantThunks.begin(), + e = CovariantThunks.end(); + i != e; ++i) { + const CXXMethodDecl *MD = i->first; + Index_t idx = Index[MD]; + Index_t nv_t = i->second.first.first.first; + Index_t v_t = i->second.first.first.second; + Index_t nv_r = i->second.first.second.first; + Index_t v_r = i->second.first.second.second; + submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r, + v_r); + } + CovariantThunks.clear(); + } + + void OverrideMethods(std::vector<std::pair<const CXXRecordDecl *, + int64_t> > *Path, bool MorallyVirtual) { + for (std::vector<std::pair<const CXXRecordDecl *, + int64_t> >::reverse_iterator i =Path->rbegin(), + e = Path->rend(); i != e; ++i) { + const CXXRecordDecl *RD = i->first; + int64_t Offset = i->second; + for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; + ++mi) { + if (!mi->isVirtual()) + continue; + + const CXXMethodDecl *MD = *mi; + llvm::Constant *m = 0; + if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) + m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete)); + else { + const FunctionProtoType *FPT = + MD->getType()->getAs<FunctionProtoType>(); + const llvm::Type *Ty = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + + m = wrap(CGM.GetAddrOfFunction(MD, Ty)); + } + + OverrideMethod(MD, m, MorallyVirtual, Offset); + } + } + } + + void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset) { + llvm::Constant *m = 0; + if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) + m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete)); + else { + const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); + const llvm::Type *Ty = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + + m = wrap(CGM.GetAddrOfFunction(MD, Ty)); + } + + // If we can find a previously allocated slot for this, reuse it. + if (OverrideMethod(MD, m, MorallyVirtual, Offset)) + return; + + // else allocate a new slot. + Index[MD] = submethods.size(); + submethods.push_back(m); + if (MorallyVirtual) { + VCallOffset[MD] = Offset/8; + Index_t &idx = VCall[MD]; + // Allocate the first one, after that, we reuse the previous one. + if (idx == 0) { + idx = VCalls.size()+1; + VCalls.push_back(0); + } + } + } + + void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual, + Index_t Offset) { + for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; + ++mi) + if (mi->isVirtual()) + AddMethod(*mi, MorallyVirtual, Offset); + } + + void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout, + const CXXRecordDecl *PrimaryBase, + bool PrimaryBaseWasVirtual, bool MorallyVirtual, + int64_t Offset) { + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + if (i->isVirtual()) + continue; + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + if (Base != PrimaryBase || PrimaryBaseWasVirtual) { + uint64_t o = Offset + Layout.getBaseClassOffset(Base); + StartNewTable(); + std::vector<std::pair<const CXXRecordDecl *, + int64_t> > S; + S.push_back(std::make_pair(RD, Offset)); + GenerateVtableForBase(Base, MorallyVirtual, o, false, &S); + } + } + } + + Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets, + const ASTRecordLayout &Layout, + const CXXRecordDecl *PrimaryBase, + bool PrimaryBaseWasVirtual, bool MorallyVirtual, + int64_t Offset, bool ForVirtualBase) { + StartNewTable(); + extra = 0; + // FIXME: Cleanup. + if (!ForVirtualBase) { + // then virtual base offsets... + for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), + e = offsets.rend(); i != e; ++i) + methods.push_back(*i); + } + + // The vcalls come first... + for (std::vector<Index_t>::reverse_iterator i=VCalls.rbegin(), + e=VCalls.rend(); + i != e; ++i) + methods.push_back(wrap((0?600:0) + *i)); + VCalls.clear(); + + if (ForVirtualBase) { + // then virtual base offsets... + for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), + e = offsets.rend(); i != e; ++i) + methods.push_back(*i); + } + + methods.push_back(wrap(-(Offset/8))); + methods.push_back(rtti); + Index_t AddressPoint = methods.size(); + + InstallThunks(); + methods.insert(methods.end(), submethods.begin(), submethods.end()); + submethods.clear(); + + // and then the non-virtual bases. + NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, + MorallyVirtual, Offset); + return AddressPoint; + } + + void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset) { + if (!RD->isDynamicClass()) + return; + + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); + + // vtables are composed from the chain of primaries. + if (PrimaryBase) { + if (PrimaryBaseWasVirtual) + IndirectPrimary.insert(PrimaryBase); + Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset); + } + + // And add the virtuals for the class to the primary vtable. + AddMethods(RD, MorallyVirtual, Offset); + } + + int64_t GenerateVtableForBase(const CXXRecordDecl *RD, + bool MorallyVirtual = false, int64_t Offset = 0, + bool ForVirtualBase = false, + std::vector<std::pair<const CXXRecordDecl *, + int64_t> > *Path = 0) { + if (!RD->isDynamicClass()) + return 0; + + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); + + std::vector<llvm::Constant *> offsets; + extra = 0; + GenerateVBaseOffsets(offsets, RD, Offset, !ForVirtualBase, 0); + if (ForVirtualBase) + extra = offsets.size(); + + // vtables are composed from the chain of primaries. + if (PrimaryBase) { + if (PrimaryBaseWasVirtual) + IndirectPrimary.insert(PrimaryBase); + Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset); + } + + // And add the virtuals for the class to the primary vtable. + AddMethods(RD, MorallyVirtual, Offset); + + if (Path) + OverrideMethods(Path, MorallyVirtual); + + return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual, + MorallyVirtual, Offset, ForVirtualBase); + } + + void GenerateVtableForVBases(const CXXRecordDecl *RD, + int64_t Offset = 0, + std::vector<std::pair<const CXXRecordDecl *, + int64_t> > *Path = 0) { + bool alloc = false; + if (Path == 0) { + alloc = true; + Path = new std::vector<std::pair<const CXXRecordDecl *, + int64_t> >; + } + // FIXME: We also need to override using all paths to a virtual base, + // right now, we just process the first path + Path->push_back(std::make_pair(RD, Offset)); + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + if (i->isVirtual() && !IndirectPrimary.count(Base)) { + // Mark it so we don't output it twice. + IndirectPrimary.insert(Base); + StartNewTable(); + int64_t BaseOffset = BLayout.getVBaseClassOffset(Base); + GenerateVtableForBase(Base, true, BaseOffset, true, Path); + } + int64_t BaseOffset = Offset; + if (i->isVirtual()) + BaseOffset = BLayout.getVBaseClassOffset(Base); + if (Base->getNumVBases()) + GenerateVtableForVBases(Base, BaseOffset, Path); + } + Path->pop_back(); + if (alloc) + delete Path; + } +}; + + +VtableBuilder::Index_t VtableBuilder::VBlookup(CXXRecordDecl *D, + CXXRecordDecl *B) { + return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B); +} + +int64_t CGVtableInfo::getMethodVtableIndex(const CXXMethodDecl *MD) { + MD = MD->getCanonicalDecl(); + + MethodVtableIndicesTy::iterator I = MethodVtableIndices.find(MD); + if (I != MethodVtableIndices.end()) + return I->second; + + const CXXRecordDecl *RD = MD->getParent(); + + std::vector<llvm::Constant *> methods; + // FIXME: This seems expensive. Can we do a partial job to get + // just this data. + VtableBuilder b(methods, RD, CGM); + b.GenerateVtableForBase(RD); + b.GenerateVtableForVBases(RD); + + MethodVtableIndices.insert(b.getIndex().begin(), + b.getIndex().end()); + + I = MethodVtableIndices.find(MD); + assert(I != MethodVtableIndices.end() && "Did not find index!"); + return I->second; +} + +int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD, + const CXXRecordDecl *VBase) { + ClassPairTy ClassPair(RD, VBase); + + VirtualBaseClassIndiciesTy::iterator I = + VirtualBaseClassIndicies.find(ClassPair); + if (I != VirtualBaseClassIndicies.end()) + return I->second; + + std::vector<llvm::Constant *> methods; + // FIXME: This seems expensive. Can we do a partial job to get + // just this data. + VtableBuilder b(methods, RD, CGM); + b.GenerateVtableForBase(RD); + b.GenerateVtableForVBases(RD); + + for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I = + b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) { + // Insert all types. + ClassPairTy ClassPair(RD, I->first); + + VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second)); + } + + I = VirtualBaseClassIndicies.find(ClassPair); + assert(I != VirtualBaseClassIndicies.end() && "Did not find index!"); + + return I->second; +} + +llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { + llvm::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + mangleCXXVtable(CGM.getMangleContext(), RD, Out); + + llvm::GlobalVariable::LinkageTypes linktype; + linktype = llvm::GlobalValue::WeakAnyLinkage; + std::vector<llvm::Constant *> methods; + llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); + int64_t AddressPoint; + + VtableBuilder b(methods, RD, CGM); + + // First comes the vtables for all the non-virtual bases... + AddressPoint = b.GenerateVtableForBase(RD); + + // then the vtables for all the virtual bases. + b.GenerateVtableForVBases(RD); + + llvm::Constant *C; + llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size()); + C = llvm::ConstantArray::get(type, methods); + llvm::Value *vtable = new llvm::GlobalVariable(CGM.getModule(), type, true, + linktype, C, Out.str()); + vtable = Builder.CreateBitCast(vtable, Ptr8Ty); + vtable = Builder.CreateGEP(vtable, + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + AddressPoint*LLVMPointerWidth/8)); + return vtable; +} diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h new file mode 100644 index 0000000000000..69fb1f1005996 --- /dev/null +++ b/lib/CodeGen/CGVtable.h @@ -0,0 +1,61 @@ +//===--- CGVtable.h - Emit LLVM Code for C++ vtables ----------------------===// +// +// 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 of virtual tables. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CODEGEN_CGVTABLE_H +#define CLANG_CODEGEN_CGVTABLE_H + +#include "llvm/ADT/DenseMap.h" + +namespace clang { + class CXXMethodDecl; + class CXXRecordDecl; + +namespace CodeGen { + class CodeGenModule; + +class CGVtableInfo { + CodeGenModule &CGM; + + /// MethodVtableIndices - Contains the index (relative to the vtable address + /// point) where the function pointer for a virtual function is stored. + typedef llvm::DenseMap<const CXXMethodDecl *, int64_t> MethodVtableIndicesTy; + MethodVtableIndicesTy MethodVtableIndices; + + typedef std::pair<const CXXRecordDecl *, + const CXXRecordDecl *> ClassPairTy; + + /// VirtualBaseClassIndicies - Contains the index into the vtable where the + /// offsets for virtual bases of a class are stored. + typedef llvm::DenseMap<ClassPairTy, int64_t> VirtualBaseClassIndiciesTy; + VirtualBaseClassIndiciesTy VirtualBaseClassIndicies; +public: + CGVtableInfo(CodeGenModule &CGM) + : CGM(CGM) { } + + /// getMethodVtableIndex - Return the index (relative to the vtable address + /// point) where the function pointer for the given virtual function is + /// stored. + int64_t getMethodVtableIndex(const CXXMethodDecl *MD); + + /// getVirtualBaseOffsetIndex - Return the index (relative to the vtable + /// address point) where the offset of the virtual base that contains the + /// given Base is stored, otherwise, if no virtual base contains the given + /// class, return 0. Base must be a virtual base class or an unambigious + /// base. + int64_t getVirtualBaseOffsetIndex(const CXXRecordDecl *RD, + const CXXRecordDecl *VBase); +}; + +} +} +#endif diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index c206a3bdd2088..2f46313c9c207 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -1,22 +1,27 @@ set(LLVM_NO_RTTI 1) add_clang_library(clangCodeGen - CGBuiltin.cpp CGBlocks.cpp - CGCall.cpp + CGBuiltin.cpp CGCXX.cpp + CGCXXClass.cpp + CGCXXExpr.cpp CGCXXTemp.cpp + CGCall.cpp CGDebugInfo.cpp CGDecl.cpp + CGExpr.cpp CGExprAgg.cpp CGExprComplex.cpp CGExprConstant.cpp - CGExpr.cpp CGExprScalar.cpp CGObjC.cpp CGObjCGNU.cpp CGObjCMac.cpp + CGRecordLayoutBuilder.cpp + CGRtti.cpp CGStmt.cpp + CGVtable.cpp CodeGenFunction.cpp CodeGenModule.cpp CodeGenTypes.cpp diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index c3f9364e7ae44..5206f447f8d0d 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -19,15 +19,16 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "llvm/Support/CFG.h" #include "llvm/Target/TargetData.h" using namespace clang; using namespace CodeGen; -CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) +CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : BlockFunction(cgm, *this, Builder), CGM(cgm), Target(CGM.getContext().Target), - DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0), + Builder(cgm.getModule().getContext()), + DebugInfo(0), IndirectGotoSwitch(0), + SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0), CXXThisDecl(0) { LLVMIntTy = ConvertType(getContext().IntTy); LLVMPointerWidth = Target.getPointerWidth(0); @@ -41,7 +42,7 @@ ASTContext &CodeGenFunction::getContext() const { llvm::BasicBlock *CodeGenFunction::getBasicBlockForLabel(const LabelStmt *S) { llvm::BasicBlock *&BB = LabelMap[S]; if (BB) return BB; - + // Create, but don't insert, the new block. return BB = createBasicBlock(S->getName()); } @@ -66,11 +67,8 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T) { } bool CodeGenFunction::hasAggregateLLVMType(QualType T) { - // FIXME: Use positive checks instead of negative ones to be more robust in - // the face of extension. - return !T->hasPointerRepresentation() &&!T->isRealType() && - !T->isVoidType() && !T->isVectorType() && !T->isFunctionType() && - !T->isBlockPointerType(); + return T->isRecordType() || T->isArrayType() || T->isAnyComplexType() || + T->isMemberFunctionPointerType(); } void CodeGenFunction::EmitReturnBlock() { @@ -81,11 +79,12 @@ void CodeGenFunction::EmitReturnBlock() { if (CurBB) { assert(!CurBB->getTerminator() && "Unexpected terminated block."); - // We have a valid insert point, reuse it if there are no explicit - // jumps to the return block. - if (ReturnBlock->use_empty()) + // We have a valid insert point, reuse it if it is empty or there are no + // explicit jumps to the return block. + if (CurBB->empty() || ReturnBlock->use_empty()) { + ReturnBlock->replaceAllUsesWith(CurBB); delete ReturnBlock; - else + } else EmitBlock(ReturnBlock); return; } @@ -94,7 +93,7 @@ void CodeGenFunction::EmitReturnBlock() { // branch then we can just put the code in that block instead. This // cleans up functions which started with a unified return block. if (ReturnBlock->hasOneUse()) { - llvm::BranchInst *BI = + llvm::BranchInst *BI = dyn_cast<llvm::BranchInst>(*ReturnBlock->use_begin()); if (BI && BI->isUnconditional() && BI->getSuccessor(0) == ReturnBlock) { // Reset insertion point and delete the branch. @@ -113,17 +112,14 @@ void CodeGenFunction::EmitReturnBlock() { } void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { - // Finish emission of indirect switches. - EmitIndirectSwitches(); - assert(BreakContinueStack.empty() && "mismatched push/pop in break/continue stack!"); assert(BlockScopes.empty() && "did not remove all blocks from block scope map!"); assert(CleanupEntries.empty() && "mismatched push/pop in cleanup stack!"); - - // Emit function epilog (to return). + + // Emit function epilog (to return). EmitReturnBlock(); // Emit debug descriptor for function end. @@ -140,10 +136,12 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { Ptr->eraseFromParent(); } -void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy, +void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const FunctionArgList &Args, SourceLocation StartLoc) { + const Decl *D = GD.getDecl(); + DidCallStackSave = false; CurCodeDecl = CurFuncDecl = D; FnRetTy = RetTy; @@ -155,28 +153,31 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy, // Create a marker to make it easy to insert allocas into the entryblock // later. Don't create this with the builder, because we don't want it // folded. - llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::Int32Ty); - AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::Int32Ty, "", + llvm::Value *Undef = llvm::UndefValue::get(llvm::Type::getInt32Ty(VMContext)); + AllocaInsertPt = new llvm::BitCastInst(Undef, + llvm::Type::getInt32Ty(VMContext), "", EntryBB); if (Builder.isNamePreserving()) AllocaInsertPt->setName("allocapt"); - + ReturnBlock = createBasicBlock("return"); ReturnValue = 0; if (!RetTy->isVoidType()) ReturnValue = CreateTempAlloca(ConvertType(RetTy), "retval"); - + Builder.SetInsertPoint(EntryBB); - + // Emit subprogram debug descriptor. // FIXME: The cast here is a huge hack. if (CGDebugInfo *DI = getDebugInfo()) { DI->setLocation(StartLoc); - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - DI->EmitFunctionStart(CGM.getMangledName(FD), RetTy, CurFn, Builder); + if (isa<FunctionDecl>(D)) { + DI->EmitFunctionStart(CGM.getMangledName(GD), RetTy, CurFn, Builder); } else { // Just use LLVM function name. - DI->EmitFunctionStart(Fn->getName().c_str(), + + // FIXME: Remove unnecessary conversion to std::string when API settles. + DI->EmitFunctionStart(std::string(Fn->getName()).c_str(), RetTy, CurFn, Builder); } } @@ -184,7 +185,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy, // FIXME: Leaked. CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args); EmitFunctionProlog(*CurFnInfo, CurFn, Args); - + // If any of the arguments have a variably modified type, make sure to // emit the type size. for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); @@ -196,40 +197,96 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy, } } -void CodeGenFunction::GenerateCode(const FunctionDecl *FD, +void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) { + const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); + // Check if we should generate debug info for this function. - if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>()) + if (CGM.getDebugInfo() && !FD->hasAttr<NoDebugAttr>()) DebugInfo = CGM.getDebugInfo(); - + FunctionArgList Args; - + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { if (MD->isInstance()) { // Create the implicit 'this' decl. // FIXME: I'm not entirely sure I like using a fake decl just for code // generation. Maybe we can come up with a better way? CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), - &getContext().Idents.get("this"), + &getContext().Idents.get("this"), MD->getThisType(getContext())); Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType())); } } - + if (FD->getNumParams()) { - const FunctionProtoType* FProto = FD->getType()->getAsFunctionProtoType(); + const FunctionProtoType* FProto = FD->getType()->getAs<FunctionProtoType>(); assert(FProto && "Function def must have prototype!"); for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) - Args.push_back(std::make_pair(FD->getParamDecl(i), + Args.push_back(std::make_pair(FD->getParamDecl(i), FProto->getArgType(i))); } // FIXME: Support CXXTryStmt here, too. if (const CompoundStmt *S = FD->getCompoundBody()) { - StartFunction(FD, FD->getResultType(), Fn, Args, S->getLBracLoc()); + StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc()); + const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD); + llvm::BasicBlock *DtorEpilogue = 0; + if (DD) { + DtorEpilogue = createBasicBlock("dtor.epilogue"); + + PushCleanupBlock(DtorEpilogue); + } + + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) + EmitCtorPrologue(CD, GD.getCtorType()); EmitStmt(S); + + if (DD) { + CleanupBlockInfo Info = PopCleanupBlock(); + + assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!"); + EmitBlock(DtorEpilogue); + EmitDtorEpilogue(DD, GD.getDtorType()); + + if (Info.SwitchBlock) + EmitBlock(Info.SwitchBlock); + if (Info.EndBlock) + EmitBlock(Info.EndBlock); + } FinishFunction(S->getRBracLoc()); + } else if (FD->isImplicit()) { + const CXXRecordDecl *ClassDecl = + cast<CXXRecordDecl>(FD->getDeclContext()); + (void) ClassDecl; + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { + // FIXME: For C++0x, we want to look for implicit *definitions* of + // these special member functions, rather than implicit *declarations*. + if (CD->isCopyConstructor(getContext())) { + assert(!ClassDecl->hasUserDeclaredCopyConstructor() && + "Cannot synthesize a non-implicit copy constructor"); + SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args); + } else if (CD->isDefaultConstructor()) { + assert(!ClassDecl->hasUserDeclaredConstructor() && + "Cannot synthesize a non-implicit default constructor."); + SynthesizeDefaultConstructor(CD, GD.getCtorType(), Fn, Args); + } else { + assert(false && "Implicit constructor cannot be synthesized"); + } + } else if (const CXXDestructorDecl *CD = dyn_cast<CXXDestructorDecl>(FD)) { + assert(!ClassDecl->hasUserDeclaredDestructor() && + "Cannot synthesize a non-implicit destructor"); + SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args); + } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { + assert(MD->isCopyAssignment() && + !ClassDecl->hasUserDeclaredCopyAssignment() && + "Cannot synthesize a method that is not an implicit-defined " + "copy constructor"); + SynthesizeCXXCopyAssignment(MD, Fn, Args); + } else { + assert(false && "Cannot synthesize unknown implicit function"); + } } // Destroy the 'this' declaration. @@ -243,27 +300,27 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD, bool CodeGenFunction::ContainsLabel(const Stmt *S, bool IgnoreCaseStmts) { // Null statement, not a label! if (S == 0) return false; - + // If this is a label, we have to emit the code, consider something like: // if (0) { ... foo: bar(); } goto foo; if (isa<LabelStmt>(S)) return true; - + // If this is a case/default statement, and we haven't seen a switch, we have // to emit the code. if (isa<SwitchCase>(S) && !IgnoreCaseStmts) return true; - + // If this is a switch statement, we want to ignore cases below it. if (isa<SwitchStmt>(S)) IgnoreCaseStmts = true; - + // Scan subexpressions for verboten labels. for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); I != E; ++I) if (ContainsLabel(*I, IgnoreCaseStmts)) return true; - + return false; } @@ -276,13 +333,13 @@ int CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond) { // FIXME: Rename and handle conversion of other evaluatable things // to bool. Expr::EvalResult Result; - if (!Cond->Evaluate(Result, getContext()) || !Result.Val.isInt() || + if (!Cond->Evaluate(Result, getContext()) || !Result.Val.isInt() || Result.HasSideEffects) return 0; // Not foldable, not integer or not fully evaluatable. - + if (CodeGenFunction::ContainsLabel(Cond)) return 0; // Contains a label. - + return Result.Val.getInt().getBoolValue() ? 1 : -1; } @@ -296,7 +353,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *FalseBlock) { if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) return EmitBranchOnBoolExpr(PE->getSubExpr(), TrueBlock, FalseBlock); - + if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) { // Handle X && Y in a condition. if (CondBOp->getOpcode() == BinaryOperator::LAnd) { @@ -306,20 +363,20 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, // br(1 && X) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); } - + // If we have "X && 1", simplify the code to use an uncond branch. // "X && 0" would have been constant folded to 0. if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == 1) { // br(X && 1) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock); } - + // Emit the LHS as a conditional. If the LHS conditional is false, we // want to jump to the FalseBlock. llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true"); EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock); EmitBlock(LHSTrue); - + EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); return; } else if (CondBOp->getOpcode() == BinaryOperator::LOr) { @@ -329,31 +386,31 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, // br(0 || X) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); } - + // If we have "X || 0", simplify the code to use an uncond branch. // "X || 1" would have been constant folded to 1. if (ConstantFoldsToSimpleInteger(CondBOp->getRHS()) == -1) { // br(X || 0) -> br(X). return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock); } - + // Emit the LHS as a conditional. If the LHS conditional is true, we // want to jump to the TrueBlock. llvm::BasicBlock *LHSFalse = createBasicBlock("lor.lhs.false"); EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse); EmitBlock(LHSFalse); - + EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock); return; } } - + if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(Cond)) { // br(!x, t, f) -> br(x, f, t) if (CondUOp->getOpcode() == UnaryOperator::LNot) return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock); } - + if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(Cond)) { // Handle ?: operator. @@ -376,15 +433,6 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, Builder.CreateCondBr(CondV, TrueBlock, FalseBlock); } -/// getCGRecordLayout - Return record layout info. -const CGRecordLayout *CodeGenFunction::getCGRecordLayout(CodeGenTypes &CGT, - QualType Ty) { - const RecordType *RTy = Ty->getAsRecordType(); - assert (RTy && "Unexpected type. RecordType expected here."); - - return CGT.getCGRecordLayout(RTy->getDecl()); -} - /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type, @@ -392,13 +440,8 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type, CGM.ErrorUnsupported(S, Type, OmitOnError); } -unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) { - // Use LabelIDs.size() as the new ID if one hasn't been assigned. - return LabelIDs.insert(std::make_pair(L, LabelIDs.size())).first->second; -} - void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) { - const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); if (DestPtr->getType() != BP) DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); @@ -408,93 +451,141 @@ void CodeGenFunction::EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty) { // Don't bother emitting a zero-byte memset. if (TypeInfo.first == 0) return; - + // FIXME: Handle variable sized types. - const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); + const llvm::Type *IntPtr = llvm::IntegerType::get(VMContext, + LLVMPointerWidth); Builder.CreateCall4(CGM.getMemSetFn(), DestPtr, - llvm::ConstantInt::getNullValue(llvm::Type::Int8Ty), + llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)), // TypeInfo.first describes size in bits. llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), - llvm::ConstantInt::get(llvm::Type::Int32Ty, + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), TypeInfo.second/8)); } -void CodeGenFunction::EmitIndirectSwitches() { - llvm::BasicBlock *Default; +unsigned CodeGenFunction::GetIDForAddrOfLabel(const LabelStmt *L) { + // Use LabelIDs.size()+1 as the new ID if one hasn't been assigned. + unsigned &Entry = LabelIDs[L]; + if (Entry) return Entry; + + Entry = LabelIDs.size(); + + // If this is the first "address taken" of a label and the indirect goto has + // already been seen, add this to it. + if (IndirectGotoSwitch) { + // If this is the first address-taken label, set it as the default dest. + if (Entry == 1) + IndirectGotoSwitch->setSuccessor(0, getBasicBlockForLabel(L)); + else { + // Otherwise add it to the switch as a new dest. + const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext); + IndirectGotoSwitch->addCase(llvm::ConstantInt::get(Int32Ty, Entry), + getBasicBlockForLabel(L)); + } + } - if (IndirectSwitches.empty()) - return; + return Entry; +} + +llvm::BasicBlock *CodeGenFunction::GetIndirectGotoBlock() { + // If we already made the switch stmt for indirect goto, return its block. + if (IndirectGotoSwitch) return IndirectGotoSwitch->getParent(); + + EmitBlock(createBasicBlock("indirectgoto")); + + // Create the PHI node that indirect gotos will add entries to. + llvm::Value *DestVal = + Builder.CreatePHI(llvm::Type::getInt32Ty(VMContext), "indirect.goto.dest"); + + // Create the switch instruction. For now, set the insert block to this block + // which will be fixed as labels are added. + IndirectGotoSwitch = Builder.CreateSwitch(DestVal, Builder.GetInsertBlock()); + + // Clear the insertion point to indicate we are in unreachable code. + Builder.ClearInsertionPoint(); + // If we already have labels created, add them. if (!LabelIDs.empty()) { - Default = getBasicBlockForLabel(LabelIDs.begin()->first); + // Invert LabelID's so that the order is determinstic. + std::vector<const LabelStmt*> AddrTakenLabelsByID; + AddrTakenLabelsByID.resize(LabelIDs.size()); + + for (std::map<const LabelStmt*,unsigned>::iterator + LI = LabelIDs.begin(), LE = LabelIDs.end(); LI != LE; ++LI) { + assert(LI->second-1 < AddrTakenLabelsByID.size() && + "Numbering inconsistent"); + AddrTakenLabelsByID[LI->second-1] = LI->first; + } + + // Set the default entry as the first block. + IndirectGotoSwitch->setSuccessor(0, + getBasicBlockForLabel(AddrTakenLabelsByID[0])); + + const llvm::IntegerType *Int32Ty = llvm::Type::getInt32Ty(VMContext); + + // FIXME: The iteration order of this is nondeterminstic! + for (unsigned i = 1, e = AddrTakenLabelsByID.size(); i != e; ++i) + IndirectGotoSwitch->addCase(llvm::ConstantInt::get(Int32Ty, i+1), + getBasicBlockForLabel(AddrTakenLabelsByID[i])); } else { - // No possible targets for indirect goto, just emit an infinite - // loop. - Default = createBasicBlock("indirectgoto.loop", CurFn); - llvm::BranchInst::Create(Default, Default); + // Otherwise, create a dead block and set it as the default dest. This will + // be removed by the optimizers after the indirect goto is set up. + llvm::BasicBlock *Dummy = createBasicBlock("indgoto.dummy"); + EmitBlock(Dummy); + IndirectGotoSwitch->setSuccessor(0, Dummy); + Builder.CreateUnreachable(); + Builder.ClearInsertionPoint(); } - for (std::vector<llvm::SwitchInst*>::iterator i = IndirectSwitches.begin(), - e = IndirectSwitches.end(); i != e; ++i) { - llvm::SwitchInst *I = *i; - - I->setSuccessor(0, Default); - for (std::map<const LabelStmt*,unsigned>::iterator LI = LabelIDs.begin(), - LE = LabelIDs.end(); LI != LE; ++LI) { - I->addCase(llvm::ConstantInt::get(llvm::Type::Int32Ty, - LI->second), - getBasicBlockForLabel(LI->first)); - } - } + return IndirectGotoSwitch->getParent(); } -llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) -{ - llvm::Value *&SizeEntry = VLASizeMap[VAT]; - +llvm::Value *CodeGenFunction::GetVLASize(const VariableArrayType *VAT) { + llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()]; + assert(SizeEntry && "Did not emit size for type"); return SizeEntry; } -llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) -{ +llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) { assert(Ty->isVariablyModifiedType() && "Must pass variably modified type to EmitVLASizes!"); - + + EnsureInsertPoint(); + if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) { - llvm::Value *&SizeEntry = VLASizeMap[VAT]; - + llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()]; + if (!SizeEntry) { + const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); + // Get the element size; - llvm::Value *ElemSize; - QualType ElemTy = VAT->getElementType(); - - const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); - + llvm::Value *ElemSize; if (ElemTy->isVariableArrayType()) ElemSize = EmitVLASize(ElemTy); - else { + else ElemSize = llvm::ConstantInt::get(SizeTy, getContext().getTypeSize(ElemTy) / 8); - } - + llvm::Value *NumElements = EmitScalarExpr(VAT->getSizeExpr()); NumElements = Builder.CreateIntCast(NumElements, SizeTy, false, "tmp"); - + SizeEntry = Builder.CreateMul(ElemSize, NumElements); } - + return SizeEntry; - } else if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) { + } + + if (const ArrayType *AT = dyn_cast<ArrayType>(Ty)) { EmitVLASize(AT->getElementType()); - } else if (const PointerType *PT = Ty->getAsPointerType()) - EmitVLASize(PT->getPointeeType()); - else { - assert(0 && "unknown VM type!"); + return 0; } - + + const PointerType *PT = Ty->getAs<PointerType>(); + assert(PT && "unknown VM type!"); + EmitVLASize(PT->getPointeeType()); return 0; } @@ -505,32 +596,29 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) { return EmitLValue(E).getAddress(); } -void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupBlock) -{ +void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupBlock) { CleanupEntries.push_back(CleanupEntry(CleanupBlock)); } -void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) -{ - assert(CleanupEntries.size() >= OldCleanupStackSize && +void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) { + assert(CleanupEntries.size() >= OldCleanupStackSize && "Cleanup stack mismatch!"); - + while (CleanupEntries.size() > OldCleanupStackSize) EmitCleanupBlock(); } -CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() -{ +CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { CleanupEntry &CE = CleanupEntries.back(); - + llvm::BasicBlock *CleanupBlock = CE.CleanupBlock; - + std::vector<llvm::BasicBlock *> Blocks; std::swap(Blocks, CE.Blocks); - + std::vector<llvm::BranchInst *> BranchFixups; std::swap(BranchFixups, CE.BranchFixups); - + CleanupEntries.pop_back(); // Check if any branch fixups pointed to the scope we just popped. If so, @@ -538,12 +626,12 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() for (size_t i = 0, e = BranchFixups.size(); i != e; ++i) { llvm::BasicBlock *Dest = BranchFixups[i]->getSuccessor(0); BlockScopeMap::iterator I = BlockScopes.find(Dest); - + if (I == BlockScopes.end()) continue; - + assert(I->second <= CleanupEntries.size() && "Invalid branch fixup!"); - + if (I->second == CleanupEntries.size()) { // We don't need to do this branch fixup. BranchFixups[i] = BranchFixups.back(); @@ -553,32 +641,32 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() continue; } } - + llvm::BasicBlock *SwitchBlock = 0; llvm::BasicBlock *EndBlock = 0; if (!BranchFixups.empty()) { SwitchBlock = createBasicBlock("cleanup.switch"); EndBlock = createBasicBlock("cleanup.end"); - + llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); - + Builder.SetInsertPoint(SwitchBlock); - llvm::Value *DestCodePtr = CreateTempAlloca(llvm::Type::Int32Ty, + llvm::Value *DestCodePtr = CreateTempAlloca(llvm::Type::getInt32Ty(VMContext), "cleanup.dst"); llvm::Value *DestCode = Builder.CreateLoad(DestCodePtr, "tmp"); - + // Create a switch instruction to determine where to jump next. - llvm::SwitchInst *SI = Builder.CreateSwitch(DestCode, EndBlock, + llvm::SwitchInst *SI = Builder.CreateSwitch(DestCode, EndBlock, BranchFixups.size()); // Restore the current basic block (if any) if (CurBB) { Builder.SetInsertPoint(CurBB); - + // If we had a current basic block, we also need to emit an instruction // to initialize the cleanup destination. - Builder.CreateStore(llvm::Constant::getNullValue(llvm::Type::Int32Ty), + Builder.CreateStore(llvm::Constant::getNullValue(llvm::Type::getInt32Ty(VMContext)), DestCodePtr); } else Builder.ClearInsertionPoint(); @@ -586,39 +674,39 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() for (size_t i = 0, e = BranchFixups.size(); i != e; ++i) { llvm::BranchInst *BI = BranchFixups[i]; llvm::BasicBlock *Dest = BI->getSuccessor(0); - + // Fixup the branch instruction to point to the cleanup block. BI->setSuccessor(0, CleanupBlock); - + if (CleanupEntries.empty()) { llvm::ConstantInt *ID; - + // Check if we already have a destination for this block. if (Dest == SI->getDefaultDest()) - ID = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0); + ID = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0); else { ID = SI->findCaseDest(Dest); if (!ID) { // No code found, get a new unique one by using the number of // switch successors. - ID = llvm::ConstantInt::get(llvm::Type::Int32Ty, + ID = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), SI->getNumSuccessors()); SI->addCase(ID, Dest); } } - + // Store the jump destination before the branch instruction. new llvm::StoreInst(ID, DestCodePtr, BI); } else { // We need to jump through another cleanup block. Create a pad block // with a branch instruction that jumps to the final destination and // add it as a branch fixup to the current cleanup scope. - + // Create the pad block. llvm::BasicBlock *CleanupPad = createBasicBlock("cleanup.pad", CurFn); // Create a unique case ID. - llvm::ConstantInt *ID = llvm::ConstantInt::get(llvm::Type::Int32Ty, + llvm::ConstantInt *ID = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), SI->getNumSuccessors()); // Store the jump destination before the branch instruction. @@ -626,89 +714,86 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() // Add it as the destination. SI->addCase(ID, CleanupPad); - + // Create the branch to the final destination. llvm::BranchInst *BI = llvm::BranchInst::Create(Dest); CleanupPad->getInstList().push_back(BI); - + // And add it as a branch fixup. CleanupEntries.back().BranchFixups.push_back(BI); } } } - + // Remove all blocks from the block scope map. for (size_t i = 0, e = Blocks.size(); i != e; ++i) { assert(BlockScopes.count(Blocks[i]) && "Did not find block in scope map!"); - + BlockScopes.erase(Blocks[i]); } - + return CleanupBlockInfo(CleanupBlock, SwitchBlock, EndBlock); } -void CodeGenFunction::EmitCleanupBlock() -{ +void CodeGenFunction::EmitCleanupBlock() { CleanupBlockInfo Info = PopCleanupBlock(); - + llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); - if (CurBB && !CurBB->getTerminator() && + if (CurBB && !CurBB->getTerminator() && Info.CleanupBlock->getNumUses() == 0) { CurBB->getInstList().splice(CurBB->end(), Info.CleanupBlock->getInstList()); delete Info.CleanupBlock; - } else + } else EmitBlock(Info.CleanupBlock); - + if (Info.SwitchBlock) EmitBlock(Info.SwitchBlock); if (Info.EndBlock) EmitBlock(Info.EndBlock); } -void CodeGenFunction::AddBranchFixup(llvm::BranchInst *BI) -{ - assert(!CleanupEntries.empty() && +void CodeGenFunction::AddBranchFixup(llvm::BranchInst *BI) { + assert(!CleanupEntries.empty() && "Trying to add branch fixup without cleanup block!"); - + // FIXME: We could be more clever here and check if there's already a branch // fixup for this destination and recycle it. CleanupEntries.back().BranchFixups.push_back(BI); } -void CodeGenFunction::EmitBranchThroughCleanup(llvm::BasicBlock *Dest) -{ +void CodeGenFunction::EmitBranchThroughCleanup(llvm::BasicBlock *Dest) { if (!HaveInsertPoint()) return; - + llvm::BranchInst* BI = Builder.CreateBr(Dest); - + Builder.ClearInsertionPoint(); - + // The stack is empty, no need to do any cleanup. if (CleanupEntries.empty()) return; - + if (!Dest->getParent()) { // We are trying to branch to a block that hasn't been inserted yet. AddBranchFixup(BI); return; } - + BlockScopeMap::iterator I = BlockScopes.find(Dest); if (I == BlockScopes.end()) { // We are trying to jump to a block that is outside of any cleanup scope. AddBranchFixup(BI); return; } - + assert(I->second < CleanupEntries.size() && "Trying to branch into cleanup region"); - + if (I->second == CleanupEntries.size() - 1) { // We have a branch to a block in the same scope. return; } - + AddBranchFixup(BI); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 72c4aa4a658ab..722d002c19f57 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -22,6 +22,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/ValueHandle.h" #include <map> +#include "CodeGenModule.h" #include "CGBlocks.h" #include "CGBuilder.h" #include "CGCall.h" @@ -30,6 +31,7 @@ namespace llvm { class BasicBlock; + class LLVMContext; class Module; class SwitchInst; class Value; @@ -38,6 +40,7 @@ namespace llvm { namespace clang { class ASTContext; class CXXDestructorDecl; + class CXXTryStmt; class Decl; class EnumConstantDecl; class FunctionDecl; @@ -145,7 +148,11 @@ public: ~CleanupScope() { CGF.PushCleanupBlock(CleanupBB); - CGF.Builder.SetInsertPoint(CurBB); + // FIXME: This is silly, move this into the builder. + if (CurBB) + CGF.Builder.SetInsertPoint(CurBB); + else + CGF.Builder.ClearInsertionPoint(); } }; @@ -160,20 +167,20 @@ public: /// this behavior for branches? void EmitBranchThroughCleanup(llvm::BasicBlock *Dest); - /// PushConditionalTempDestruction - Should be called before a conditional + /// PushConditionalTempDestruction - Should be called before a conditional /// part of an expression is emitted. For example, before the RHS of the /// expression below is emitted: - /// + /// /// b && f(T()); /// /// This is used to make sure that any temporaryes created in the conditional /// branch are only destroyed if the branch is taken. void PushConditionalTempDestruction(); - - /// PopConditionalTempDestruction - Should be called after a conditional + + /// PopConditionalTempDestruction - Should be called after a conditional /// part of an expression has been emitted. void PopConditionalTempDestruction(); - + private: CGDebugInfo* DebugInfo; @@ -182,10 +189,12 @@ private: /// labels inside getIDForAddrOfLabel(). std::map<const LabelStmt*, unsigned> LabelIDs; - /// IndirectSwitches - Record the list of switches for indirect - /// gotos. Emission of the actual switching code needs to be delayed until all - /// AddrLabelExprs have been seen. - std::vector<llvm::SwitchInst*> IndirectSwitches; + /// IndirectGotoSwitch - The first time an indirect goto is seen we create a + /// block with the switch for the indirect gotos. Every time we see the + /// address of a label taken, we add the label to the indirect goto. Every + /// subsequent indirect goto is codegen'd as a jump to the + /// IndirectGotoSwitch's basic block. + llvm::SwitchInst *IndirectGotoSwitch; /// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C /// decls. @@ -218,9 +227,12 @@ private: llvm::BasicBlock *InvokeDest; // VLASizeMap - This keeps track of the associated size for each VLA type. + // We track this by the size expression rather than the type itself because + // in certain situations, like a const qualifier applied to an VLA typedef, + // multiple VLA types can share the same size expression. // FIXME: Maybe this could be a stack of maps that is pushed/popped as we // enter/leave scopes. - llvm::DenseMap<const VariableArrayType*, llvm::Value*> VLASizeMap; + llvm::DenseMap<const Expr*, llvm::Value*> VLASizeMap; /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid /// calling llvm.stacksave for multiple VLAs in the same scope. @@ -252,36 +264,46 @@ private: /// CXXThisDecl - When parsing an C++ function, this will hold the implicit /// 'this' declaration. ImplicitParamDecl *CXXThisDecl; - + /// CXXLiveTemporaryInfo - Holds information about a live C++ temporary. struct CXXLiveTemporaryInfo { /// Temporary - The live temporary. const CXXTemporary *Temporary; - + /// ThisPtr - The pointer to the temporary. llvm::Value *ThisPtr; - + /// DtorBlock - The destructor block. llvm::BasicBlock *DtorBlock; - + /// CondPtr - If this is a conditional temporary, this is the pointer to /// the condition variable that states whether the destructor should be /// called or not. llvm::Value *CondPtr; - + CXXLiveTemporaryInfo(const CXXTemporary *temporary, llvm::Value *thisptr, llvm::BasicBlock *dtorblock, llvm::Value *condptr) - : Temporary(temporary), ThisPtr(thisptr), DtorBlock(dtorblock), + : Temporary(temporary), ThisPtr(thisptr), DtorBlock(dtorblock), CondPtr(condptr) { } }; - + llvm::SmallVector<CXXLiveTemporaryInfo, 4> LiveTemporaries; - /// ConditionalTempDestructionStack - Contains the number of live temporaries + /// ConditionalTempDestructionStack - Contains the number of live temporaries /// when PushConditionalTempDestruction was called. This is used so that /// we know how many temporaries were created by a certain expression. llvm::SmallVector<size_t, 4> ConditionalTempDestructionStack; + + + /// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM + /// type as well as the field number that contains the actual data. + llvm::DenseMap<const ValueDecl *, std::pair<const llvm::Type *, + unsigned> > ByRefValueInfo; + + /// getByrefValueFieldNumber - Given a declaration, returns the LLVM field + /// number that holds the value. + unsigned getByRefValueLLVMField(const ValueDecl *VD) const; public: CodeGenFunction(CodeGenModule &cgm); @@ -292,6 +314,8 @@ public: llvm::BasicBlock *getInvokeDest() { return InvokeDest; } void setInvokeDest(llvm::BasicBlock *B) { InvokeDest = B; } + llvm::LLVMContext &getLLVMContext() { return VMContext; } + //===--------------------------------------------------------------------===// // Objective-C //===--------------------------------------------------------------------===// @@ -332,12 +356,10 @@ public: llvm::Value *LoadBlockStruct(); llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E); + const llvm::Type *BuildByRefType(const ValueDecl *D); - const llvm::Type *BuildByRefType(QualType Ty, uint64_t Align); - - void GenerateCode(const FunctionDecl *FD, - llvm::Function *Fn); - void StartFunction(const Decl *D, QualType RetTy, + void GenerateCode(GlobalDecl GD, llvm::Function *Fn); + void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const FunctionArgList &Args, SourceLocation StartLoc); @@ -350,6 +372,44 @@ public: /// legal to call this function even if there is no current insertion point. void FinishFunction(SourceLocation EndLoc=SourceLocation()); + /// GenerateVtable - Generate the vtable for the given type. + llvm::Value *GenerateVtable(const CXXRecordDecl *RD); + + /// GenerateThunk - Generate a thunk for the given method + llvm::Constant *GenerateThunk(llvm::Function *Fn, const CXXMethodDecl *MD, + bool Extern, int64_t nv, int64_t v); + llvm::Constant *GenerateCovariantThunk(llvm::Function *Fn, + const CXXMethodDecl *MD, bool Extern, + int64_t nv_t, int64_t v_t, + int64_t nv_r, int64_t v_r); + + void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type); + + void SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, + CXXCtorType Type, + llvm::Function *Fn, + const FunctionArgList &Args); + + void SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, + llvm::Function *Fn, + const FunctionArgList &Args); + + void SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor, + CXXCtorType Type, + llvm::Function *Fn, + const FunctionArgList &Args); + + void SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, + CXXDtorType Type, + llvm::Function *Fn, + const FunctionArgList &Args); + + /// EmitDtorEpilogue - Emit all code that comes at the end of class's + /// destructor. This is to call destructors on members and base classes + /// in reverse order of their construction. + void EmitDtorEpilogue(const CXXDestructorDecl *Dtor, + CXXDtorType Type); + /// EmitFunctionProlog - Emit the target specific LLVM code to load the /// arguments for the given function. This is also responsible for naming the /// LLVM function arguments. @@ -380,9 +440,9 @@ public: llvm::Function *Parent=0, llvm::BasicBlock *InsertBefore=0) { #ifdef NDEBUG - return llvm::BasicBlock::Create("", Parent, InsertBefore); + return llvm::BasicBlock::Create(VMContext, "", Parent, InsertBefore); #else - return llvm::BasicBlock::Create(Name, Parent, InsertBefore); + return llvm::BasicBlock::Create(VMContext, Name, Parent, InsertBefore); #endif } @@ -439,6 +499,12 @@ public: // Helpers //===--------------------------------------------------------------------===// + Qualifiers MakeQualifiers(QualType T) { + Qualifiers Quals = T.getQualifiers(); + Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T)); + return Quals; + } + /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty, @@ -455,7 +521,8 @@ public: /// /// \param IgnoreResult - True if the resulting value isn't used. RValue EmitAnyExpr(const Expr *E, llvm::Value *AggLoc = 0, - bool isAggLocVolatile = false, bool IgnoreResult = false); + bool IsAggLocVolatile = false, bool IgnoreResult = false, + bool IsInitializer = false); // EmitVAListRef - Emit a "reference" to a va_list; this is either the address // or the value of the expression, depending on how va_list is defined. @@ -463,8 +530,8 @@ public: /// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will /// always be accessible even if no aggregate location is provided. - RValue EmitAnyExprToTemp(const Expr *E, llvm::Value *AggLoc = 0, - bool isAggLocVolatile = false); + RValue EmitAnyExprToTemp(const Expr *E, bool IsAggLocVolatile = false, + bool IsInitializer = false); /// EmitAggregateCopy - Emit an aggrate copy. /// @@ -479,9 +546,6 @@ public: /// then reuse it. void StartBlock(const char *N); - /// getCGRecordLayout - Return record layout info. - const CGRecordLayout *getCGRecordLayout(CodeGenTypes &CGT, QualType RTy); - /// GetAddrOfStaticLocalVar - Return the address of a static local variable. llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD); @@ -493,6 +557,7 @@ public: static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts); unsigned GetIDForAddrOfLabel(const LabelStmt *L); + llvm::BasicBlock *GetIndirectGotoBlock(); /// EmitMemSetToZero - Generate code to memset a value of the given type to 0. void EmitMemSetToZero(llvm::Value *DestPtr, QualType Ty); @@ -506,6 +571,8 @@ public: // EmitVLASize - Generate code for any VLA size expressions that might occur // in a variably modified type. If Ty is a VLA, will return the value that // corresponds to the size in bytes of the VLA type. Will return 0 otherwise. + /// + /// This function can be called with a null (unreachable) insert point. llvm::Value *EmitVLASize(QualType Ty); // GetVLASize - Returns an LLVM value that corresponds to the size in bytes @@ -515,27 +582,87 @@ public: /// LoadCXXThis - Load the value of 'this'. This function is only valid while /// generating code for an C++ member function. llvm::Value *LoadCXXThis(); + + /// GetAddressCXXOfBaseClass - This function will add the necessary delta + /// to the load of 'this' and returns address of the base class. + // FIXME. This currently only does a derived to non-virtual base conversion. + // Other kinds of conversions will come later. + llvm::Value *GetAddressCXXOfBaseClass(llvm::Value *BaseValue, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, + bool NullCheckValue); - void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, + llvm::Value * + GetVirtualCXXBaseClassOffset(llvm::Value *This, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl); + + void EmitClassAggrMemberwiseCopy(llvm::Value *DestValue, + llvm::Value *SrcValue, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty); + + void EmitClassAggrCopyAssignment(llvm::Value *DestValue, + llvm::Value *SrcValue, + const ArrayType *Array, + const CXXRecordDecl *BaseClassDecl, + QualType Ty); + + void EmitClassMemberwiseCopy(llvm::Value *DestValue, llvm::Value *SrcValue, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, + QualType Ty); + + void EmitClassCopyAssignment(llvm::Value *DestValue, llvm::Value *SrcValue, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl, + QualType Ty); + + void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); + void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, + const ConstantArrayType *ArrayTy, + llvm::Value *ArrayPtr); + void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, + llvm::Value *NumElements, + llvm::Value *ArrayPtr); + + void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, + const ArrayType *Array, + llvm::Value *This); + void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, llvm::Value *This); - + void PushCXXTemporary(const CXXTemporary *Temporary, llvm::Value *Ptr); void PopCXXTemporary(); - + llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); - + void EmitCXXDeleteExpr(const CXXDeleteExpr *E); + //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// + /// EmitDecl - Emit a declaration. + /// + /// This function can be called with a null (unreachable) insert point. void EmitDecl(const Decl &D); + + /// EmitBlockVarDecl - Emit a block variable declaration. + /// + /// This function can be called with a null (unreachable) insert point. void EmitBlockVarDecl(const VarDecl &D); + + /// EmitLocalBlockVarDecl - Emit a local block variable declaration. + /// + /// This function can be called with a null (unreachable) insert point. void EmitLocalBlockVarDecl(const VarDecl &D); + void EmitStaticBlockVarDecl(const VarDecl &D); /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl. @@ -593,6 +720,8 @@ public: void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S); void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S); + void EmitCXXTryStmt(const CXXTryStmt &S); + //===--------------------------------------------------------------------===// // LValue Expression Emission //===--------------------------------------------------------------------===// @@ -685,7 +814,7 @@ public: LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E); LValue EmitMemberExpr(const MemberExpr *E); LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E); - LValue EmitConditionalOperator(const ConditionalOperator *E); + LValue EmitConditionalOperatorLValue(const ConditionalOperator *E); LValue EmitCastLValue(const CastExpr *E); llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, @@ -704,11 +833,12 @@ public: LValue EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E); LValue EmitCXXConstructLValue(const CXXConstructExpr *E); LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E); + LValue EmitCXXExprWithTemporariesLValue(const CXXExprWithTemporaries *E); LValue EmitObjCMessageExprLValue(const ObjCMessageExpr *E); LValue EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E); LValue EmitObjCPropertyRefLValue(const ObjCPropertyRefExpr *E); - LValue EmitObjCKVCRefLValue(const ObjCKVCRefExpr *E); + LValue EmitObjCKVCRefLValue(const ObjCImplicitSetterGetterRefExpr *E); LValue EmitObjCSuperExprLValue(const ObjCSuperExpr *E); LValue EmitStmtExprLValue(const StmtExpr *E); @@ -727,24 +857,28 @@ public: llvm::Value *Callee, const CallArgList &Args, const Decl *TargetDecl = 0); - + RValue EmitCall(llvm::Value *Callee, QualType FnType, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, const Decl *TargetDecl = 0); RValue EmitCallExpr(const CallExpr *E); - + + llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This, + const llvm::Type *Ty); RValue EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *Callee, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E); + RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E); RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const CXXMethodDecl *MD); + - RValue EmitBuiltinExpr(const FunctionDecl *FD, + RValue EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E); RValue EmitBlockCallExpr(const CallExpr *E); @@ -772,8 +906,9 @@ public: /// EmitReferenceBindingToExpr - Emits a reference binding to the passed in /// expression. Will emit a temporary variable if E is not an LValue. - RValue EmitReferenceBindingToExpr(const Expr* E, QualType DestType); - + RValue EmitReferenceBindingToExpr(const Expr* E, QualType DestType, + bool IsInitializer = false); + //===--------------------------------------------------------------------===// // Expression Emission //===--------------------------------------------------------------------===// @@ -782,7 +917,7 @@ public: /// EmitScalarExpr - Emit the computation of the specified expression of LLVM /// scalar type, returning the result. - llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign=false); + llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign = false); /// EmitScalarConversion - Emit a conversion from the specified type to the /// specified destination type, both of which are LLVM scalar types. @@ -800,7 +935,13 @@ public: /// aggregate type. The result is computed into DestPtr. Note that if /// DestPtr is null, the value of the aggregate expression is not needed. void EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest, - bool IgnoreResult = false); + bool IgnoreResult = false, bool IsInitializer = false, + bool RequiresGCollection = false); + + /// EmitGCMemmoveCollectable - Emit special API for structs with object + /// pointers. + void EmitGCMemmoveCollectable(llvm::Value *DestPtr, llvm::Value *SrcPtr, + QualType Ty); /// EmitComplexExpr - Emit the computation of the specified expression of /// complex type, returning the result. @@ -827,17 +968,33 @@ public: llvm::GlobalValue::LinkageTypes Linkage); - /// GenerateStaticCXXBlockVarDecl - Create the initializer for a C++ + /// EmitStaticCXXBlockVarDeclInit - Create the initializer for a C++ /// runtime initialized static block var decl. - void GenerateStaticCXXBlockVarDeclInit(const VarDecl &D, - llvm::GlobalVariable *GV); + void EmitStaticCXXBlockVarDeclInit(const VarDecl &D, + llvm::GlobalVariable *GV); + + /// EmitCXXGlobalVarDeclInit - Create the initializer for a C++ + /// variable with global storage. + void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr); + + /// EmitCXXGlobalDtorRegistration - Emits a call to register the global ptr + /// with the C++ runtime so that its destructor will be called at exit. + void EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor, + llvm::Constant *DeclPtr); + + /// GenerateCXXGlobalInitFunc - Generates code for initializing global + /// variables. + void GenerateCXXGlobalInitFunc(llvm::Function *Fn, + const VarDecl **Decls, + unsigned NumDecls); void EmitCXXConstructExpr(llvm::Value *Dest, const CXXConstructExpr *E); - + RValue EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, - llvm::Value *AggLoc = 0, - bool isAggLocVolatile = false); - + llvm::Value *AggLoc = 0, + bool IsAggLocVolatile = false, + bool IsInitializer = false); + //===--------------------------------------------------------------------===// // Internal Helpers //===--------------------------------------------------------------------===// @@ -860,10 +1017,6 @@ public: llvm::BasicBlock *FalseBlock); private: - /// EmitIndirectSwitches - Emit code for all of the switch - /// instructions in IndirectSwitches. - void EmitIndirectSwitches(); - void EmitReturnOfRValue(RValue RV, QualType Ty); /// ExpandTypeFromArgs - Reconstruct a structure of type \arg Ty @@ -882,7 +1035,7 @@ private: void ExpandTypeToArgs(QualType Ty, RValue Src, llvm::SmallVector<llvm::Value*, 16> &Args); - llvm::Value* EmitAsmInput(const AsmStmt &S, + llvm::Value* EmitAsmInput(const AsmStmt &S, const TargetInfo::ConstraintInfo &Info, const Expr *InputExpr, std::string &ConstraintStr); @@ -895,9 +1048,9 @@ private: /// EmitCallArg - Emit a single call argument. RValue EmitCallArg(const Expr *E, QualType ArgType); - + /// EmitCallArgs - Emit call arguments for a function. - /// The CallArgTypeInfo parameter is used for iterating over the known + /// The CallArgTypeInfo parameter is used for iterating over the known /// argument types of the function being called. template<typename T> void EmitCallArgs(CallArgList& Args, const T* CallArgTypeInfo, @@ -912,21 +1065,21 @@ private: QualType ArgType = *I; assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). - getTypePtr() == - getContext().getCanonicalType(Arg->getType()).getTypePtr() && + getTypePtr() == + getContext().getCanonicalType(Arg->getType()).getTypePtr() && "type mismatch in call argument!"); - - Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType), + + Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType), ArgType)); } - - // Either we've emitted all the call args, or we have a call to a + + // Either we've emitted all the call args, or we have a call to a // variadic function. - assert((Arg == ArgEnd || CallArgTypeInfo->isVariadic()) && + assert((Arg == ArgEnd || CallArgTypeInfo->isVariadic()) && "Extra arguments in non-variadic function!"); - + } - + // If we still have any arguments, emit them using the type of the argument. for (; Arg != ArgEnd; ++Arg) { QualType ArgType = Arg->getType(); @@ -935,7 +1088,7 @@ private: } } }; - + } // end namespace CodeGen } // end namespace clang diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index d88a37a45b233..36ad7f514ec81 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -39,8 +39,10 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CompileOptions &compileOpts, Diagnostic &diags) : BlockModule(C, M, TD, Types, *this), Context(C), Features(C.getLangOptions()), CompileOpts(compileOpts), TheModule(M), - TheTargetData(TD), Diags(diags), Types(C, M, TD), Runtime(0), - MemCpyFn(0), MemMoveFn(0), MemSetFn(0), CFConstantStringClassRef(0) { + TheTargetData(TD), Diags(diags), Types(C, M, TD), MangleCtx(C), + VtableInfo(*this), Runtime(0), + MemCpyFn(0), MemMoveFn(0), MemSetFn(0), CFConstantStringClassRef(0), + VMContext(M.getContext()) { if (!Features.ObjC1) Runtime = 0; @@ -61,6 +63,9 @@ CodeGenModule::~CodeGenModule() { } void CodeGenModule::Release() { + // We need to call this first because it can add deferred declarations. + EmitCXXGlobalInitFunc(); + EmitDeferred(); if (Runtime) if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction()) @@ -77,7 +82,7 @@ void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type, bool OmitOnError) { if (OmitOnError && getDiags().hasErrorOccurred()) return; - unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error, + unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error, "cannot compile this %0 yet"); std::string Msg = Type; getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID) @@ -90,13 +95,13 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type, bool OmitOnError) { if (OmitOnError && getDiags().hasErrorOccurred()) return; - unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error, + unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error, "cannot compile this %0 yet"); std::string Msg = Type; getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg; } -LangOptions::VisibilityMode +LangOptions::VisibilityMode CodeGenModule::getDeclVisibilityMode(const Decl *D) const { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) if (VD->getStorageClass() == VarDecl::PrivateExtern) @@ -105,7 +110,7 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const { if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) { switch (attr->getVisibility()) { default: assert(0 && "Unknown visibility!"); - case VisibilityAttr::DefaultVisibility: + case VisibilityAttr::DefaultVisibility: return LangOptions::Default; case VisibilityAttr::HiddenVisibility: return LangOptions::Hidden; @@ -117,7 +122,7 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const { return getLangOptions().getVisibilityMode(); } -void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, +void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const { // Internal definitions always have default visibility. if (GV->hasLocalLinkage()) { @@ -137,13 +142,13 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, } const char *CodeGenModule::getMangledName(const GlobalDecl &GD) { - const NamedDecl *ND = GD.getDecl(); - + const NamedDecl *ND = cast<NamedDecl>(GD.getDecl()); + if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND)) return getMangledCXXCtorName(D, GD.getCtorType()); if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND)) return getMangledCXXDtorName(D, GD.getDtorType()); - + return getMangledName(ND); } @@ -159,10 +164,10 @@ const char *CodeGenModule::getMangledName(const NamedDecl *ND) { assert(ND->getIdentifier() && "Attempt to mangle unnamed decl."); return ND->getNameAsCString(); } - + llvm::SmallString<256> Name; llvm::raw_svector_ostream Out(Name); - if (!mangleName(ND, Context, Out)) { + if (!mangleName(getMangleContext(), ND, Out)) { assert(ND->getIdentifier() && "Attempt to mangle unnamed decl."); return ND->getNameAsCString(); } @@ -174,7 +179,7 @@ const char *CodeGenModule::getMangledName(const NamedDecl *ND) { const char *CodeGenModule::UniqueMangledName(const char *NameStart, const char *NameEnd) { assert(*(NameEnd - 1) == '\0' && "Mangled name must be null terminated!"); - + return MangledNames.GetOrCreateValue(NameStart, NameEnd).getKeyData(); } @@ -195,32 +200,32 @@ void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) { void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { // Ctor function type is void()*. llvm::FunctionType* CtorFTy = - llvm::FunctionType::get(llvm::Type::VoidTy, + llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 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::StructType* CtorStructTy = + llvm::StructType::get(VMContext, llvm::Type::getInt32Ty(VMContext), 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::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), + 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, + new llvm::GlobalVariable(TheModule, AT, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(AT, Ctors), - GlobalName, - &TheModule); + GlobalName); } } @@ -233,67 +238,56 @@ void CodeGenModule::EmitAnnotations() { llvm::ConstantArray::get(llvm::ArrayType::get(Annotations[0]->getType(), Annotations.size()), Annotations); - llvm::GlobalValue *gv = - new llvm::GlobalVariable(Array->getType(), false, - llvm::GlobalValue::AppendingLinkage, Array, - "llvm.global.annotations", &TheModule); + llvm::GlobalValue *gv = + new llvm::GlobalVariable(TheModule, Array->getType(), false, + llvm::GlobalValue::AppendingLinkage, Array, + "llvm.global.annotations"); gv->setSection("llvm.metadata"); } static CodeGenModule::GVALinkage -GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD, +GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD, const LangOptions &Features) { + // Everything located semantically within an anonymous namespace is + // always internal. + if (FD->isInAnonymousNamespace()) + return CodeGenModule::GVA_Internal; + // The kind of external linkage this function will have, if it is not // inline or static. CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal; if (Context.getLangOptions().CPlusPlus && - (FD->getPrimaryTemplate() || FD->getInstantiatedFromMemberFunction()) && - !FD->isExplicitSpecialization()) + FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) External = CodeGenModule::GVA_TemplateInstantiation; - + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { // C++ member functions defined inside the class are always inline. if (MD->isInline() || !MD->isOutOfLine()) return CodeGenModule::GVA_CXXInline; - + return External; } - + // "static" functions get internal linkage. if (FD->getStorageClass() == FunctionDecl::Static) return CodeGenModule::GVA_Internal; if (!FD->isInline()) return External; - - // If the inline function explicitly has the GNU inline attribute on it, or if - // this is C89 mode, we use to GNU semantics. - if (!Features.C99 && !Features.CPlusPlus) { - // extern inline in GNU mode is like C99 inline. - if (FD->getStorageClass() == FunctionDecl::Extern) - return CodeGenModule::GVA_C99Inline; - // Normal inline is a strong symbol. - return CodeGenModule::GVA_StrongExternal; - } else if (FD->hasActiveGNUInlineAttribute(Context)) { - // GCC in C99 mode seems to use a different decision-making - // process for extern inline, which factors in previous - // declarations. - if (FD->isExternGNUInline(Context)) - return CodeGenModule::GVA_C99Inline; - // Normal inline is a strong symbol. - return External; - } - // The definition of inline changes based on the language. Note that we - // have already handled "static inline" above, with the GVA_Internal case. - if (Features.CPlusPlus) // inline and extern inline. - return CodeGenModule::GVA_CXXInline; - - assert(Features.C99 && "Must be in C99 mode if not in C89 or C++ mode"); - if (FD->isC99InlineDefinition()) + if (!Features.CPlusPlus || FD->hasAttr<GNUInlineAttr>()) { + // GNU or C99 inline semantics. Determine whether this symbol should be + // externally visible. + if (FD->isInlineDefinitionExternallyVisible()) + return External; + + // C99 inline semantics, where the symbol is not externally visible. return CodeGenModule::GVA_C99Inline; + } - return CodeGenModule::GVA_StrongExternal; + // C++ inline semantics + assert(Features.CPlusPlus && "Must be in C++ mode"); + return CodeGenModule::GVA_CXXInline; } /// SetFunctionDefinitionAttributes - Set attributes for a global. @@ -332,35 +326,35 @@ void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D, } void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D, - const CGFunctionInfo &Info, + const CGFunctionInfo &Info, llvm::Function *F) { + unsigned CallingConv; AttributeListType AttributeList; - ConstructAttributeList(Info, D, AttributeList); - + ConstructAttributeList(Info, D, AttributeList, CallingConv); F->setAttributes(llvm::AttrListPtr::get(AttributeList.begin(), - AttributeList.size())); - - // Set the appropriate calling convention for the Function. - if (D->hasAttr<FastCallAttr>()) - F->setCallingConv(llvm::CallingConv::X86_FastCall); - - if (D->hasAttr<StdCallAttr>()) - F->setCallingConv(llvm::CallingConv::X86_StdCall); + AttributeList.size())); + F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); } void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, llvm::Function *F) { if (!Features.Exceptions && !Features.ObjCNonFragileABI) - F->addFnAttr(llvm::Attribute::NoUnwind); + F->addFnAttr(llvm::Attribute::NoUnwind); if (D->hasAttr<AlwaysInlineAttr>()) F->addFnAttr(llvm::Attribute::AlwaysInline); - - if (D->hasAttr<NoinlineAttr>()) + + if (D->hasAttr<NoInlineAttr>()) F->addFnAttr(llvm::Attribute::NoInline); + + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) + F->setAlignment(AA->getAlignment()/8); + // C++ ABI requires 2-byte alignment for member functions. + if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D)) + F->setAlignment(2); } -void CodeGenModule::SetCommonAttributes(const Decl *D, +void CodeGenModule::SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV) { setGlobalVisibility(GV, D); @@ -387,19 +381,19 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, bool IsIncompleteFunction) { if (!IsIncompleteFunction) SetLLVMFunctionAttributes(FD, getTypes().getFunctionInfo(FD), F); - + // Only a few attributes are set on declarations; these may later be // overridden by a definition. - + if (FD->hasAttr<DLLImportAttr>()) { F->setLinkage(llvm::Function::DLLImportLinkage); - } else if (FD->hasAttr<WeakAttr>() || + } else if (FD->hasAttr<WeakAttr>() || FD->hasAttr<WeakImportAttr>()) { // "extern_weak" is overloaded in LLVM; we probably should have - // separate linkage types for this. + // separate linkage types for this. F->setLinkage(llvm::Function::ExternalWeakLinkage); } else { - F->setLinkage(llvm::Function::ExternalLinkage); + F->setLinkage(llvm::Function::ExternalLinkage); } if (const SectionAttr *SA = FD->getAttr<SectionAttr>()) @@ -407,39 +401,36 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, } void CodeGenModule::AddUsedGlobal(llvm::GlobalValue *GV) { - assert(!GV->isDeclaration() && + assert(!GV->isDeclaration() && "Only globals with definition can force usage."); LLVMUsed.push_back(GV); } void CodeGenModule::EmitLLVMUsed() { // Don't create llvm.used if there is no need. - // FIXME. Runtime indicates that there might be more 'used' symbols; but not - // necessariy. So, this test is not accurate for emptiness. - if (LLVMUsed.empty() && !Runtime) + if (LLVMUsed.empty()) return; - llvm::Type *i8PTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - + const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(VMContext); + // Convert LLVMUsed to what ConstantArray needs. std::vector<llvm::Constant*> UsedArray; UsedArray.resize(LLVMUsed.size()); for (unsigned i = 0, e = LLVMUsed.size(); i != e; ++i) { - UsedArray[i] = - llvm::ConstantExpr::getBitCast(cast<llvm::Constant>(&*LLVMUsed[i]), i8PTy); + UsedArray[i] = + llvm::ConstantExpr::getBitCast(cast<llvm::Constant>(&*LLVMUsed[i]), + i8PTy); } - - if (Runtime) - Runtime->MergeMetadataGlobals(UsedArray); + if (UsedArray.empty()) return; llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, UsedArray.size()); - - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(ATy, false, + + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(getModule(), ATy, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(ATy, UsedArray), - "llvm.used", &getModule()); + "llvm.used"); GV->setSection("llvm.metadata"); } @@ -458,59 +449,60 @@ void CodeGenModule::EmitDeferred() { // just ignore the deferred decl. llvm::GlobalValue *CGRef = GlobalDeclMap[getMangledName(D)]; assert(CGRef && "Deferred decl wasn't referenced?"); - + if (!CGRef->isDeclaration()) continue; - + // Otherwise, emit the definition and move on to the next one. EmitGlobalDefinition(D); } } -/// EmitAnnotateAttr - Generate the llvm::ConstantStruct which contains the +/// EmitAnnotateAttr - Generate the llvm::ConstantStruct which contains the /// annotation information for a given GlobalValue. The annotation struct is -/// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the -/// GlobalValue being annotated. The second field is the constant string -/// created from the AnnotateAttr's annotation. The third field is a constant +/// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the +/// GlobalValue being annotated. The second field is the constant string +/// created from the AnnotateAttr's annotation. The third field is a constant /// string containing the name of the translation unit. The fourth field is /// the line number in the file of the annotated value declaration. /// /// FIXME: this does not unique the annotation string constants, as llvm-gcc /// appears to. /// -llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, +llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, const AnnotateAttr *AA, unsigned LineNo) { llvm::Module *M = &getModule(); // get [N x i8] constants for the annotation string, and the filename string // which are the 2nd and 3rd elements of the global annotation structure. - const llvm::Type *SBP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - llvm::Constant *anno = llvm::ConstantArray::get(AA->getAnnotation(), true); - llvm::Constant *unit = llvm::ConstantArray::get(M->getModuleIdentifier(), + const llvm::Type *SBP = llvm::Type::getInt8PtrTy(VMContext); + llvm::Constant *anno = llvm::ConstantArray::get(VMContext, + AA->getAnnotation(), true); + llvm::Constant *unit = llvm::ConstantArray::get(VMContext, + M->getModuleIdentifier(), true); // Get the two global values corresponding to the ConstantArrays we just // created to hold the bytes of the strings. - const char *StringPrefix = getContext().Target.getStringSymbolPrefix(true); - llvm::GlobalValue *annoGV = - new llvm::GlobalVariable(anno->getType(), false, - llvm::GlobalValue::InternalLinkage, anno, - GV->getName() + StringPrefix, M); + llvm::GlobalValue *annoGV = + new llvm::GlobalVariable(*M, anno->getType(), false, + llvm::GlobalValue::PrivateLinkage, anno, + GV->getName()); // translation unit name string, emitted into the llvm.metadata section. llvm::GlobalValue *unitGV = - new llvm::GlobalVariable(unit->getType(), false, - llvm::GlobalValue::InternalLinkage, unit, - StringPrefix, M); + new llvm::GlobalVariable(*M, unit->getType(), false, + llvm::GlobalValue::PrivateLinkage, unit, + ".str"); // Create the ConstantStruct for the global annotation. llvm::Constant *Fields[4] = { llvm::ConstantExpr::getBitCast(GV, SBP), llvm::ConstantExpr::getBitCast(annoGV, SBP), llvm::ConstantExpr::getBitCast(unitGV, SBP), - llvm::ConstantInt::get(llvm::Type::Int32Ty, LineNo) + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), LineNo) }; - return llvm::ConstantStruct::get(Fields, 4, false); + return llvm::ConstantStruct::get(VMContext, Fields, 4, false); } bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { @@ -521,12 +513,12 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) { // Constructors and destructors should never be deferred. - if (FD->hasAttr<ConstructorAttr>() || + if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) return false; GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features); - + // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. if (Linkage == GVA_Internal || Linkage == GVA_C99Inline || @@ -534,16 +526,27 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { return true; return false; } - + const VarDecl *VD = cast<VarDecl>(Global); assert(VD->isFileVarDecl() && "Invalid decl"); + // We never want to defer structs that have non-trivial constructors or + // destructors. + + // FIXME: Handle references. + if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()) + return false; + } + } + return VD->getStorageClass() == VarDecl::Static; } void CodeGenModule::EmitGlobal(GlobalDecl GD) { - const ValueDecl *Global = GD.getDecl(); - + const ValueDecl *Global = cast<ValueDecl>(GD.getDecl()); + // If this is an alias definition (which otherwise looks like a declaration) // emit it now. if (Global->hasAttr<AliasAttr>()) @@ -560,8 +563,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // In C++, if this is marked "extern", defer code generation. if (getLangOptions().CPlusPlus && !VD->getInit() && - (VD->getStorageClass() == VarDecl::Extern || - VD->isExternC(getContext()))) + (VD->getStorageClass() == VarDecl::Extern || + VD->isExternC())) return; // In C, if this isn't a definition, defer code generation. @@ -591,8 +594,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { } void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) { - const ValueDecl *D = GD.getDecl(); - + const ValueDecl *D = cast<ValueDecl>(GD.getDecl()); + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) EmitCXXConstructor(CD, GD.getCtorType()); else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) @@ -621,16 +624,16 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, if (Entry) { if (Entry->getType()->getElementType() == Ty) return Entry; - + // Make sure the result is of the correct type. const llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); return llvm::ConstantExpr::getBitCast(Entry, PTy); } - + // This is the first use or definition of a mangled name. If there is a // deferred decl with this name, remember that we need to emit it at the end // of the file. - llvm::DenseMap<const char*, GlobalDecl>::iterator DDI = + llvm::DenseMap<const char*, GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName); if (DDI != DeferredDecls.end()) { // Move the potentially referenced deferred decl to the DeferredDeclsToEmit @@ -643,18 +646,33 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // top-level declarations. if (FD->isThisDeclarationADefinition() && MayDeferGeneration(FD)) DeferredDeclsToEmit.push_back(D); + // A called constructor which has no definition or declaration need be + // synthesized. + else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { + const CXXRecordDecl *ClassDecl = + cast<CXXRecordDecl>(CD->getDeclContext()); + if (CD->isCopyConstructor(getContext())) + DeferredCopyConstructorToEmit(D); + else if (!ClassDecl->hasUserDeclaredConstructor()) + DeferredDeclsToEmit.push_back(D); + } + else if (isa<CXXDestructorDecl>(FD)) + DeferredDestructorToEmit(D); + else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) + if (MD->isCopyAssignment()) + DeferredCopyAssignmentToEmit(D); } - + // This function doesn't have a complete type (for example, the return // type is an incomplete struct). Use a fake type instead, and make // sure not to try to set attributes. bool IsIncompleteFunction = false; if (!isa<llvm::FunctionType>(Ty)) { - Ty = llvm::FunctionType::get(llvm::Type::VoidTy, + Ty = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), std::vector<const llvm::Type*>(), false); IsIncompleteFunction = true; } - llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), + llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), llvm::Function::ExternalLinkage, "", &getModule()); F->setName(MangledName); @@ -665,6 +683,126 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, return F; } +/// Defer definition of copy constructor(s) which need be implicitly defined. +void CodeGenModule::DeferredCopyConstructorToEmit(GlobalDecl CopyCtorDecl) { + const CXXConstructorDecl *CD = + cast<CXXConstructorDecl>(CopyCtorDecl.getDecl()); + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); + if (ClassDecl->hasTrivialCopyConstructor() || + ClassDecl->hasUserDeclaredCopyConstructor()) + return; + + // First make sure all direct base classes and virtual bases and non-static + // data mebers which need to have their copy constructors implicitly defined + // are defined. 12.8.p7 + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(Context, 0)) + GetAddrOfCXXConstructor(BaseCopyCtor, Ctor_Complete); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = Context.getCanonicalType((*Field)->getType()); + if (const ArrayType *Array = Context.getAsArrayType(FieldType)) + FieldType = Array->getElementType(); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + if ((*Field)->isAnonymousStructOrUnion()) + continue; + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + if (CXXConstructorDecl *FieldCopyCtor = + FieldClassDecl->getCopyConstructor(Context, 0)) + GetAddrOfCXXConstructor(FieldCopyCtor, Ctor_Complete); + } + } + DeferredDeclsToEmit.push_back(CopyCtorDecl); +} + +/// Defer definition of copy assignments which need be implicitly defined. +void CodeGenModule::DeferredCopyAssignmentToEmit(GlobalDecl CopyAssignDecl) { + const CXXMethodDecl *CD = cast<CXXMethodDecl>(CopyAssignDecl.getDecl()); + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); + + if (ClassDecl->hasTrivialCopyAssignment() || + ClassDecl->hasUserDeclaredCopyAssignment()) + return; + + // First make sure all direct base classes and virtual bases and non-static + // data mebers which need to have their copy assignments implicitly defined + // are defined. 12.8.p12 + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + const CXXMethodDecl *MD = 0; + if (!BaseClassDecl->hasTrivialCopyAssignment() && + !BaseClassDecl->hasUserDeclaredCopyAssignment() && + BaseClassDecl->hasConstCopyAssignment(getContext(), MD)) + GetAddrOfFunction(MD, 0); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = Context.getCanonicalType((*Field)->getType()); + if (const ArrayType *Array = Context.getAsArrayType(FieldType)) + FieldType = Array->getElementType(); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + if ((*Field)->isAnonymousStructOrUnion()) + continue; + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + const CXXMethodDecl *MD = 0; + if (!FieldClassDecl->hasTrivialCopyAssignment() && + !FieldClassDecl->hasUserDeclaredCopyAssignment() && + FieldClassDecl->hasConstCopyAssignment(getContext(), MD)) + GetAddrOfFunction(MD, 0); + } + } + DeferredDeclsToEmit.push_back(CopyAssignDecl); +} + +void CodeGenModule::DeferredDestructorToEmit(GlobalDecl DtorDecl) { + const CXXDestructorDecl *DD = cast<CXXDestructorDecl>(DtorDecl.getDecl()); + const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext()); + if (ClassDecl->hasTrivialDestructor() || + ClassDecl->hasUserDeclaredDestructor()) + return; + + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (const CXXDestructorDecl *BaseDtor = + BaseClassDecl->getDestructor(Context)) + GetAddrOfCXXDestructor(BaseDtor, Dtor_Complete); + } + + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + QualType FieldType = Context.getCanonicalType((*Field)->getType()); + if (const ArrayType *Array = Context.getAsArrayType(FieldType)) + FieldType = Array->getElementType(); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + if ((*Field)->isAnonymousStructOrUnion()) + continue; + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + if (const CXXDestructorDecl *FieldDtor = + FieldClassDecl->getDestructor(Context)) + GetAddrOfCXXDestructor(FieldDtor, Dtor_Complete); + } + } + DeferredDeclsToEmit.push_back(DtorDecl); +} + + /// GetAddrOfFunction - Return the address of the given function. If Ty is /// non-null, then this function will use the specified type if it has to /// create it (this occurs when we see a definition of the function). @@ -672,8 +810,8 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, const llvm::Type *Ty) { // If there was no specific requested type, just convert it now. if (!Ty) - Ty = getTypes().ConvertType(GD.getDecl()->getType()); - return GetOrCreateLLVMFunction(getMangledName(GD.getDecl()), Ty, GD); + Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType()); + return GetOrCreateLLVMFunction(getMangledName(GD), Ty, GD); } /// CreateRuntimeFunction - Create a new runtime function with the specified @@ -701,15 +839,15 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, if (Entry) { if (Entry->getType() == Ty) return Entry; - + // Make sure the result is of the correct type. return llvm::ConstantExpr::getBitCast(Entry, Ty); } - + // This is the first use or definition of a mangled name. If there is a // deferred decl with this name, remember that we need to emit it at the end // of the file. - llvm::DenseMap<const char*, GlobalDecl>::iterator DDI = + llvm::DenseMap<const char*, GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName); if (DDI != DeferredDecls.end()) { // Move the potentially referenced deferred decl to the DeferredDeclsToEmit @@ -717,11 +855,11 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, DeferredDeclsToEmit.push_back(DDI->second); DeferredDecls.erase(DDI); } - - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(Ty->getElementType(), false, + + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(getModule(), Ty->getElementType(), false, llvm::GlobalValue::ExternalLinkage, - 0, "", &getModule(), + 0, "", 0, false, Ty->getAddressSpace()); GV->setName(MangledName); @@ -735,13 +873,13 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, if (D->getStorageClass() == VarDecl::PrivateExtern) GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - if (D->hasAttr<WeakAttr>() || + if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>()) GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); GV->setThreadLocal(D->isThreadSpecified()); } - + return Entry = GV; } @@ -756,8 +894,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, QualType ASTTy = D->getType(); if (Ty == 0) Ty = getTypes().ConvertTypeForMem(ASTTy); - - const llvm::PointerType *PTy = + + const llvm::PointerType *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace()); return GetOrCreateLLVMGlobal(getMangledName(D), PTy, D); } @@ -781,7 +919,7 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { // later. const char *MangledName = getMangledName(D); if (GlobalDeclMap.count(MangledName) == 0) { - DeferredDecls[MangledName] = GlobalDecl(D); + DeferredDecls[MangledName] = D; return; } } @@ -793,7 +931,7 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::Constant *Init = 0; QualType ASTTy = D->getType(); - + if (D->getInit() == 0) { // This is a tentative definition; tentative definitions are // implicitly initialized with { 0 }. @@ -805,28 +943,36 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // exists. A use may still exists, however, so we still may need // to do a RAUW. assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type"); - Init = llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(ASTTy)); + Init = EmitNullConstant(D->getType()); } else { Init = EmitConstantExpr(D->getInit(), D->getType()); + if (!Init) { - ErrorUnsupported(D, "static initializer"); QualType T = D->getInit()->getType(); - Init = llvm::UndefValue::get(getTypes().ConvertType(T)); + if (getLangOptions().CPlusPlus) { + CXXGlobalInits.push_back(D); + Init = EmitNullConstant(T); + } else { + ErrorUnsupported(D, "static initializer"); + Init = llvm::UndefValue::get(getTypes().ConvertType(T)); + } } } const llvm::Type* InitType = Init->getType(); llvm::Constant *Entry = GetAddrOfGlobalVar(D, InitType); - + // Strip off a bitcast if we got one back. if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) { - assert(CE->getOpcode() == llvm::Instruction::BitCast); + assert(CE->getOpcode() == llvm::Instruction::BitCast || + // all zero index gep. + CE->getOpcode() == llvm::Instruction::GetElementPtr); Entry = CE->getOperand(0); } - + // Entry is now either a Function or GlobalVariable. llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Entry); - + // We have a definition after a declaration with the wrong type. // We must make a new GlobalVariable* and update everything that used OldGV // (a declaration or tentative definition) with the new GlobalVariable* @@ -839,7 +985,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { if (GV == 0 || GV->getType()->getElementType() != InitType || GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) { - + // Remove the old entry from GlobalDeclMap so that we'll create a new one. GlobalDeclMap.erase(getMangledName(D)); @@ -848,7 +994,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->takeName(cast<llvm::GlobalValue>(Entry)); // Replace all uses of the old global with the new global - llvm::Constant *NewPtrForOldDecl = + llvm::Constant *NewPtrForOldDecl = llvm::ConstantExpr::getBitCast(GV, Entry->getType()); Entry->replaceAllUsesWith(NewPtrForOldDecl); @@ -863,22 +1009,38 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { } GV->setInitializer(Init); - GV->setConstant(D->getType().isConstant(Context)); + + // If it is safe to mark the global 'constant', do so now. + GV->setConstant(false); + if (D->getType().isConstant(Context)) { + // FIXME: In C++, if the variable has a non-trivial ctor/dtor or any mutable + // members, it cannot be declared "LLVM const". + GV->setConstant(true); + } + GV->setAlignment(getContext().getDeclAlignInBytes(D)); // Set the llvm linkage type as appropriate. - if (D->getStorageClass() == VarDecl::Static) + if (D->isInAnonymousNamespace()) + GV->setLinkage(llvm::Function::InternalLinkage); + else if (D->getStorageClass() == VarDecl::Static) GV->setLinkage(llvm::Function::InternalLinkage); else if (D->hasAttr<DLLImportAttr>()) GV->setLinkage(llvm::Function::DLLImportLinkage); else if (D->hasAttr<DLLExportAttr>()) GV->setLinkage(llvm::Function::DLLExportLinkage); - else if (D->hasAttr<WeakAttr>()) - GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); - else if (!CompileOpts.NoCommon && - (!D->hasExternalStorage() && !D->getInit())) + else if (D->hasAttr<WeakAttr>()) { + if (GV->isConstant()) + GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage); + else + GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); + } else if (!CompileOpts.NoCommon && + !D->hasExternalStorage() && !D->getInit() && + !D->getAttr<SectionAttr>()) { GV->setLinkage(llvm::GlobalVariable::CommonLinkage); - else + // common vars aren't constant even if declared const. + GV->setConstant(false); + } else GV->setLinkage(llvm::GlobalVariable::ExternalLinkage); SetCommonAttributes(D, GV); @@ -904,7 +1066,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, // If we're redefining a global as a function, don't transform it. llvm::Function *OldFn = dyn_cast<llvm::Function>(Old); if (OldFn == 0) return; - + const llvm::Type *NewRetTy = NewFn->getReturnType(); llvm::SmallVector<llvm::Value*, 4> ArgList; @@ -914,7 +1076,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, unsigned OpNo = UI.getOperandNo(); llvm::CallInst *CI = dyn_cast<llvm::CallInst>(*UI++); if (!CI || OpNo != 0) continue; - + // If the return types don't match exactly, and if the call isn't dead, then // we can't transform this call. if (CI->getType() != NewRetTy && !CI->use_empty()) @@ -935,21 +1097,26 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, } if (DontTransform) continue; - + // Okay, we can transform this. Create the new call instruction and copy // over the required information. ArgList.append(CI->op_begin()+1, CI->op_begin()+1+ArgNo); llvm::CallInst *NewCall = llvm::CallInst::Create(NewFn, ArgList.begin(), ArgList.end(), "", CI); ArgList.clear(); - if (NewCall->getType() != llvm::Type::VoidTy) + if (!NewCall->getType()->isVoidTy()) NewCall->takeName(CI); - NewCall->setCallingConv(CI->getCallingConv()); NewCall->setAttributes(CI->getAttributes()); + NewCall->setCallingConv(CI->getCallingConv()); // Finally, remove the old call, replacing any uses with the new one. if (!CI->use_empty()) CI->replaceAllUsesWith(NewCall); + + // Copy any custom metadata attached with CI. + llvm::MetadataContext &TheMetadata = CI->getContext().getMetadata(); + TheMetadata.copyMD(CI, NewCall); + CI->eraseFromParent(); } } @@ -958,21 +1125,21 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { const llvm::FunctionType *Ty; const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl()); - + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - bool isVariadic = D->getType()->getAsFunctionProtoType()->isVariadic(); - + bool isVariadic = D->getType()->getAs<FunctionProtoType>()->isVariadic(); + Ty = getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), isVariadic); } else { Ty = cast<llvm::FunctionType>(getTypes().ConvertType(D->getType())); - + // As a special case, make sure that definitions of K&R function // "type foo()" aren't declared as varargs (which forces the backend // to do unnecessary work). if (D->getType()->isFunctionNoProtoType()) { assert(Ty->isVarArg() && "Didn't lower type as expected"); - // Due to stret, the lowered function could have arguments. - // Just create the same type as was lowered by ConvertType + // Due to stret, the lowered function could have arguments. + // Just create the same type as was lowered by ConvertType // but strip off the varargs bit. std::vector<const llvm::Type*> Args(Ty->param_begin(), Ty->param_end()); Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false); @@ -981,17 +1148,17 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { // Get or create the prototype for the function. llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); - + // Strip off a bitcast if we got one back. if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) { assert(CE->getOpcode() == llvm::Instruction::BitCast); Entry = CE->getOperand(0); } - - + + if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != Ty) { llvm::GlobalValue *OldFn = cast<llvm::GlobalValue>(Entry); - + // If the types mismatch then we have to rewrite the definition. assert(OldFn->isDeclaration() && "Shouldn't replace non-declaration"); @@ -1007,7 +1174,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { GlobalDeclMap.erase(getMangledName(D)); llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty)); NewFn->takeName(OldFn); - + // If this is an implementation of a function without a prototype, try to // replace any existing uses of the function (which may be calls) with uses // of the new function @@ -1015,27 +1182,27 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { ReplaceUsesOfNonProtoTypeWithRealFunction(OldFn, NewFn); OldFn->removeDeadConstantUsers(); } - + // Replace uses of F with the Function we will endow with a body. if (!Entry->use_empty()) { - llvm::Constant *NewPtrForOldDecl = + llvm::Constant *NewPtrForOldDecl = llvm::ConstantExpr::getBitCast(NewFn, Entry->getType()); Entry->replaceAllUsesWith(NewPtrForOldDecl); } - + // Ok, delete the old function now, which is dead. OldFn->eraseFromParent(); - + Entry = NewFn; } - + llvm::Function *Fn = cast<llvm::Function>(Entry); CodeGenFunction(*this).GenerateCode(D, Fn); SetFunctionDefinitionAttributes(D, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); - + if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) AddGlobalCtor(Fn, CA->getPriority()); if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) @@ -1047,7 +1214,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { assert(AA && "Not an alias?"); const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); - + // Unique the name through the identifier table. const char *AliaseeName = AA->getAliasee().c_str(); AliaseeName = getContext().Idents.get(AliaseeName).getName(); @@ -1062,22 +1229,22 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { llvm::PointerType::getUnqual(DeclTy), 0); // Create the new alias itself, but don't set a name yet. - llvm::GlobalValue *GA = + llvm::GlobalValue *GA = new llvm::GlobalAlias(Aliasee->getType(), llvm::Function::ExternalLinkage, "", Aliasee, &getModule()); - + // See if there is already something with the alias' name in the module. const char *MangledName = getMangledName(D); llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; - + if (Entry && !Entry->isDeclaration()) { // If there is a definition in the module, then it wins over the alias. // This is dubious, but allow it to be safe. Just ignore the alias. GA->eraseFromParent(); return; } - + if (Entry) { // If there is a declaration in the module, then we had an extern followed // by the alias, as in: @@ -1086,12 +1253,12 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { // int test6() __attribute__((alias("test7"))); // // Remove it and replace uses of it with the alias. - + Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GA, Entry->getType())); Entry->eraseFromParent(); } - + // Now we know that there is no conflict, set the name. Entry = GA; GA->setName(MangledName); @@ -1107,7 +1274,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { } else { GA->setLinkage(llvm::Function::DLLExportLinkage); } - } else if (D->hasAttr<WeakAttr>() || + } else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>()) { GA->setLinkage(llvm::Function::WeakAnyLinkage); } @@ -1117,28 +1284,28 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { /// getBuiltinLibFunction - Given a builtin id for a function like /// "__builtin_fabsf", return a Function* for "fabsf". -llvm::Value *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) { +llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD, + unsigned BuiltinID) { assert((Context.BuiltinInfo.isLibFunction(BuiltinID) || - Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) && + Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) && "isn't a lib fn"); - + // Get the name, skip over the __builtin_ prefix (if necessary). const char *Name = Context.BuiltinInfo.GetName(BuiltinID); if (Context.BuiltinInfo.isLibFunction(BuiltinID)) Name += 10; - + // Get the type for the builtin. ASTContext::GetBuiltinTypeError Error; QualType Type = Context.GetBuiltinType(BuiltinID, Error); assert(Error == ASTContext::GE_None && "Can't get builtin type"); - const llvm::FunctionType *Ty = + const llvm::FunctionType *Ty = cast<llvm::FunctionType>(getTypes().ConvertType(Type)); // Unique the name through the identifier table. Name = getContext().Idents.get(Name).getName(); - // FIXME: param attributes for sext/zext etc. - return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl()); + return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD)); } llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys, @@ -1149,186 +1316,167 @@ llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys, llvm::Function *CodeGenModule::getMemCpyFn() { if (MemCpyFn) return MemCpyFn; - const llvm::Type *IntPtr = TheTargetData.getIntPtrType(); + const llvm::Type *IntPtr = TheTargetData.getIntPtrType(VMContext); return MemCpyFn = getIntrinsic(llvm::Intrinsic::memcpy, &IntPtr, 1); } llvm::Function *CodeGenModule::getMemMoveFn() { if (MemMoveFn) return MemMoveFn; - const llvm::Type *IntPtr = TheTargetData.getIntPtrType(); + const llvm::Type *IntPtr = TheTargetData.getIntPtrType(VMContext); return MemMoveFn = getIntrinsic(llvm::Intrinsic::memmove, &IntPtr, 1); } llvm::Function *CodeGenModule::getMemSetFn() { if (MemSetFn) return MemSetFn; - const llvm::Type *IntPtr = TheTargetData.getIntPtrType(); + const llvm::Type *IntPtr = TheTargetData.getIntPtrType(VMContext); return MemSetFn = getIntrinsic(llvm::Intrinsic::memset, &IntPtr, 1); } -static void appendFieldAndPadding(CodeGenModule &CGM, - std::vector<llvm::Constant*>& Fields, - FieldDecl *FieldD, FieldDecl *NextFieldD, - llvm::Constant* Field, - RecordDecl* RD, const llvm::StructType *STy) { - // Append the field. - Fields.push_back(Field); - - int StructFieldNo = CGM.getTypes().getLLVMFieldNo(FieldD); - - int NextStructFieldNo; - if (!NextFieldD) { - NextStructFieldNo = STy->getNumElements(); - } else { - NextStructFieldNo = CGM.getTypes().getLLVMFieldNo(NextFieldD); +static llvm::StringMapEntry<llvm::Constant*> & +GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map, + const StringLiteral *Literal, + bool TargetIsLSB, + bool &IsUTF16, + unsigned &StringLength) { + unsigned NumBytes = Literal->getByteLength(); + + // Check for simple case. + if (!Literal->containsNonAsciiOrNull()) { + StringLength = NumBytes; + return Map.GetOrCreateValue(llvm::StringRef(Literal->getStrData(), + StringLength)); } - - // Append padding - for (int i = StructFieldNo + 1; i < NextStructFieldNo; i++) { - llvm::Constant *C = - llvm::Constant::getNullValue(STy->getElementType(StructFieldNo + 1)); - - Fields.push_back(C); + + // Otherwise, convert the UTF8 literals into a byte string. + llvm::SmallVector<UTF16, 128> ToBuf(NumBytes); + const UTF8 *FromPtr = (UTF8 *)Literal->getStrData(); + UTF16 *ToPtr = &ToBuf[0]; + + ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, + &ToPtr, ToPtr + NumBytes, + strictConversion); + + // Check for conversion failure. + if (Result != conversionOK) { + // FIXME: Have Sema::CheckObjCString() validate the UTF-8 string and remove + // this duplicate code. + assert(Result == sourceIllegal && "UTF-8 to UTF-16 conversion failed"); + StringLength = NumBytes; + return Map.GetOrCreateValue(llvm::StringRef(Literal->getStrData(), + StringLength)); } + + // ConvertUTF8toUTF16 returns the length in ToPtr. + StringLength = ToPtr - &ToBuf[0]; + + // Render the UTF-16 string into a byte array and convert to the target byte + // order. + // + // FIXME: This isn't something we should need to do here. + llvm::SmallString<128> AsBytes; + AsBytes.reserve(StringLength * 2); + for (unsigned i = 0; i != StringLength; ++i) { + unsigned short Val = ToBuf[i]; + if (TargetIsLSB) { + AsBytes.push_back(Val & 0xFF); + AsBytes.push_back(Val >> 8); + } else { + AsBytes.push_back(Val >> 8); + AsBytes.push_back(Val & 0xFF); + } + } + // Append one extra null character, the second is automatically added by our + // caller. + AsBytes.push_back(0); + + IsUTF16 = true; + return Map.GetOrCreateValue(llvm::StringRef(AsBytes.data(), AsBytes.size())); } -llvm::Constant *CodeGenModule:: -GetAddrOfConstantCFString(const StringLiteral *Literal) { - std::string str; +llvm::Constant * +CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { unsigned StringLength = 0; - bool isUTF16 = false; - if (Literal->containsNonAsciiOrNull()) { - // Convert from UTF-8 to UTF-16. - llvm::SmallVector<UTF16, 128> ToBuf(Literal->getByteLength()); - const UTF8 *FromPtr = (UTF8 *)Literal->getStrData(); - UTF16 *ToPtr = &ToBuf[0]; - - ConversionResult Result; - Result = ConvertUTF8toUTF16(&FromPtr, FromPtr+Literal->getByteLength(), - &ToPtr, ToPtr+Literal->getByteLength(), - strictConversion); - if (Result == conversionOK) { - // FIXME: Storing UTF-16 in a C string is a hack to test Unicode strings - // without doing more surgery to this routine. Since we aren't explicitly - // checking for endianness here, it's also a bug (when generating code for - // a target that doesn't match the host endianness). Modeling this as an - // i16 array is likely the cleanest solution. - StringLength = ToPtr-&ToBuf[0]; - str.assign((char *)&ToBuf[0], StringLength*2);// Twice as many UTF8 chars. - isUTF16 = true; - } else if (Result == sourceIllegal) { - // FIXME: Have Sema::CheckObjCString() validate the UTF-8 string. - str.assign(Literal->getStrData(), Literal->getByteLength()); - StringLength = str.length(); - } else - assert(Result == conversionOK && "UTF-8 to UTF-16 conversion failed"); - - } else { - str.assign(Literal->getStrData(), Literal->getByteLength()); - StringLength = str.length(); - } - llvm::StringMapEntry<llvm::Constant *> &Entry = - CFConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]); - + llvm::StringMapEntry<llvm::Constant*> &Entry = + GetConstantCFStringEntry(CFConstantStringMap, Literal, + getTargetData().isLittleEndian(), + isUTF16, StringLength); + if (llvm::Constant *C = Entry.getValue()) return C; - - llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty); + + llvm::Constant *Zero = + llvm::Constant::getNullValue(llvm::Type::getInt32Ty(VMContext)); llvm::Constant *Zeros[] = { Zero, Zero }; - + + // If we don't already have it, get __CFConstantStringClassReference. if (!CFConstantStringClassRef) { const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); Ty = llvm::ArrayType::get(Ty, 0); - - // FIXME: This is fairly broken if __CFConstantStringClassReference is - // already defined, in that it will get renamed and the user will most - // likely see an opaque error message. This is a general issue with relying - // on particular names. - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(Ty, false, - llvm::GlobalVariable::ExternalLinkage, 0, - "__CFConstantStringClassReference", - &getModule()); - + llvm::Constant *GV = CreateRuntimeVariable(Ty, + "__CFConstantStringClassReference"); // Decay array -> ptr CFConstantStringClassRef = llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2); } - + QualType CFTy = getContext().getCFConstantStringType(); - RecordDecl *CFRD = CFTy->getAsRecordType()->getDecl(); - const llvm::StructType *STy = + const llvm::StructType *STy = cast<llvm::StructType>(getTypes().ConvertType(CFTy)); - std::vector<llvm::Constant*> Fields; - RecordDecl::field_iterator Field = CFRD->field_begin(); + std::vector<llvm::Constant*> Fields(4); // Class pointer. - FieldDecl *CurField = *Field++; - FieldDecl *NextField = *Field++; - appendFieldAndPadding(*this, Fields, CurField, NextField, - CFConstantStringClassRef, CFRD, STy); - + Fields[0] = CFConstantStringClassRef; + // Flags. - CurField = NextField; - NextField = *Field++; const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy); - appendFieldAndPadding(*this, Fields, CurField, NextField, - isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0) - : llvm::ConstantInt::get(Ty, 0x07C8), - CFRD, STy); - + Fields[1] = isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0) : + llvm::ConstantInt::get(Ty, 0x07C8); + // String pointer. - CurField = NextField; - NextField = *Field++; - llvm::Constant *C = llvm::ConstantArray::get(str); + llvm::Constant *C = llvm::ConstantArray::get(VMContext, Entry.getKey().str()); - const char *Sect, *Prefix; + const char *Sect = 0; + llvm::GlobalValue::LinkageTypes Linkage; bool isConstant; if (isUTF16) { - Prefix = getContext().Target.getUnicodeStringSymbolPrefix(); Sect = getContext().Target.getUnicodeStringSection(); - // FIXME: Why does GCC not set constant here? - isConstant = false; - } else { - Prefix = getContext().Target.getStringSymbolPrefix(true); - Sect = getContext().Target.getCFStringDataSection(); - // FIXME: -fwritable-strings should probably affect this, but we - // are following gcc here. + // FIXME: why do utf strings get "_" labels instead of "L" labels? + Linkage = llvm::GlobalValue::InternalLinkage; + // Note: -fwritable-strings doesn't make unicode CFStrings writable, but + // does make plain ascii ones writable. isConstant = true; + } else { + Linkage = llvm::GlobalValue::PrivateLinkage; + isConstant = !Features.WritableStrings; } - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(C->getType(), isConstant, - llvm::GlobalValue::InternalLinkage, - C, Prefix, &getModule()); + + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C, + ".str"); if (Sect) GV->setSection(Sect); if (isUTF16) { unsigned Align = getContext().getTypeAlign(getContext().ShortTy)/8; - GV->setAlignment(Align); + GV->setAlignment(Align); } - appendFieldAndPadding(*this, Fields, CurField, NextField, - llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2), - CFRD, STy); - + Fields[2] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2); + // String length. - CurField = NextField; - NextField = 0; Ty = getTypes().ConvertType(getContext().LongTy); - appendFieldAndPadding(*this, Fields, CurField, NextField, - llvm::ConstantInt::get(Ty, StringLength), CFRD, STy); - + Fields[3] = llvm::ConstantInt::get(Ty, StringLength); + // The struct. C = llvm::ConstantStruct::get(STy, Fields); - GV = new llvm::GlobalVariable(C->getType(), true, - llvm::GlobalVariable::InternalLinkage, C, - getContext().Target.getCFStringSymbolPrefix(), - &getModule()); + GV = new llvm::GlobalVariable(getModule(), C->getType(), true, + llvm::GlobalVariable::PrivateLinkage, C, + "_unnamed_cfstring_"); if (const char *Sect = getContext().Target.getCFStringSection()) GV->setSection(Sect); Entry.setValue(GV); - + return GV; } @@ -1341,16 +1489,16 @@ std::string CodeGenModule::GetStringForStringLiteral(const StringLiteral *E) { const ConstantArrayType *CAT = getContext().getAsConstantArrayType(E->getType()); assert(CAT && "String isn't pointer or array!"); - + // Resize the string to the right size. std::string Str(StrData, StrData+Len); uint64_t RealLen = CAT->getSize().getZExtValue(); - + if (E->isWide()) RealLen *= getContext().Target.getWCharWidth()/8; - + Str.resize(RealLen, '\0'); - + return Str; } @@ -1374,17 +1522,18 @@ CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) { /// GenerateWritableString -- Creates storage for a string literal. -static llvm::Constant *GenerateStringLiteral(const std::string &str, +static llvm::Constant *GenerateStringLiteral(const std::string &str, bool constant, CodeGenModule &CGM, const char *GlobalName) { // Create Constant for this string literal. Don't add a '\0'. - llvm::Constant *C = llvm::ConstantArray::get(str, false); - + llvm::Constant *C = + llvm::ConstantArray::get(CGM.getLLVMContext(), str, false); + // Create a global variable for this string - return new llvm::GlobalVariable(C->getType(), constant, - llvm::GlobalValue::InternalLinkage, - C, GlobalName, &CGM.getModule()); + return new llvm::GlobalVariable(CGM.getModule(), C->getType(), constant, + llvm::GlobalValue::PrivateLinkage, + C, GlobalName); } /// GetAddrOfConstantString - Returns a pointer to a character array @@ -1401,14 +1550,14 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str, // Get the default prefix if a name wasn't specified. if (!GlobalName) - GlobalName = getContext().Target.getStringSymbolPrefix(IsConstant); + GlobalName = ".str"; // Don't share any string literals if strings aren't constant. if (!IsConstant) return GenerateStringLiteral(str, false, *this, GlobalName); - - llvm::StringMapEntry<llvm::Constant *> &Entry = - ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]); + + llvm::StringMapEntry<llvm::Constant *> &Entry = + ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]); if (Entry.getValue()) return Entry.getValue(); @@ -1429,12 +1578,12 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str, /// EmitObjCPropertyImplementations - Emit information for synthesized /// properties for an implementation. -void CodeGenModule::EmitObjCPropertyImplementations(const +void CodeGenModule::EmitObjCPropertyImplementations(const ObjCImplementationDecl *D) { - for (ObjCImplementationDecl::propimpl_iterator + for (ObjCImplementationDecl::propimpl_iterator i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; - + // Dynamic is just for type-checking. if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { ObjCPropertyDecl *PD = PID->getPropertyDecl(); @@ -1464,7 +1613,8 @@ void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) { // EmitLinkageSpec - Emit all declarations in a linkage spec. void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) { - if (LSD->getLanguage() != LinkageSpecDecl::lang_c) { + if (LSD->getLanguage() != LinkageSpecDecl::lang_c && + LSD->getLanguage() != LinkageSpecDecl::lang_cxx) { ErrorUnsupported(LSD, "linkage spec"); return; } @@ -1485,18 +1635,20 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { // Ignore dependent declarations. if (D->getDeclContext() && D->getDeclContext()->isDependentContext()) return; - + switch (D->getKind()) { + case Decl::CXXConversion: case Decl::CXXMethod: case Decl::Function: // Skip function templates if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate()) return; + + EmitGlobal(cast<FunctionDecl>(D)); + break; - // Fall through - case Decl::Var: - EmitGlobal(GlobalDecl(cast<ValueDecl>(D))); + EmitGlobal(cast<VarDecl>(D)); break; // C++ Decls @@ -1505,8 +1657,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; // No code generation needed. case Decl::Using: + case Decl::UsingDirective: case Decl::ClassTemplate: case Decl::FunctionTemplate: + case Decl::NamespaceAlias: break; case Decl::CXXConstructor: EmitCXXConstructors(cast<CXXConstructorDecl>(D)); @@ -1520,7 +1674,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; // Objective-C Decls - + // Forward declarations, no (immediate) code generation. case Decl::ObjCClass: case Decl::ObjCForwardProtocol: @@ -1543,7 +1697,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { EmitObjCPropertyImplementations(OMD); Runtime->GenerateClass(OMD); break; - } + } case Decl::ObjCMethod: { ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D); // If this is not a prototype, emit the body. @@ -1551,7 +1705,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { CodeGenFunction(*this).GenerateObjCMethod(OMD); break; } - case Decl::ObjCCompatibleAlias: + case Decl::ObjCCompatibleAlias: // compatibility-alias is a directive and has no code gen. break; @@ -1563,7 +1717,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { FileScopeAsmDecl *AD = cast<FileScopeAsmDecl>(D); std::string AsmString(AD->getAsmString()->getStrData(), AD->getAsmString()->getByteLength()); - + const std::string &S = getModule().getModuleInlineAsm(); if (S.empty()) getModule().setModuleInlineAsm(AsmString); @@ -1571,8 +1725,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { getModule().setModuleInlineAsm(S + '\n' + AsmString); break; } - - default: + + default: // 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. diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ba9f1b28a07d3..2e58337ee52db 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -17,16 +17,22 @@ #include "clang/Basic/LangOptions.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "CGBlocks.h" #include "CGCall.h" #include "CGCXX.h" +#include "CGVtable.h" #include "CodeGenTypes.h" +#include "Mangle.h" +#include "llvm/Module.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/ValueHandle.h" #include <list> +#define ATTACH_DEBUG_INFO_TO_AN_INSN 1 + namespace llvm { class Module; class Constant; @@ -34,6 +40,7 @@ namespace llvm { class GlobalValue; class TargetData; class FunctionType; + class LLVMContext; } namespace clang { @@ -68,42 +75,50 @@ namespace CodeGen { /// GlobalDecl - represents a global declaration. This can either be a /// CXXConstructorDecl and the constructor type (Base, Complete). /// a CXXDestructorDecl and the destructor type (Base, Complete) or -// a regular VarDecl or a FunctionDecl. +/// a VarDecl, a FunctionDecl or a BlockDecl. class GlobalDecl { - llvm::PointerIntPair<const ValueDecl*, 2> Value; + llvm::PointerIntPair<const Decl*, 2> Value; + + void Init(const Decl *D) { + assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!"); + assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!"); + + Value.setPointer(D); + } public: GlobalDecl() {} - - explicit GlobalDecl(const ValueDecl *VD) : Value(VD, 0) { - assert(!isa<CXXConstructorDecl>(VD) && "Use other ctor with ctor decls!"); - assert(!isa<CXXDestructorDecl>(VD) && "Use other ctor with dtor decls!"); - } - GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) + + GlobalDecl(const VarDecl *D) { Init(D);} + GlobalDecl(const FunctionDecl *D) { Init(D); } + GlobalDecl(const BlockDecl *D) { Init(D); } + GlobalDecl(const ObjCMethodDecl *D) { Init(D); } + + GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} - - const ValueDecl *getDecl() const { return Value.getPointer(); } - + + const Decl *getDecl() const { return Value.getPointer(); } + CXXCtorType getCtorType() const { assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!"); return static_cast<CXXCtorType>(Value.getInt()); } - + CXXDtorType getDtorType() const { assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!"); return static_cast<CXXDtorType>(Value.getInt()); } }; - + /// CodeGenModule - This class organizes the cross-function state that is used /// while generating LLVM code. class CodeGenModule : public BlockModule { CodeGenModule(const CodeGenModule&); // DO NOT IMPLEMENT void operator=(const CodeGenModule&); // DO NOT IMPLEMENT - typedef std::vector< std::pair<llvm::Constant*, int> > CtorList; + typedef std::vector<std::pair<llvm::Constant*, int> > CtorList; ASTContext &Context; const LangOptions &Features; @@ -112,9 +127,14 @@ class CodeGenModule : public BlockModule { const llvm::TargetData &TheTargetData; Diagnostic &Diags; CodeGenTypes Types; + MangleContext MangleCtx; + + /// VtableInfo - Holds information about C++ vtables. + CGVtableInfo VtableInfo; + CGObjCRuntime* Runtime; CGDebugInfo* DebugInfo; - + llvm::Function *MemCpyFn; llvm::Function *MemMoveFn; llvm::Function *MemSetFn; @@ -171,9 +191,15 @@ class CodeGenModule : public BlockModule { llvm::StringMap<llvm::Constant*> CFConstantStringMap; llvm::StringMap<llvm::Constant*> ConstantStringMap; + /// CXXGlobalInits - Variables with global initializers that need to run + /// before main. + std::vector<const VarDecl*> CXXGlobalInits; + /// CFConstantStringClassRef - Cached reference to the class for constant /// strings. This value has type int * but is actually an Obj-C class pointer. llvm::Constant *CFConstantStringClassRef; + + llvm::LLVMContext &VMContext; public: CodeGenModule(ASTContext &C, const CompileOptions &CompileOpts, llvm::Module &M, const llvm::TargetData &TD, Diagnostic &Diags); @@ -200,8 +226,11 @@ public: const LangOptions &getLangOptions() const { return Features; } llvm::Module &getModule() const { return TheModule; } CodeGenTypes &getTypes() { return Types; } + MangleContext &getMangleContext() { return MangleCtx; } + CGVtableInfo &getVtableInfo() { return VtableInfo; } Diagnostic &getDiags() const { return Diags; } const llvm::TargetData &getTargetData() const { return TheTargetData; } + llvm::LLVMContext &getLLVMContext() { return VMContext; } /// getDeclVisibilityMode - Compute the visibility of the decl \arg D. LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const; @@ -223,6 +252,22 @@ public: llvm::Constant *GetAddrOfFunction(GlobalDecl GD, const llvm::Type *Ty = 0); + /// GenerateRtti - Generate the rtti information for the given type. + llvm::Constant *GenerateRtti(const CXXRecordDecl *RD); + + /// BuildThunk - Build a thunk for the given method + llvm::Constant *BuildThunk(const CXXMethodDecl *MD, bool Extern, int64_t nv, + int64_t v); + /// BuildCoVariantThunk - Build a thunk for the given method + llvm::Constant *BuildCovariantThunk(const CXXMethodDecl *MD, bool Extern, + int64_t nv_t, int64_t v_t, + int64_t nv_r, int64_t v_r); + + /// GetCXXBaseClassOffset - Returns the offset from a derived class to its + /// base class. Returns null if the offset is 0. + llvm::Constant *GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl); + /// GetStringForStringLiteral - Return the appropriate bytes for a string /// literal, properly padded to match the literal type. If only the address of /// a constant is needed consider using GetAddrOfConstantStringLiteral. @@ -239,7 +284,7 @@ public: /// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant /// array for the given ObjCEncodeExpr node. llvm::Constant *GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *); - + /// GetAddrOfConstantString - Returns a pointer to a character array /// containing the literal. This contents are exactly that of the given /// string, i.e. it will not be null terminated automatically; see @@ -264,17 +309,18 @@ public: /// GetAddrOfCXXConstructor - Return the address of the constructor of the /// given type. - llvm::Function *GetAddrOfCXXConstructor(const CXXConstructorDecl *D, + llvm::Function *GetAddrOfCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type); /// GetAddrOfCXXDestructor - Return the address of the constructor of the /// given type. - llvm::Function *GetAddrOfCXXDestructor(const CXXDestructorDecl *D, + llvm::Function *GetAddrOfCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type); - + /// getBuiltinLibFunction - Given a builtin id for a function like /// "__builtin_fabsf", return a Function* for "fabsf". - llvm::Value *getBuiltinLibFunction(unsigned BuiltinID); + llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD, + unsigned BuiltinID); llvm::Function *getMemCpyFn(); llvm::Function *getMemMoveFn(); @@ -355,20 +401,30 @@ public: /// as a return type. bool ReturnTypeUsesSret(const CGFunctionInfo &FI); + /// ConstructAttributeList - Get the LLVM attributes and calling convention to + /// use for a particular function type. + /// + /// \param Info - The function type information. + /// \param TargetDecl - The decl these attributes are being constructed + /// for. If supplied the attributes applied to this decl may contribute to the + /// function attributes and calling convention. + /// \param PAL [out] - On return, the attribute list to use. + /// \param CallingConv [out] - On return, the LLVM calling convention to use. void ConstructAttributeList(const CGFunctionInfo &Info, const Decl *TargetDecl, - AttributeListType &PAL); + AttributeListType &PAL, + unsigned &CallingConv); const char *getMangledName(const GlobalDecl &D); const char *getMangledName(const NamedDecl *ND); - const char *getMangledCXXCtorName(const CXXConstructorDecl *D, + const char *getMangledCXXCtorName(const CXXConstructorDecl *D, CXXCtorType Type); - const char *getMangledCXXDtorName(const CXXDestructorDecl *D, + const char *getMangledCXXDtorName(const CXXDestructorDecl *D, CXXDtorType Type); void EmitTentativeDefinition(const VarDecl *D); - + enum GVALinkage { GVA_Internal, GVA_C99Inline, @@ -376,19 +432,22 @@ public: GVA_StrongExternal, GVA_TemplateInstantiation }; - + private: /// UniqueMangledName - Unique a name by (if necessary) inserting it into the /// MangledNames string map. const char *UniqueMangledName(const char *NameStart, const char *NameEnd); - + llvm::Constant *GetOrCreateLLVMFunction(const char *MangledName, const llvm::Type *Ty, GlobalDecl D); llvm::Constant *GetOrCreateLLVMGlobal(const char *MangledName, const llvm::PointerType *PTy, const VarDecl *D); - + void DeferredCopyConstructorToEmit(GlobalDecl D); + void DeferredCopyAssignmentToEmit(GlobalDecl D); + void DeferredDestructorToEmit(GlobalDecl D); + /// SetCommonAttributes - Set attributes which are common to any /// form of a global definition (alias, Objective-C method, /// function, global variable). @@ -397,9 +456,9 @@ private: void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV); /// SetFunctionDefinitionAttributes - Set attributes for a global definition. - void SetFunctionDefinitionAttributes(const FunctionDecl *D, + void SetFunctionDefinitionAttributes(const FunctionDecl *D, llvm::GlobalValue *GV); - + /// SetFunctionAttributes - Set function attributes for a function /// declaration. void SetFunctionAttributes(const FunctionDecl *FD, @@ -418,26 +477,29 @@ private: void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); // C++ related functions. - + void EmitNamespace(const NamespaceDecl *D); void EmitLinkageSpec(const LinkageSpecDecl *D); /// EmitCXXConstructors - Emit constructors (base, complete) from a /// C++ constructor Decl. void EmitCXXConstructors(const CXXConstructorDecl *D); - + /// EmitCXXConstructor - Emit a single constructor with the given type from /// a C++ constructor Decl. void EmitCXXConstructor(const CXXConstructorDecl *D, CXXCtorType Type); - - /// EmitCXXDestructors - Emit destructors (base, complete) from a + + /// EmitCXXDestructors - Emit destructors (base, complete) from a /// C++ destructor Decl. void EmitCXXDestructors(const CXXDestructorDecl *D); - + /// EmitCXXDestructor - Emit a single destructor with the given type from /// a C++ destructor Decl. void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type); - + + /// EmitCXXGlobalInitFunc - Emit a function that initializes C++ globals. + void EmitCXXGlobalInitFunc(); + // FIXME: Hardcoding priority here is gross. void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535); void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535); diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 1a30ea37fbbc3..dedf824ef9fd4 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This is the code that handles AST -> LLVM type lowering. +// This is the code that handles AST -> LLVM type lowering. // //===----------------------------------------------------------------------===// #include "CodeGenTypes.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" #include "llvm/DerivedTypes.h" @@ -21,47 +22,11 @@ #include "llvm/Target/TargetData.h" #include "CGCall.h" +#include "CGRecordLayoutBuilder.h" using namespace clang; using namespace CodeGen; -namespace { - /// RecordOrganizer - This helper class, used by CGRecordLayout, layouts - /// structs and unions. It manages transient information used during layout. - /// FIXME : Handle field aligments. Handle packed structs. - class RecordOrganizer { - public: - explicit RecordOrganizer(CodeGenTypes &Types, const RecordDecl& Record) : - CGT(Types), RD(Record), STy(NULL) {} - - /// layoutStructFields - Do the actual work and lay out all fields. Create - /// corresponding llvm struct type. This should be invoked only after - /// all fields are added. - void layoutStructFields(const ASTRecordLayout &RL); - - /// layoutUnionFields - Do the actual work and lay out all fields. Create - /// corresponding llvm struct type. This should be invoked only after - /// all fields are added. - void layoutUnionFields(const ASTRecordLayout &RL); - - /// getLLVMType - Return associated llvm struct type. This may be NULL - /// if fields are not laid out. - llvm::Type *getLLVMType() const { - return STy; - } - - llvm::SmallSet<unsigned, 8> &getPaddingFields() { - return PaddingFields; - } - - private: - CodeGenTypes &CGT; - const RecordDecl& RD; - llvm::Type *STy; - llvm::SmallSet<unsigned, 8> PaddingFields; - }; -} - CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M, const llvm::TargetData &TD) : Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD), @@ -69,8 +34,8 @@ CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M, } CodeGenTypes::~CodeGenTypes() { - for(llvm::DenseMap<const Type *, CGRecordLayout *>::iterator - I = CGRecordLayouts.begin(), E = CGRecordLayouts.end(); + for (llvm::DenseMap<const Type *, CGRecordLayout *>::iterator + I = CGRecordLayouts.begin(), E = CGRecordLayouts.end(); I != E; ++I) delete I->second; CGRecordLayouts.clear(); @@ -100,7 +65,7 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) { const llvm::Type *CodeGenTypes::ConvertTypeRecursive(QualType T) { T = Context.getCanonicalType(T); - + // See if type is already cached. llvm::DenseMap<Type *, llvm::PATypeHolder>::iterator I = TypeCache.find(T.getTypePtr()); @@ -110,15 +75,16 @@ const llvm::Type *CodeGenTypes::ConvertTypeRecursive(QualType T) { return I->second.get(); const llvm::Type *ResultType = ConvertNewType(T); - TypeCache.insert(std::make_pair(T.getTypePtr(), + TypeCache.insert(std::make_pair(T.getTypePtr(), llvm::PATypeHolder(ResultType))); return ResultType; } const llvm::Type *CodeGenTypes::ConvertTypeForMemRecursive(QualType T) { const llvm::Type *ResultType = ConvertTypeRecursive(T); - if (ResultType == llvm::Type::Int1Ty) - return llvm::IntegerType::get((unsigned)Context.getTypeSize(T)); + if (ResultType == llvm::Type::getInt1Ty(getLLVMContext())) + return llvm::IntegerType::get(getLLVMContext(), + (unsigned)Context.getTypeSize(T)); return ResultType; } @@ -128,26 +94,27 @@ const llvm::Type *CodeGenTypes::ConvertTypeForMemRecursive(QualType T) { /// memory representation is usually i8 or i32, depending on the target. const llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) { const llvm::Type *R = ConvertType(T); - + // If this is a non-bool type, don't map it. - if (R != llvm::Type::Int1Ty) + if (R != llvm::Type::getInt1Ty(getLLVMContext())) return R; - + // Otherwise, return an integer of the target-specified size. - return llvm::IntegerType::get((unsigned)Context.getTypeSize(T)); - + return llvm::IntegerType::get(getLLVMContext(), + (unsigned)Context.getTypeSize(T)); + } // Code to verify a given function type is complete, i.e. the return type // and all of the argument types are complete. static const TagType *VerifyFuncTypeComplete(const Type* T) { const FunctionType *FT = cast<FunctionType>(T); - if (const TagType* TT = FT->getResultType()->getAsTagType()) + if (const TagType* TT = FT->getResultType()->getAs<TagType>()) if (!TT->getDecl()->isDefinition()) return TT; if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(T)) for (unsigned i = 0; i < FPT->getNumArgs(); i++) - if (const TagType* TT = FPT->getArgType(i)->getAsTagType()) + if (const TagType* TT = FPT->getArgType(i)->getAs<TagType>()) if (!TT->getDecl()->isDefinition()) return TT; return 0; @@ -156,17 +123,16 @@ static const TagType *VerifyFuncTypeComplete(const Type* T) { /// UpdateCompletedType - When we find the full definition for a TagDecl, /// replace the 'opaque' type we previously made for it if applicable. void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { - const Type *Key = - Context.getTagDeclType(const_cast<TagDecl*>(TD)).getTypePtr(); - llvm::DenseMap<const Type*, llvm::PATypeHolder>::iterator TDTI = + const Type *Key = Context.getTagDeclType(TD).getTypePtr(); + llvm::DenseMap<const Type*, llvm::PATypeHolder>::iterator TDTI = TagDeclTypes.find(Key); if (TDTI == TagDeclTypes.end()) return; - + // Remember the opaque LLVM type for this tagdecl. llvm::PATypeHolder OpaqueHolder = TDTI->second; assert(isa<llvm::OpaqueType>(OpaqueHolder.get()) && "Updating compilation of an already non-opaque type?"); - + // Remove it from TagDeclTypes so that it will be regenerated. TagDeclTypes.erase(TDTI); @@ -197,24 +163,25 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { } } -static const llvm::Type* getTypeForFormat(const llvm::fltSemantics &format) { +static const llvm::Type* getTypeForFormat(llvm::LLVMContext &VMContext, + const llvm::fltSemantics &format) { if (&format == &llvm::APFloat::IEEEsingle) - return llvm::Type::FloatTy; + return llvm::Type::getFloatTy(VMContext); if (&format == &llvm::APFloat::IEEEdouble) - return llvm::Type::DoubleTy; + return llvm::Type::getDoubleTy(VMContext); if (&format == &llvm::APFloat::IEEEquad) - return llvm::Type::FP128Ty; + return llvm::Type::getFP128Ty(VMContext); if (&format == &llvm::APFloat::PPCDoubleDouble) - return llvm::Type::PPC_FP128Ty; + return llvm::Type::getPPC_FP128Ty(VMContext); if (&format == &llvm::APFloat::x87DoubleExtended) - return llvm::Type::X86_FP80Ty; + return llvm::Type::getX86_FP80Ty(VMContext); assert(0 && "Unknown float format!"); return 0; } const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { const clang::Type &Ty = *Context.getCanonicalType(T); - + switch (Ty.getTypeClass()) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) @@ -228,14 +195,16 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { switch (cast<BuiltinType>(Ty).getKind()) { default: assert(0 && "Unknown builtin type!"); case BuiltinType::Void: + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: // LLVM void type can only be used as the result of a function call. Just // map to the same as char. - return llvm::IntegerType::get(8); + return llvm::IntegerType::get(getLLVMContext(), 8); case BuiltinType::Bool: // Note that we always return bool as i1 for use as a scalar type. - return llvm::Type::Int1Ty; - + return llvm::Type::getInt1Ty(getLLVMContext()); + case BuiltinType::Char_S: case BuiltinType::Char_U: case BuiltinType::SChar: @@ -249,46 +218,56 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case BuiltinType::LongLong: case BuiltinType::ULongLong: case BuiltinType::WChar: - return llvm::IntegerType::get( + case BuiltinType::Char16: + case BuiltinType::Char32: + return llvm::IntegerType::get(getLLVMContext(), static_cast<unsigned>(Context.getTypeSize(T))); - + case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: - return getTypeForFormat(Context.getFloatTypeSemantics(T)); - + return getTypeForFormat(getLLVMContext(), + Context.getFloatTypeSemantics(T)); + + case BuiltinType::NullPtr: { + // Model std::nullptr_t as i8* + const llvm::Type *Ty = llvm::IntegerType::get(getLLVMContext(), 8); + return llvm::PointerType::getUnqual(Ty); + } + case BuiltinType::UInt128: case BuiltinType::Int128: - return llvm::IntegerType::get(128); + return llvm::IntegerType::get(getLLVMContext(), 128); } break; } case Type::FixedWidthInt: - return llvm::IntegerType::get(cast<FixedWidthIntType>(T)->getWidth()); + return llvm::IntegerType::get(getLLVMContext(), + cast<FixedWidthIntType>(T)->getWidth()); case Type::Complex: { - const llvm::Type *EltTy = + const llvm::Type *EltTy = ConvertTypeRecursive(cast<ComplexType>(Ty).getElementType()); - return llvm::StructType::get(EltTy, EltTy, NULL); + return llvm::StructType::get(TheModule.getContext(), EltTy, EltTy, NULL); } case Type::LValueReference: case Type::RValueReference: { const ReferenceType &RTy = cast<ReferenceType>(Ty); QualType ETy = RTy.getPointeeType(); - llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(); + llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext()); PointersToResolve.push_back(std::make_pair(ETy, PointeeType)); return llvm::PointerType::get(PointeeType, ETy.getAddressSpace()); } case Type::Pointer: { const PointerType &PTy = cast<PointerType>(Ty); QualType ETy = PTy.getPointeeType(); - llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(); + llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext()); PointersToResolve.push_back(std::make_pair(ETy, PointeeType)); return llvm::PointerType::get(PointeeType, ETy.getAddressSpace()); } - + case Type::VariableArray: { const VariableArrayType &A = cast<VariableArrayType>(Ty); - assert(A.getIndexTypeQualifier() == 0 && + assert(A.getIndexTypeCVRQualifiers() == 0 && "FIXME: We only handle trivial array types so far!"); // VLAs resolve to the innermost element type; this matches // the return of alloca, and there isn't any obviously better choice. @@ -296,7 +275,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { } case Type::IncompleteArray: { const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty); - assert(A.getIndexTypeQualifier() == 0 && + assert(A.getIndexTypeCVRQualifiers() == 0 && "FIXME: We only handle trivial array types so far!"); // int X[] -> [0 x int] return llvm::ArrayType::get(ConvertTypeForMemRecursive(A.getElementType()), 0); @@ -320,7 +299,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { // we have an opaque type corresponding to the tag type. ConvertTagDeclType(TT->getDecl()); // Create an opaque type for this function type, save it, and return it. - llvm::Type *ResultType = llvm::OpaqueType::get(); + llvm::Type *ResultType = llvm::OpaqueType::get(getLLVMContext()); FunctionTypes.insert(std::make_pair(&Ty, ResultType)); return ResultType; } @@ -332,55 +311,57 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(&Ty); return GetFunctionType(getFunctionInfo(FNPT), true); } - - case Type::ExtQual: - return - ConvertTypeRecursive(QualType(cast<ExtQualType>(Ty).getBaseType(), 0)); - - case Type::ObjCQualifiedInterface: { - // Lower foo<P1,P2> just like foo. - ObjCInterfaceDecl *ID = cast<ObjCQualifiedInterfaceType>(Ty).getDecl(); - return ConvertTypeRecursive(Context.getObjCInterfaceType(ID)); - } - + case Type::ObjCInterface: { // Objective-C interfaces are always opaque (outside of the // runtime, which can do whatever it likes); we never refine // these. const llvm::Type *&T = InterfaceTypes[cast<ObjCInterfaceType>(&Ty)]; if (!T) - T = llvm::OpaqueType::get(); + T = llvm::OpaqueType::get(getLLVMContext()); return T; } - - case Type::ObjCObjectPointer: - // Protocols don't influence the LLVM type. - return ConvertTypeRecursive(Context.getObjCIdType()); + + case Type::ObjCObjectPointer: { + // Protocol qualifications do not influence the LLVM type, we just return a + // pointer to the underlying interface type. We don't need to worry about + // recursive conversion. + const llvm::Type *T = + ConvertTypeRecursive(cast<ObjCObjectPointerType>(Ty).getPointeeType()); + return llvm::PointerType::getUnqual(T); + } case Type::Record: case Type::Enum: { const TagDecl *TD = cast<TagType>(Ty).getDecl(); const llvm::Type *Res = ConvertTagDeclType(TD); - + std::string TypeName(TD->getKindName()); TypeName += '.'; - + // Name the codegen type after the typedef name // if there is no tag type name available if (TD->getIdentifier()) - TypeName += TD->getNameAsString(); + // FIXME: We should not have to check for a null decl context here. + // Right now we do it because the implicit Obj-C decls don't have one. + TypeName += TD->getDeclContext() ? TD->getQualifiedNameAsString() : + TD->getNameAsString(); else if (const TypedefType *TdT = dyn_cast<TypedefType>(T)) - TypeName += TdT->getDecl()->getNameAsString(); + // FIXME: We should not have to check for a null decl context here. + // Right now we do it because the implicit Obj-C decls don't have one. + TypeName += TdT->getDecl()->getDeclContext() ? + TdT->getDecl()->getQualifiedNameAsString() : + TdT->getDecl()->getNameAsString(); else TypeName += "anon"; - - TheModule.addTypeName(TypeName, Res); + + TheModule.addTypeName(TypeName, Res); return Res; } case Type::BlockPointer: { const QualType FTy = cast<BlockPointerType>(Ty).getPointeeType(); - llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(); + llvm::OpaqueType *PointeeType = llvm::OpaqueType::get(getLLVMContext()); PointersToResolve.push_back(std::make_pair(FTy, PointeeType)); return llvm::PointerType::get(PointeeType, FTy.getAddressSpace()); } @@ -392,7 +373,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { QualType ETy = cast<MemberPointerType>(Ty).getPointeeType(); if (ETy->isFunctionType()) { - return llvm::StructType::get(ConvertType(Context.getPointerDiffType()), + return llvm::StructType::get(TheModule.getContext(), + ConvertType(Context.getPointerDiffType()), ConvertType(Context.getPointerDiffType()), NULL); } else @@ -402,85 +384,85 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case Type::TemplateSpecialization: assert(false && "Dependent types can't get here"); } - + // FIXME: implement. - return llvm::OpaqueType::get(); + return llvm::OpaqueType::get(getLLVMContext()); } /// ConvertTagDeclType - Lay out a tagged decl type like struct or union or /// enum. const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) { + + // FIXME. This may have to move to a better place. + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) { + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + if (!i->isVirtual()) { + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + ConvertTagDeclType(Base); + } + } + } + // TagDecl's are not necessarily unique, instead use the (clang) // type connected to the decl. - const Type *Key = - Context.getTagDeclType(const_cast<TagDecl*>(TD)).getTypePtr(); - llvm::DenseMap<const Type*, llvm::PATypeHolder>::iterator TDTI = + const Type *Key = + Context.getTagDeclType(TD).getTypePtr(); + llvm::DenseMap<const Type*, llvm::PATypeHolder>::iterator TDTI = TagDeclTypes.find(Key); - + // If we've already compiled this tag type, use the previous definition. if (TDTI != TagDeclTypes.end()) return TDTI->second; - + // If this is still a forward definition, just define an opaque type to use // for this tagged decl. if (!TD->isDefinition()) { - llvm::Type *ResultType = llvm::OpaqueType::get(); + llvm::Type *ResultType = llvm::OpaqueType::get(getLLVMContext()); TagDeclTypes.insert(std::make_pair(Key, ResultType)); return ResultType; } - + // Okay, this is a definition of a type. Compile the implementation now. - + if (TD->isEnum()) { // Don't bother storing enums in TagDeclTypes. return ConvertTypeRecursive(cast<EnumDecl>(TD)->getIntegerType()); } - + // This decl could well be recursive. In this case, insert an opaque // definition of this type, which the recursive uses will get. We will then // refine this opaque version later. // Create new OpaqueType now for later use in case this is a recursive // type. This will later be refined to the actual type. - llvm::PATypeHolder ResultHolder = llvm::OpaqueType::get(); + llvm::PATypeHolder ResultHolder = llvm::OpaqueType::get(getLLVMContext()); TagDeclTypes.insert(std::make_pair(Key, ResultHolder)); - + const llvm::Type *ResultType; const RecordDecl *RD = cast<const RecordDecl>(TD); - // There isn't any extra information for empty structures/unions. - if (RD->field_empty()) { - ResultType = llvm::StructType::get(std::vector<const llvm::Type*>()); - } else { - // Layout fields. - RecordOrganizer RO(*this, *RD); - - if (TD->isStruct() || TD->isClass()) - RO.layoutStructFields(Context.getASTRecordLayout(RD)); - else { - assert(TD->isUnion() && "unknown tag decl kind!"); - RO.layoutUnionFields(Context.getASTRecordLayout(RD)); - } - - // Get llvm::StructType. - const Type *Key = - Context.getTagDeclType(const_cast<TagDecl*>(TD)).getTypePtr(); - CGRecordLayouts[Key] = new CGRecordLayout(RO.getLLVMType(), - RO.getPaddingFields()); - ResultType = RO.getLLVMType(); - } - + // Layout fields. + CGRecordLayout *Layout = + CGRecordLayoutBuilder::ComputeLayout(*this, RD); + + CGRecordLayouts[Key] = Layout; + ResultType = Layout->getLLVMType(); + // Refine our Opaque type to ResultType. This can invalidate ResultType, so // make sure to read the result out of the holder. cast<llvm::OpaqueType>(ResultHolder.get()) ->refineAbstractTypeTo(ResultType); - + return ResultHolder.get(); -} +} /// getLLVMFieldNo - Return llvm::StructType element number /// that corresponds to the field FD. unsigned CodeGenTypes::getLLVMFieldNo(const FieldDecl *FD) { + assert(!FD->isBitField() && "Don't use getLLVMFieldNo on bit fields!"); + llvm::DenseMap<const FieldDecl*, unsigned>::iterator I = FieldInfo.find(FD); assert (I != FieldInfo.end() && "Unable to find field info"); return I->second; @@ -500,115 +482,19 @@ CodeGenTypes::BitFieldInfo CodeGenTypes::getBitFieldInfo(const FieldDecl *FD) { } /// addBitFieldInfo - Assign a start bit and a size to field FD. -void CodeGenTypes::addBitFieldInfo(const FieldDecl *FD, unsigned Begin, - unsigned Size) { - BitFields.insert(std::make_pair(FD, BitFieldInfo(Begin, Size))); +void CodeGenTypes::addBitFieldInfo(const FieldDecl *FD, unsigned FieldNo, + unsigned Start, unsigned Size) { + BitFields.insert(std::make_pair(FD, BitFieldInfo(FieldNo, Start, Size))); } /// getCGRecordLayout - Return record layout info for the given llvm::Type. -const CGRecordLayout * +const CGRecordLayout & CodeGenTypes::getCGRecordLayout(const TagDecl *TD) const { - const Type *Key = - Context.getTagDeclType(const_cast<TagDecl*>(TD)).getTypePtr(); + const Type *Key = + Context.getTagDeclType(TD).getTypePtr(); llvm::DenseMap<const Type*, CGRecordLayout *>::iterator I = CGRecordLayouts.find(Key); - assert (I != CGRecordLayouts.end() + assert (I != CGRecordLayouts.end() && "Unable to find record layout information for type"); - return I->second; -} - -/// layoutStructFields - Do the actual work and lay out all fields. Create -/// corresponding llvm struct type. -/// Note that this doesn't actually try to do struct layout; it depends on -/// the layout built by the AST. (We have to do struct layout to do Sema, -/// and there's no point to duplicating the work.) -void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) { - // FIXME: This code currently always generates packed structures. - // Unpacked structures are more readable, and sometimes more efficient! - // (But note that any changes here are likely to impact CGExprConstant, - // which makes some messy assumptions.) - uint64_t llvmSize = 0; - // FIXME: Make this a SmallVector - std::vector<const llvm::Type*> LLVMFields; - - unsigned curField = 0; - for (RecordDecl::field_iterator Field = RD.field_begin(), - FieldEnd = RD.field_end(); - Field != FieldEnd; ++Field) { - uint64_t offset = RL.getFieldOffset(curField); - const llvm::Type *Ty = CGT.ConvertTypeForMemRecursive(Field->getType()); - uint64_t size = CGT.getTargetData().getTypeAllocSizeInBits(Ty); - - if (Field->isBitField()) { - uint64_t BitFieldSize = - Field->getBitWidth()->EvaluateAsInt(CGT.getContext()).getZExtValue(); - - // Bitfield field info is different from other field info; - // it actually ignores the underlying LLVM struct because - // there isn't any convenient mapping. - CGT.addFieldInfo(*Field, offset / size); - CGT.addBitFieldInfo(*Field, offset % size, BitFieldSize); - } else { - // Put the element into the struct. This would be simpler - // if we didn't bother, but it seems a bit too strange to - // allocate all structs as i8 arrays. - while (llvmSize < offset) { - LLVMFields.push_back(llvm::Type::Int8Ty); - llvmSize += 8; - } - - llvmSize += size; - CGT.addFieldInfo(*Field, LLVMFields.size()); - LLVMFields.push_back(Ty); - } - ++curField; - } - - while (llvmSize < RL.getSize()) { - LLVMFields.push_back(llvm::Type::Int8Ty); - llvmSize += 8; - } - - STy = llvm::StructType::get(LLVMFields, true); - assert(CGT.getTargetData().getTypeAllocSizeInBits(STy) == RL.getSize()); -} - -/// layoutUnionFields - Do the actual work and lay out all fields. Create -/// corresponding llvm struct type. This should be invoked only after -/// all fields are added. -void RecordOrganizer::layoutUnionFields(const ASTRecordLayout &RL) { - unsigned curField = 0; - for (RecordDecl::field_iterator Field = RD.field_begin(), - FieldEnd = RD.field_end(); - Field != FieldEnd; ++Field) { - // The offset should usually be zero, but bitfields could be strange - uint64_t offset = RL.getFieldOffset(curField); - CGT.ConvertTypeRecursive(Field->getType()); - - if (Field->isBitField()) { - Expr *BitWidth = Field->getBitWidth(); - uint64_t BitFieldSize = - BitWidth->EvaluateAsInt(CGT.getContext()).getZExtValue(); - - CGT.addFieldInfo(*Field, 0); - CGT.addBitFieldInfo(*Field, offset, BitFieldSize); - } else { - CGT.addFieldInfo(*Field, 0); - } - ++curField; - } - - // This looks stupid, but it is correct in the sense that - // it works no matter how complicated the sizes and alignments - // of the union elements are. The natural alignment - // of the result doesn't matter because anyone allocating - // structures should be aligning them appropriately anyway. - // FIXME: We can be a bit more intuitive in a lot of cases. - // FIXME: Make this a struct type to work around PR2399; the - // C backend doesn't like structs using array types. - std::vector<const llvm::Type*> LLVMFields; - LLVMFields.push_back(llvm::ArrayType::get(llvm::Type::Int8Ty, - RL.getSize() / 8)); - STy = llvm::StructType::get(LLVMFields, true); - assert(CGT.getTargetData().getTypeAllocSizeInBits(STy) == RL.getSize()); + return *I->second; } diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index b72d8e92013ae..a92a019b988ec 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This is the code that handles AST -> LLVM type lowering. +// This is the code that handles AST -> LLVM type lowering. // //===----------------------------------------------------------------------===// #ifndef CLANG_CODEGEN_CODEGENTYPES_H #define CLANG_CODEGEN_CODEGENTYPES_H +#include "llvm/Module.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include <vector> @@ -27,6 +28,7 @@ namespace llvm { class PATypeHolder; class TargetData; class Type; + class LLVMContext; } namespace clang { @@ -47,35 +49,44 @@ namespace clang { namespace CodeGen { class CodeGenTypes; - /// CGRecordLayout - This class handles struct and union layout info while + /// CGRecordLayout - This class handles struct and union layout info while /// lowering AST types to LLVM types. class CGRecordLayout { CGRecordLayout(); // DO NOT IMPLEMENT + + /// LLVMType - The LLVMType corresponding to this record layout. + const llvm::Type *LLVMType; + + /// ContainsMemberPointer - Whether one of the fields in this record layout + /// is a member pointer, or a struct that contains a member pointer. + bool ContainsMemberPointer; + + /// KeyFunction - The key function of the record layout (if one exists), + /// which is the first non-pure virtual function that is not inline at the + /// point of class definition. + /// See http://www.codesourcery.com/public/cxx-abi/abi.html#vague-vtable. + const CXXMethodDecl *KeyFunction; + public: - CGRecordLayout(llvm::Type *T, llvm::SmallSet<unsigned, 8> &PF) - : STy(T), PaddingFields(PF) { - // FIXME : Collect info about fields that requires adjustments - // (i.e. fields that do not directly map to llvm struct fields.) - } + CGRecordLayout(const llvm::Type *T, bool ContainsMemberPointer, + const CXXMethodDecl *KeyFunction) + : LLVMType(T), ContainsMemberPointer(ContainsMemberPointer), + KeyFunction(KeyFunction) { } /// getLLVMType - Return llvm type associated with this record. - llvm::Type *getLLVMType() const { - return STy; + const llvm::Type *getLLVMType() const { + return LLVMType; } - bool isPaddingField(unsigned No) const { - return PaddingFields.count(No) != 0; + bool containsMemberPointer() const { + return ContainsMemberPointer; } - unsigned getNumPaddingFields() { - return PaddingFields.size(); + const CXXMethodDecl *getKeyFunction() const { + return KeyFunction; } - - private: - llvm::Type *STy; - llvm::SmallSet<unsigned, 8> PaddingFields; }; - + /// CodeGenTypes - This class organizes the cross-module state that is used /// while lowering AST types to LLVM types. class CodeGenTypes { @@ -84,7 +95,7 @@ class CodeGenTypes { llvm::Module& TheModule; const llvm::TargetData& TheTargetData; mutable const ABIInfo* TheABIInfo; - + llvm::SmallVector<std::pair<QualType, llvm::OpaqueType *>, 8> PointersToResolve; @@ -98,9 +109,9 @@ class CodeGenTypes { /// types are never refined. llvm::DenseMap<const ObjCInterfaceType*, const llvm::Type *> InterfaceTypes; - /// CGRecordLayouts - This maps llvm struct type with corresponding - /// record layout info. - /// FIXME : If CGRecordLayout is less than 16 bytes then use + /// CGRecordLayouts - This maps llvm struct type with corresponding + /// record layout info. + /// FIXME : If CGRecordLayout is less than 16 bytes then use /// inline it in the map. llvm::DenseMap<const Type*, CGRecordLayout *> CGRecordLayouts; @@ -112,13 +123,15 @@ class CodeGenTypes { llvm::FoldingSet<CGFunctionInfo> FunctionInfos; public: - class BitFieldInfo { - public: - explicit BitFieldInfo(unsigned short B, unsigned short S) - : Begin(B), Size(S) {} - - unsigned short Begin; - unsigned short Size; + struct BitFieldInfo { + BitFieldInfo(unsigned FieldNo, + unsigned Start, + unsigned Size) + : FieldNo(FieldNo), Start(Start), Size(Size) {} + + unsigned FieldNo; + unsigned Start; + unsigned Size; }; private: @@ -126,7 +139,7 @@ private: /// TypeCache - This map keeps cache of llvm::Types (through PATypeHolder) /// and maps llvm::Types to corresponding clang::Type. llvm::PATypeHolder is - /// used instead of llvm::Type because it allows us to bypass potential + /// used instead of llvm::Type because it allows us to bypass potential /// dangling type pointers due to type refinement on llvm side. llvm::DenseMap<Type *, llvm::PATypeHolder> TypeCache; @@ -138,16 +151,17 @@ private: public: CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD); ~CodeGenTypes(); - + const llvm::TargetData &getTargetData() const { return TheTargetData; } TargetInfo &getTarget() const { return Target; } ASTContext &getContext() const { return Context; } const ABIInfo &getABIInfo() const; + llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); } - /// ConvertType - Convert type T into a llvm::Type. + /// ConvertType - Convert type T into a llvm::Type. const llvm::Type *ConvertType(QualType T); const llvm::Type *ConvertTypeRecursive(QualType T); - + /// ConvertTypeForMem - Convert type T into a llvm::Type. This differs from /// ConvertType in that it is used to convert to the memory representation for /// a type. For example, the scalar representation for _Bool is i1, but the @@ -158,39 +172,51 @@ public: /// GetFunctionType - Get the LLVM function type for \arg Info. const llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info, bool IsVariadic); - - const CGRecordLayout *getCGRecordLayout(const TagDecl*) const; - + + const CGRecordLayout &getCGRecordLayout(const TagDecl*) const; + /// getLLVMFieldNo - Return llvm::StructType element number /// that corresponds to the field FD. unsigned getLLVMFieldNo(const FieldDecl *FD); - + /// UpdateCompletedType - When we find the full definition for a TagDecl, /// replace the 'opaque' type we previously made for it if applicable. void UpdateCompletedType(const TagDecl *TD); - /// getFunctionInfo - Get the CGFunctionInfo for this function signature. - const CGFunctionInfo &getFunctionInfo(QualType RetTy, - const llvm::SmallVector<QualType,16> - &ArgTys); - +private: const CGFunctionInfo &getFunctionInfo(const FunctionNoProtoType *FTNP); const CGFunctionInfo &getFunctionInfo(const FunctionProtoType *FTP); + +public: + /// getFunctionInfo - Get the function info for the specified function decl. const CGFunctionInfo &getFunctionInfo(const FunctionDecl *FD); const CGFunctionInfo &getFunctionInfo(const CXXMethodDecl *MD); const CGFunctionInfo &getFunctionInfo(const ObjCMethodDecl *MD); - const CGFunctionInfo &getFunctionInfo(QualType ResTy, - const CallArgList &Args); -public: - const CGFunctionInfo &getFunctionInfo(QualType ResTy, - const FunctionArgList &Args); + // getFunctionInfo - Get the function info for a member function. + const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD, + const FunctionProtoType *FTP); + + /// getFunctionInfo - Get the function info for a function described by a + /// return type and argument types. If the calling convention is not + /// specified, the "C" calling convention will be used. + const CGFunctionInfo &getFunctionInfo(QualType ResTy, + const CallArgList &Args, + unsigned CallingConvention = 0); + const CGFunctionInfo &getFunctionInfo(QualType ResTy, + const FunctionArgList &Args, + unsigned CallingConvention = 0); + const CGFunctionInfo &getFunctionInfo(QualType RetTy, + const llvm::SmallVector<QualType, 16> &ArgTys, + unsigned CallingConvention = 0); + public: // These are internal details of CGT that shouldn't be used externally. /// addFieldInfo - Assign field number to field FD. - void addFieldInfo(const FieldDecl *FD, unsigned No); + void addFieldInfo(const FieldDecl *FD, unsigned FieldNo); /// addBitFieldInfo - Assign a start bit and a size to field FD. - void addBitFieldInfo(const FieldDecl *FD, unsigned Begin, unsigned Size); + void addBitFieldInfo(const FieldDecl *FD, unsigned FieldNo, + unsigned Start, unsigned Size); /// getBitFieldInfo - Return the BitFieldInfo that corresponds to the field /// FD. diff --git a/lib/CodeGen/Makefile b/lib/CodeGen/Makefile index e716fe78bc609..108490b71d48e 100644 --- a/lib/CodeGen/Makefile +++ b/lib/CodeGen/Makefile @@ -18,6 +18,9 @@ BUILD_ARCHIVE = 1 CXXFLAGS = -fno-rtti CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include +ifdef CLANG_VENDOR +CPPFLAGS += -DCLANG_VENDOR='"$(CLANG_VENDOR) "' +endif include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 8018b4f45a84d..fd772748dbda3 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -20,85 +20,125 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" using namespace clang; namespace { class VISIBILITY_HIDDEN CXXNameMangler { - ASTContext &Context; + MangleContext &Context; llvm::raw_ostream &Out; const CXXMethodDecl *Structor; unsigned StructorType; CXXCtorType CtorType; + + llvm::DenseMap<uintptr_t, unsigned> Substitutions; public: - CXXNameMangler(ASTContext &C, llvm::raw_ostream &os) + CXXNameMangler(MangleContext &C, llvm::raw_ostream &os) : Context(C), Out(os), Structor(0), StructorType(0) { } bool mangle(const NamedDecl *D); + void mangleCalloffset(int64_t nv, int64_t v); + void mangleThunk(const FunctionDecl *FD, int64_t nv, int64_t v); + void mangleCovariantThunk(const FunctionDecl *FD, + int64_t nv_t, int64_t v_t, + int64_t nv_r, int64_t v_r); void mangleGuardVariable(const VarDecl *D); - + + void mangleCXXVtable(const CXXRecordDecl *RD); + void mangleCXXRtti(const CXXRecordDecl *RD); void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type); private: - bool mangleFunctionDecl(const FunctionDecl *FD); + bool mangleSubstitution(const NamedDecl *ND); + bool mangleSubstitution(QualType T); + bool mangleSubstitution(uintptr_t Ptr); + + bool mangleStandardSubstitution(const NamedDecl *ND); + void addSubstitution(const NamedDecl *ND) { + addSubstitution(reinterpret_cast<uintptr_t>(ND)); + } + void addSubstitution(QualType T); + void addSubstitution(uintptr_t Ptr); + + bool mangleFunctionDecl(const FunctionDecl *FD); + void mangleFunctionEncoding(const FunctionDecl *FD); void mangleName(const NamedDecl *ND); + void mangleName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); void mangleUnqualifiedName(const NamedDecl *ND); + void mangleUnscopedName(const NamedDecl *ND); + void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); void mangleNestedName(const NamedDecl *ND); + void mangleNestedName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); void manglePrefix(const DeclContext *DC); + void mangleTemplatePrefix(const TemplateDecl *ND); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); - void mangleCVQualifiers(unsigned Quals); + void mangleQualifiers(Qualifiers Quals); void mangleType(QualType T); - void mangleType(const BuiltinType *T); - void mangleType(const FunctionType *T); - void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType); - void mangleType(const TagType *T); - void mangleType(const ArrayType *T); - void mangleType(const MemberPointerType *T); - void mangleType(const TemplateTypeParmType *T); - void mangleType(const ObjCInterfaceType *T); - void mangleExpression(Expr *E); + + // Declare manglers for every type class. +#define ABSTRACT_TYPE(CLASS, PARENT) +#define NON_CANONICAL_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T); +#include "clang/AST/TypeNodes.def" + + void mangleType(const TagType*); + void mangleBareFunctionType(const FunctionType *T, + bool MangleReturnType); + void mangleExpression(const Expr *E); void mangleCXXCtorType(CXXCtorType T); void mangleCXXDtorType(CXXDtorType T); - + + void mangleTemplateArgs(const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); void mangleTemplateArgumentList(const TemplateArgumentList &L); void mangleTemplateArgument(const TemplateArgument &A); + + void mangleTemplateParameter(unsigned Index); }; } static bool isInCLinkageSpecification(const Decl *D) { - for (const DeclContext *DC = D->getDeclContext(); + for (const DeclContext *DC = D->getDeclContext(); !DC->isTranslationUnit(); DC = DC->getParent()) { - if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) + if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) return Linkage->getLanguage() == LinkageSpecDecl::lang_c; } - + return false; } bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) { - // Clang's "overloadable" attribute extension to C/C++ implies - // name mangling (always). + // Clang's "overloadable" attribute extension to C/C++ implies name mangling + // (always). if (!FD->hasAttr<OverloadableAttr>()) { // C functions are not mangled, and "main" is never mangled. - if (!Context.getLangOptions().CPlusPlus || FD->isMain()) + if (!Context.getASTContext().getLangOptions().CPlusPlus || FD->isMain()) return false; - - // No mangling in an "implicit extern C" header. + + // No mangling in an "implicit extern C" header. if (FD->getLocation().isValid() && - Context.getSourceManager().isInExternCSystemHeader(FD->getLocation())) + Context.getASTContext().getSourceManager(). + isInExternCSystemHeader(FD->getLocation())) return false; - + // No name mangling in a C linkage specification. - if (isInCLinkageSpecification(FD)) + if (!isa<CXXMethodDecl>(FD) && isInCLinkageSpecification(FD)) return false; } @@ -109,15 +149,15 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) { } bool CXXNameMangler::mangle(const NamedDecl *D) { - // Any decl can be declared with __asm("foo") on it, and this takes - // precedence over all other naming in the .o file. + // Any decl can be declared with __asm("foo") on it, and this takes precedence + // over all other naming in the .o file. if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { // If we have an asm name, then we use it as the mangling. Out << '\01'; // LLVM IR Marker for __asm("foo") Out << ALA->getLabel(); return true; } - + // <mangled-name> ::= _Z <encoding> // ::= <data name> // ::= <special-name> @@ -125,43 +165,54 @@ bool CXXNameMangler::mangle(const NamedDecl *D) { // FIXME: Actually use a visitor to decode these? if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) return mangleFunctionDecl(FD); - + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (!Context.getLangOptions().CPlusPlus || + if (!Context.getASTContext().getLangOptions().CPlusPlus || isInCLinkageSpecification(D) || D->getDeclContext()->isTranslationUnit()) return false; - + Out << "_Z"; mangleName(VD); return true; } - + return false; } -void CXXNameMangler::mangleCXXCtor(const CXXConstructorDecl *D, +void CXXNameMangler::mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type) { assert(!Structor && "Structor already set!"); Structor = D; StructorType = Type; - + mangle(D); } -void CXXNameMangler::mangleCXXDtor(const CXXDestructorDecl *D, +void CXXNameMangler::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type) { assert(!Structor && "Structor already set!"); Structor = D; StructorType = Type; - + mangle(D); } -void CXXNameMangler::mangleGuardVariable(const VarDecl *D) -{ - // <special-name> ::= GV <object name> # Guard variable for one-time - // # initialization +void CXXNameMangler::mangleCXXVtable(const CXXRecordDecl *RD) { + // <special-name> ::= TV <type> # virtual table + Out << "_ZTV"; + mangleName(RD); +} + +void CXXNameMangler::mangleCXXRtti(const CXXRecordDecl *RD) { + // <special-name> ::= TI <type> # typeinfo structure + Out << "_ZTI"; + mangleName(RD); +} + +void CXXNameMangler::mangleGuardVariable(const VarDecl *D) { + // <special-name> ::= GV <object name> # Guard variable for one-time + // # initialization Out << "_ZGV"; mangleName(D); @@ -170,29 +221,34 @@ void CXXNameMangler::mangleGuardVariable(const VarDecl *D) void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // <encoding> ::= <function name> <bare-function-type> mangleName(FD); - - // Whether the mangling of a function type includes the return type depends - // on the context and the nature of the function. The rules for deciding - // whether the return type is included are: - // + + // Whether the mangling of a function type includes the return type depends on + // the context and the nature of the function. The rules for deciding whether + // the return type is included are: + // // 1. Template functions (names or types) have return types encoded, with // the exceptions listed below. - // 2. Function types not appearing as part of a function name mangling, + // 2. Function types not appearing as part of a function name mangling, // e.g. parameters, pointer types, etc., have return type encoded, with the // exceptions listed below. // 3. Non-template function names do not have return types encoded. // - // The exceptions mentioned in (1) and (2) above, for which the return - // type is never included, are + // The exceptions mentioned in (1) and (2) above, for which the return type is + // never included, are // 1. Constructors. // 2. Destructors. // 3. Conversion operator functions, e.g. operator int. bool MangleReturnType = false; - if (FD->getPrimaryTemplate() && - !(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) || - isa<CXXConversionDecl>(FD))) - MangleReturnType = true; - mangleBareFunctionType(FD->getType()->getAsFunctionType(), MangleReturnType); + if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) { + if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) || + isa<CXXConversionDecl>(FD))) + MangleReturnType = true; + + // Mangle the type of the primary template. + FD = PrimaryTemplate->getTemplatedDecl(); + } + + mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), MangleReturnType); } static bool isStdNamespace(const DeclContext *DC) { @@ -200,37 +256,196 @@ static bool isStdNamespace(const DeclContext *DC) { return false; const NamespaceDecl *NS = cast<NamespaceDecl>(DC); - return NS->getOriginalNamespace()->getIdentifier()->isStr("std"); + const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); + return II && II->isStr("std"); +} + +static const TemplateDecl * +isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { + // Check if we have a function template. + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){ + if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { + TemplateArgs = FD->getTemplateSpecializationArgs(); + return TD; + } + } + + // Check if we have a class template. + if (const ClassTemplateSpecializationDecl *Spec = + dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); + return Spec->getSpecializedTemplate(); + } + + return 0; } void CXXNameMangler::mangleName(const NamedDecl *ND) { // <name> ::= <nested-name> // ::= <unscoped-name> // ::= <unscoped-template-name> <template-args> - // ::= <local-name> # See Scope Encoding below + // ::= <local-name> // + const DeclContext *DC = ND->getDeclContext(); + while (isa<LinkageSpecDecl>(DC)) + DC = DC->getParent(); + + if (DC->isTranslationUnit() || isStdNamespace(DC)) { + // Check if we have a template. + const TemplateArgumentList *TemplateArgs = 0; + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { + mangleUnscopedTemplateName(TD); + mangleTemplateArgumentList(*TemplateArgs); + return; + } + + mangleUnscopedName(ND); + return; + } + + if (isa<FunctionDecl>(DC)) { + mangleLocalName(ND); + return; + } + + mangleNestedName(ND); +} +void CXXNameMangler::mangleName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + const DeclContext *DC = TD->getDeclContext(); + while (isa<LinkageSpecDecl>(DC)) { + assert(cast<LinkageSpecDecl>(DC)->getLanguage() == + LinkageSpecDecl::lang_cxx && "Unexpected linkage decl!"); + DC = DC->getParent(); + } + + if (DC->isTranslationUnit() || isStdNamespace(DC)) { + mangleUnscopedTemplateName(TD); + mangleTemplateArgs(TemplateArgs, NumTemplateArgs); + } else { + mangleNestedName(TD, TemplateArgs, NumTemplateArgs); + } +} + +void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) { // <unscoped-name> ::= <unqualified-name> // ::= St <unqualified-name> # ::std:: - if (ND->getDeclContext()->isTranslationUnit()) - mangleUnqualifiedName(ND); - else if (isStdNamespace(ND->getDeclContext())) { + if (isStdNamespace(ND->getDeclContext())) Out << "St"; - mangleUnqualifiedName(ND); - } else if (isa<FunctionDecl>(ND->getDeclContext())) - mangleLocalName(ND); - else - mangleNestedName(ND); + + mangleUnqualifiedName(ND); +} + +void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) { + // <unscoped-template-name> ::= <unscoped-name> + // ::= <substitution> + if (mangleSubstitution(ND)) + return; + + mangleUnscopedName(ND->getTemplatedDecl()); + addSubstitution(ND); +} + +void CXXNameMangler::mangleCalloffset(int64_t nv, int64_t v) { + // <call-offset> ::= h <nv-offset> _ + // ::= v <v-offset> _ + // <nv-offset> ::= <offset number> # non-virtual base override + // <v-offset> ::= <offset nubmer> _ <virtual offset number> + // # virtual base override, with vcall offset + if (v == 0) { + Out << "h"; + if (nv < 0) { + Out << "n"; + nv = -nv; + } + Out << nv; + } else { + Out << "v"; + if (nv < 0) { + Out << "n"; + nv = -nv; + } + Out << nv; + Out << "_"; + if (v < 0) { + Out << "n"; + v = -v; + } + Out << v; + } + Out << "_"; +} + +void CXXNameMangler::mangleThunk(const FunctionDecl *FD, int64_t nv, + int64_t v) { + // <special-name> ::= T <call-offset> <base encoding> + // # base is the nominal target function of thunk + Out << "_ZT"; + mangleCalloffset(nv, v); + mangleFunctionEncoding(FD); +} + + void CXXNameMangler::mangleCovariantThunk(const FunctionDecl *FD, + int64_t nv_t, int64_t v_t, + int64_t nv_r, int64_t v_r) { + // <special-name> ::= Tc <call-offset> <call-offset> <base encoding> + // # base is the nominal target function of thunk + // # first call-offset is 'this' adjustment + // # second call-offset is result adjustment + Out << "_ZTc"; + mangleCalloffset(nv_t, v_t); + mangleCalloffset(nv_r, v_r); + mangleFunctionEncoding(FD); } void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { // <unqualified-name> ::= <operator-name> - // ::= <ctor-dtor-name> - // ::= <source-name> + // ::= <ctor-dtor-name> + // ::= <source-name> DeclarationName Name = ND->getDeclName(); switch (Name.getNameKind()) { - case DeclarationName::Identifier: - mangleSourceName(Name.getAsIdentifierInfo()); + case DeclarationName::Identifier: { + if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { + if (NS->isAnonymousNamespace()) { + // This is how gcc mangles these names. It's apparently + // always '1', no matter how many different anonymous + // namespaces appear in a context. + Out << "12_GLOBAL__N_1"; + break; + } + } + + if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { + mangleSourceName(II); + break; + } + + // We must have an anonymous struct. + const TagDecl *TD = cast<TagDecl>(ND); + if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { + assert(TD->getDeclContext() == D->getDeclContext() && + "Typedef should not be in another decl context!"); + assert(D->getDeclName().getAsIdentifierInfo() && + "Typedef was not named!"); + mangleSourceName(D->getDeclName().getAsIdentifierInfo()); + break; + } + + // Get a unique id for the anonymous struct. + uint64_t AnonStructId = Context.getAnonymousStructId(TD); + + // Mangle it as a source name in the form + // [n] $_<id> + // where n is the length of the string. + llvm::SmallString<8> Str; + Str += "$_"; + Str += llvm::utostr(AnonStructId); + + Out << Str.size(); + Out << Str.str(); break; + } case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: @@ -240,8 +455,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { case DeclarationName::CXXConstructorName: if (ND == Structor) - // If the named decl is the C++ constructor we're mangling, use the - // type we were given. + // If the named decl is the C++ constructor we're mangling, use the type + // we were given. mangleCXXCtorType(static_cast<CXXCtorType>(StructorType)); else // Otherwise, use the complete constructor name. This is relevant if a @@ -251,8 +466,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { case DeclarationName::CXXDestructorName: if (ND == Structor) - // If the named decl is the C++ destructor we're mangling, use the - // type we were given. + // If the named decl is the C++ destructor we're mangling, use the type we + // were given. mangleCXXDtorType(static_cast<CXXDtorType>(StructorType)); else // Otherwise, use the complete destructor name. This is relevant if a @@ -261,9 +476,9 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { break; case DeclarationName::CXXConversionFunctionName: - // <operator-name> ::= cv <type> # (cast) + // <operator-name> ::= cv <type> # (cast) Out << "cv"; - mangleType(Context.getCanonicalType(Name.getCXXNameType())); + mangleType(Context.getASTContext().getCanonicalType(Name.getCXXNameType())); break; case DeclarationName::CXXOperatorName: @@ -275,12 +490,6 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { assert(false && "Can't mangle a using directive name!"); break; } - - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { - if (const TemplateArgumentList *TemplateArgs - = Function->getTemplateSpecializationArgs()) - mangleTemplateArgumentList(*TemplateArgs); - } } void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { @@ -293,19 +502,40 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { void CXXNameMangler::mangleNestedName(const NamedDecl *ND) { // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E - // FIXME: no template support + Out << 'N'; if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) - mangleCVQualifiers(Method->getTypeQualifiers()); - manglePrefix(ND->getDeclContext()); - mangleUnqualifiedName(ND); + mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers())); + + // Check if we have a template. + const TemplateArgumentList *TemplateArgs = 0; + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { + mangleTemplatePrefix(TD); + mangleTemplateArgumentList(*TemplateArgs); + } else { + manglePrefix(ND->getDeclContext()); + mangleUnqualifiedName(ND); + } + + Out << 'E'; +} +void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + // <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E + + Out << 'N'; + + mangleTemplatePrefix(TD); + mangleTemplateArgs(TemplateArgs, NumTemplateArgs); + Out << 'E'; } void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] - // <discriminator> := _ <non-negative number> + // <discriminator> := _ <non-negative number> Out << 'Z'; mangleFunctionEncoding(cast<FunctionDecl>(ND->getDeclContext())); Out << 'E'; @@ -319,21 +549,46 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) { // ::= # empty // ::= <substitution> // FIXME: We only handle mangling of namespaces and classes at the moment. - if (!DC->getParent()->isTranslationUnit()) - manglePrefix(DC->getParent()); - if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(DC)) - mangleSourceName(Namespace->getIdentifier()); - else if (const RecordDecl *Record = dyn_cast<RecordDecl>(DC)) { - if (const ClassTemplateSpecializationDecl *D = - dyn_cast<ClassTemplateSpecializationDecl>(Record)) { - mangleType(QualType(D->getTypeForDecl(), 0)); - } else - mangleSourceName(Record->getIdentifier()); + while (isa<LinkageSpecDecl>(DC)) + DC = DC->getParent(); + + if (DC->isTranslationUnit()) + return; + + if (mangleSubstitution(cast<NamedDecl>(DC))) + return; + + // Check if we have a template. + const TemplateArgumentList *TemplateArgs = 0; + if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) { + mangleTemplatePrefix(TD); + mangleTemplateArgumentList(*TemplateArgs); + } else { + manglePrefix(DC->getParent()); + mangleUnqualifiedName(cast<NamedDecl>(DC)); } + + addSubstitution(cast<NamedDecl>(DC)); +} + +void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) { + // <template-prefix> ::= <prefix> <template unqualified-name> + // ::= <template-param> + // ::= <substitution> + + if (mangleSubstitution(ND)) + return; + + // FIXME: <template-param> + + manglePrefix(ND->getDeclContext()); + mangleUnqualifiedName(ND->getTemplatedDecl()); + + addSubstitution(ND); } -void +void CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { switch (OO) { // <operator-name> ::= nw # new @@ -429,88 +684,58 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) { case OO_None: case OO_Conditional: case NUM_OVERLOADED_OPERATORS: - assert(false && "Not an overloaded operator"); + assert(false && "Not an overloaded operator"); break; } } -void CXXNameMangler::mangleCVQualifiers(unsigned Quals) { - // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const - if (Quals & QualType::Restrict) +void CXXNameMangler::mangleQualifiers(Qualifiers Quals) { + // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const + if (Quals.hasRestrict()) Out << 'r'; - if (Quals & QualType::Volatile) + if (Quals.hasVolatile()) Out << 'V'; - if (Quals & QualType::Const) + if (Quals.hasConst()) Out << 'K'; + + // FIXME: For now, just drop all extension qualifiers on the floor. } void CXXNameMangler::mangleType(QualType T) { // Only operate on the canonical type! - T = Context.getCanonicalType(T); - - // FIXME: Should we have a TypeNodes.def to make this easier? (YES!) - - // <type> ::= <CV-qualifiers> <type> - mangleCVQualifiers(T.getCVRQualifiers()); - - // ::= <builtin-type> - if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) - mangleType(BT); - // ::= <function-type> - else if (const FunctionType *FT = dyn_cast<FunctionType>(T.getTypePtr())) - mangleType(FT); - // ::= <class-enum-type> - else if (const TagType *TT = dyn_cast<TagType>(T.getTypePtr())) - mangleType(TT); - // ::= <array-type> - else if (const ArrayType *AT = dyn_cast<ArrayType>(T.getTypePtr())) - mangleType(AT); - // ::= <pointer-to-member-type> - else if (const MemberPointerType *MPT - = dyn_cast<MemberPointerType>(T.getTypePtr())) - mangleType(MPT); - // ::= <template-param> - else if (const TemplateTypeParmType *TypeParm - = dyn_cast<TemplateTypeParmType>(T.getTypePtr())) - mangleType(TypeParm); - // FIXME: ::= <template-template-param> <template-args> - // FIXME: ::= <substitution> # See Compression below - // ::= P <type> # pointer-to - else if (const PointerType *PT = dyn_cast<PointerType>(T.getTypePtr())) { - Out << 'P'; - mangleType(PT->getPointeeType()); - } - // ::= R <type> # reference-to - else if (const LValueReferenceType *RT = - dyn_cast<LValueReferenceType>(T.getTypePtr())) { - Out << 'R'; - mangleType(RT->getPointeeType()); - } - // ::= O <type> # rvalue reference-to (C++0x) - else if (const RValueReferenceType *RT = - dyn_cast<RValueReferenceType>(T.getTypePtr())) { - Out << 'O'; - mangleType(RT->getPointeeType()); - } - // ::= C <type> # complex pair (C 2000) - else if (const ComplexType *CT = dyn_cast<ComplexType>(T.getTypePtr())) { - Out << 'C'; - mangleType(CT->getElementType()); - } else if (const VectorType *VT = dyn_cast<VectorType>(T.getTypePtr())) { - // GNU extension: vector types - Out << "U8__vector"; - mangleType(VT->getElementType()); - } else if (const ObjCInterfaceType *IT = - dyn_cast<ObjCInterfaceType>(T.getTypePtr())) { - mangleType(IT); - } - // FIXME: ::= G <type> # imaginary (C 2000) - // FIXME: ::= U <source-name> <type> # vendor extended type qualifier - else - assert(false && "Cannot mangle unknown type"); + T = Context.getASTContext().getCanonicalType(T); + + bool IsSubstitutable = !isa<BuiltinType>(T); + if (IsSubstitutable && mangleSubstitution(T)) + return; + + if (Qualifiers Quals = T.getQualifiers()) { + mangleQualifiers(Quals); + // Recurse: even if the qualified type isn't yet substitutable, + // the unqualified type might be. + mangleType(T.getUnqualifiedType()); + } else { + switch (T->getTypeClass()) { +#define ABSTRACT_TYPE(CLASS, PARENT) +#define NON_CANONICAL_TYPE(CLASS, PARENT) \ + case Type::CLASS: \ + llvm::llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \ + return; +#define TYPE(CLASS, PARENT) \ + case Type::CLASS: \ + mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \ + break; +#include "clang/AST/TypeNodes.def" + } + } + + // Add the substitution. + if (IsSubstitutable) + addSubstitution(T); } void CXXNameMangler::mangleType(const BuiltinType *T) { + // <type> ::= <builtin-type> // <builtin-type> ::= v # void // ::= w # wchar_t // ::= b # bool @@ -535,8 +760,8 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits) // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits) // UNSUPPORTED: ::= Dh # IEEE 754r half-precision floating point (16 bits) - // UNSUPPORTED: ::= Di # char32_t - // UNSUPPORTED: ::= Ds # char16_t + // ::= Di # char32_t + // ::= Ds # char16_t // ::= u <source-name> # vendor extended type // From our point of view, std::nullptr_t is a builtin, but as far as mangling // is concerned, it's a type called std::nullptr_t. @@ -552,6 +777,8 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::UInt128: Out << 'o'; break; case BuiltinType::SChar: Out << 'a'; break; case BuiltinType::WChar: Out << 'w'; break; + case BuiltinType::Char16: Out << "Ds"; break; + case BuiltinType::Char32: Out << "Di"; break; case BuiltinType::Short: Out << 's'; break; case BuiltinType::Int: Out << 'i'; break; case BuiltinType::Long: Out << 'l'; break; @@ -564,40 +791,45 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Overload: case BuiltinType::Dependent: - assert(false && + assert(false && "Overloaded and dependent types shouldn't get to name mangling"); break; case BuiltinType::UndeducedAuto: assert(0 && "Should not see undeduced auto here"); break; + case BuiltinType::ObjCId: Out << "11objc_object"; break; + case BuiltinType::ObjCClass: Out << "10objc_class"; break; } } -void CXXNameMangler::mangleType(const FunctionType *T) { - // <function-type> ::= F [Y] <bare-function-type> E +// <type> ::= <function-type> +// <function-type> ::= F [Y] <bare-function-type> E +void CXXNameMangler::mangleType(const FunctionProtoType *T) { Out << 'F'; // FIXME: We don't have enough information in the AST to produce the 'Y' // encoding for extern "C" function types. mangleBareFunctionType(T, /*MangleReturnType=*/true); Out << 'E'; } - +void CXXNameMangler::mangleType(const FunctionNoProtoType *T) { + llvm::llvm_unreachable("Can't mangle K&R function prototypes"); +} void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, bool MangleReturnType) { + // We should never be mangling something without a prototype. + const FunctionProtoType *Proto = cast<FunctionProtoType>(T); + // <bare-function-type> ::= <signature type>+ if (MangleReturnType) - mangleType(T->getResultType()); - - const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T); - assert(Proto && "Can't mangle K&R function prototypes"); + mangleType(Proto->getResultType()); if (Proto->getNumArgs() == 0) { Out << 'v'; return; } - + for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); + ArgEnd = Proto->arg_type_end(); Arg != ArgEnd; ++Arg) mangleType(*Arg); @@ -606,66 +838,207 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, Out << 'z'; } +// <type> ::= <class-enum-type> +// <class-enum-type> ::= <name> +void CXXNameMangler::mangleType(const EnumType *T) { + mangleType(static_cast<const TagType*>(T)); +} +void CXXNameMangler::mangleType(const RecordType *T) { + mangleType(static_cast<const TagType*>(T)); +} void CXXNameMangler::mangleType(const TagType *T) { - // <class-enum-type> ::= <name> - if (!T->getDecl()->getIdentifier()) mangleName(T->getDecl()->getTypedefForAnonDecl()); else mangleName(T->getDecl()); - - // If this is a class template specialization, mangle the template - // arguments. - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) - mangleTemplateArgumentList(Spec->getTemplateArgs()); } -void CXXNameMangler::mangleType(const ArrayType *T) { - // <array-type> ::= A <positive dimension number> _ <element type> - // ::= A [<dimension expression>] _ <element type> +// <type> ::= <array-type> +// <array-type> ::= A <positive dimension number> _ <element type> +// ::= A [<dimension expression>] _ <element type> +void CXXNameMangler::mangleType(const ConstantArrayType *T) { + Out << 'A' << T->getSize() << '_'; + mangleType(T->getElementType()); +} +void CXXNameMangler::mangleType(const VariableArrayType *T) { Out << 'A'; - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) - Out << CAT->getSize(); - else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(T)) - mangleExpression(VAT->getSizeExpr()); - else if (const DependentSizedArrayType *DSAT - = dyn_cast<DependentSizedArrayType>(T)) - mangleExpression(DSAT->getSizeExpr()); - + mangleExpression(T->getSizeExpr()); Out << '_'; mangleType(T->getElementType()); } +void CXXNameMangler::mangleType(const DependentSizedArrayType *T) { + Out << 'A'; + mangleExpression(T->getSizeExpr()); + Out << '_'; + mangleType(T->getElementType()); +} +void CXXNameMangler::mangleType(const IncompleteArrayType *T) { + Out << 'A' << '_'; + mangleType(T->getElementType()); +} +// <type> ::= <pointer-to-member-type> +// <pointer-to-member-type> ::= M <class type> <member type> void CXXNameMangler::mangleType(const MemberPointerType *T) { - // <pointer-to-member-type> ::= M <class type> <member type> Out << 'M'; mangleType(QualType(T->getClass(), 0)); QualType PointeeType = T->getPointeeType(); if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) { - mangleCVQualifiers(FPT->getTypeQuals()); + mangleQualifiers(Qualifiers::fromCVRMask(FPT->getTypeQuals())); mangleType(FPT); - } else + } else mangleType(PointeeType); } +// <type> ::= <template-param> void CXXNameMangler::mangleType(const TemplateTypeParmType *T) { - // <template-param> ::= T_ # first template parameter - // ::= T <parameter-2 non-negative number> _ - if (T->getIndex() == 0) - Out << "T_"; - else - Out << 'T' << (T->getIndex() - 1) << '_'; + mangleTemplateParameter(T->getIndex()); +} + +// FIXME: <type> ::= <template-template-param> <template-args> + +// <type> ::= P <type> # pointer-to +void CXXNameMangler::mangleType(const PointerType *T) { + Out << 'P'; + mangleType(T->getPointeeType()); +} +void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) { + Out << 'P'; + mangleType(T->getPointeeType()); +} + +// <type> ::= R <type> # reference-to +void CXXNameMangler::mangleType(const LValueReferenceType *T) { + Out << 'R'; + mangleType(T->getPointeeType()); +} + +// <type> ::= O <type> # rvalue reference-to (C++0x) +void CXXNameMangler::mangleType(const RValueReferenceType *T) { + Out << 'O'; + mangleType(T->getPointeeType()); +} + +// <type> ::= C <type> # complex pair (C 2000) +void CXXNameMangler::mangleType(const ComplexType *T) { + Out << 'C'; + mangleType(T->getElementType()); +} + +// GNU extension: vector types +void CXXNameMangler::mangleType(const VectorType *T) { + Out << "U8__vector"; + mangleType(T->getElementType()); +} +void CXXNameMangler::mangleType(const ExtVectorType *T) { + mangleType(static_cast<const VectorType*>(T)); +} +void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) { + Out << "U8__vector"; + mangleType(T->getElementType()); } void CXXNameMangler::mangleType(const ObjCInterfaceType *T) { mangleSourceName(T->getDecl()->getIdentifier()); } -void CXXNameMangler::mangleExpression(Expr *E) { - assert(false && "Cannot mangle expressions yet"); +void CXXNameMangler::mangleType(const BlockPointerType *T) { + assert(false && "can't mangle block pointer types yet"); } +void CXXNameMangler::mangleType(const FixedWidthIntType *T) { + assert(false && "can't mangle arbitary-precision integer type yet"); +} + +void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { + TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl(); + assert(TD && "FIXME: Support dependent template names!"); + + mangleName(TD, T->getArgs(), T->getNumArgs()); +} + +void CXXNameMangler::mangleType(const TypenameType *T) { + // Typename types are always nested + Out << 'N'; + + const Type *QTy = T->getQualifier()->getAsType(); + if (const TemplateSpecializationType *TST = + dyn_cast<TemplateSpecializationType>(QTy)) { + if (!mangleSubstitution(QualType(TST, 0))) { + TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl(); + + mangleTemplatePrefix(TD); + mangleTemplateArgs(TST->getArgs(), TST->getNumArgs()); + addSubstitution(QualType(TST, 0)); + } + } else if (const TemplateTypeParmType *TTPT = + dyn_cast<TemplateTypeParmType>(QTy)) { + // We use the QualType mangle type variant here because it handles + // substitutions. + mangleType(QualType(TTPT, 0)); + } else + assert(false && "Unhandled type!"); + + mangleSourceName(T->getIdentifier()); + + Out << 'E'; +} + +void CXXNameMangler::mangleExpression(const Expr *E) { + // <expression> ::= <unary operator-name> <expression> + // ::= <binary operator-name> <expression> <expression> + // ::= <trinary operator-name> <expression> <expression> <expression> + // ::= cl <expression>* E # call + // ::= cv <type> expression # conversion with one argument + // ::= cv <type> _ <expression>* E # conversion with a different number of arguments + // ::= st <type> # sizeof (a type) + // ::= at <type> # alignof (a type) + // ::= <template-param> + // ::= <function-param> + // ::= sr <type> <unqualified-name> # dependent name + // ::= sr <type> <unqualified-name> <template-args> # dependent template-id + // ::= sZ <template-param> # size of a parameter pack + // ::= <expr-primary> + switch (E->getStmtClass()) { + default: assert(false && "Unhandled expression kind!"); + case Expr::DeclRefExprClass: { + const Decl *D = cast<DeclRefExpr>(E)->getDecl(); + + switch (D->getKind()) { + default: assert(false && "Unhandled decl kind!"); + case Decl::NonTypeTemplateParm: { + const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D); + mangleTemplateParameter(PD->getIndex()); + break; + } + + } + + break; + } + + case Expr::UnresolvedDeclRefExprClass: { + const UnresolvedDeclRefExpr *DRE = cast<UnresolvedDeclRefExpr>(E); + const Type *QTy = DRE->getQualifier()->getAsType(); + assert(QTy && "Qualifier was not type!"); + + // ::= sr <type> <unqualified-name> # dependent name + Out << "sr"; + mangleType(QualType(QTy, 0)); + + assert(DRE->getDeclName().getNameKind() == DeclarationName::Identifier && + "Unhandled decl name kind!"); + mangleSourceName(DRE->getDeclName().getAsIdentifierInfo()); + + break; + } + + } +} + +// FIXME: <type> ::= G <type> # imaginary (C 2000) +// FIXME: <type> ::= U <source-name> <type> # vendor extended type qualifier + void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) { // <ctor-dtor-name> ::= C1 # complete object constructor // ::= C2 # base object constructor @@ -705,18 +1078,30 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { void CXXNameMangler::mangleTemplateArgumentList(const TemplateArgumentList &L) { // <template-args> ::= I <template-arg>+ E Out << "I"; - + for (unsigned i = 0, e = L.size(); i != e; ++i) { const TemplateArgument &A = L[i]; - + mangleTemplateArgument(A); } + + Out << "E"; +} + +void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + // <template-args> ::= I <template-arg>+ E + Out << "I"; + + for (unsigned i = 0; i != NumTemplateArgs; ++i) { + mangleTemplateArgument(TemplateArgs[i]); + } Out << "E"; } void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) { - // <template-arg> ::= <type> # type or template + // <template-arg> ::= <type> # type or template // ::= X <expression> E # expression // ::= <expr-primary> # simple expressions // ::= I <template-arg>* E # argument pack @@ -727,13 +1112,18 @@ void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) { case TemplateArgument::Type: mangleType(A.getAsType()); break; + case TemplateArgument::Expression: + Out << 'X'; + mangleExpression(A.getAsExpr()); + Out << 'E'; + break; case TemplateArgument::Integral: // <expr-primary> ::= L <type> <value number> E # integer literal Out << 'L'; - + mangleType(A.getIntegralType()); - + const llvm::APSInt *Integral = A.getAsIntegral(); if (A.getIntegralType()->isBooleanType()) { // Boolean values are encoded as 0/1. @@ -743,62 +1133,300 @@ void CXXNameMangler::mangleTemplateArgument(const TemplateArgument &A) { Out << 'n'; Integral->abs().print(Out, false); } - + Out << 'E'; break; } } +void CXXNameMangler::mangleTemplateParameter(unsigned Index) { + // <template-param> ::= T_ # first template parameter + // ::= T <parameter-2 non-negative number> _ + if (Index == 0) + Out << "T_"; + else + Out << 'T' << (Index - 1) << '_'; +} + +// <substitution> ::= S <seq-id> _ +// ::= S_ +bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { + // Try one of the standard substitutions first. + if (mangleStandardSubstitution(ND)) + return true; + + return mangleSubstitution(reinterpret_cast<uintptr_t>(ND)); +} + +bool CXXNameMangler::mangleSubstitution(QualType T) { + if (!T.getCVRQualifiers()) { + if (const RecordType *RT = T->getAs<RecordType>()) + return mangleSubstitution(RT->getDecl()); + } + + uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + + return mangleSubstitution(TypePtr); +} + +bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) { + llvm::DenseMap<uintptr_t, unsigned>::iterator I = + Substitutions.find(Ptr); + if (I == Substitutions.end()) + return false; + + unsigned SeqID = I->second; + if (SeqID == 0) + Out << "S_"; + else { + SeqID--; + + // <seq-id> is encoded in base-36, using digits and upper case letters. + char Buffer[10]; + char *BufferPtr = Buffer + 9; + + *BufferPtr = 0; + if (SeqID == 0) *--BufferPtr = '0'; + + while (SeqID) { + assert(BufferPtr > Buffer && "Buffer overflow!"); + + unsigned char c = static_cast<unsigned char>(SeqID) % 36; + + *--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10); + SeqID /= 36; + } + + Out << 'S' << BufferPtr << '_'; + } + + return true; +} + +static bool isCharType(QualType T) { + if (T.isNull()) + return false; + + return T->isSpecificBuiltinType(BuiltinType::Char_S) || + T->isSpecificBuiltinType(BuiltinType::Char_U); +} + +/// isCharSpecialization - Returns whether a given type is a template +/// specialization of a given name with a single argument of type char. +static bool isCharSpecialization(QualType T, const char *Name) { + if (T.isNull()) + return false; + + const RecordType *RT = T->getAs<RecordType>(); + if (!RT) + return false; + + const ClassTemplateSpecializationDecl *SD = + dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); + if (!SD) + return false; + + if (!isStdNamespace(SD->getDeclContext())) + return false; + + const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); + if (TemplateArgs.size() != 1) + return false; + + if (!isCharType(TemplateArgs[0].getAsType())) + return false; + + if (strcmp(SD->getIdentifier()->getName(), Name) != 0) + return false; + + return true; +} + +bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { + // <substitution> ::= St # ::std:: + if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { + if (isStdNamespace(NS)) { + Out << "St"; + return true; + } + } + + if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) { + if (!isStdNamespace(TD->getDeclContext())) + return false; + + // <substitution> ::= Sa # ::std::allocator + if (TD->getIdentifier()->isStr("allocator")) { + Out << "Sa"; + return true; + } + + // <<substitution> ::= Sb # ::std::basic_string + if (TD->getIdentifier()->isStr("basic_string")) { + Out << "Sb"; + return true; + } + } + + if (const ClassTemplateSpecializationDecl *SD = + dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + // <substitution> ::= Ss # ::std::basic_string<char, + // ::std::char_traits<char>, + // ::std::allocator<char> > + if (SD->getIdentifier()->isStr("basic_string")) { + const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); + + if (TemplateArgs.size() != 3) + return false; + + if (!isCharType(TemplateArgs[0].getAsType())) + return false; + + if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits")) + return false; + + if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator")) + return false; + + Out << "Ss"; + return true; + } + + // <substitution> ::= So # ::std::basic_ostream<char, + // ::std::char_traits<char> > + if (SD->getIdentifier()->isStr("basic_ostream")) { + const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs(); + + if (TemplateArgs.size() != 2) + return false; + + if (!isCharType(TemplateArgs[0].getAsType())) + return false; + + if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits")) + return false; + + Out << "So"; + return true; + } + } + return false; +} + +void CXXNameMangler::addSubstitution(QualType T) { + if (!T.getCVRQualifiers()) { + if (const RecordType *RT = T->getAs<RecordType>()) { + addSubstitution(RT->getDecl()); + return; + } + } + + uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + addSubstitution(TypePtr); +} + +void CXXNameMangler::addSubstitution(uintptr_t Ptr) { + unsigned SeqID = Substitutions.size(); + + assert(!Substitutions.count(Ptr) && "Substitution already exists!"); + Substitutions[Ptr] = SeqID; +} + namespace clang { - /// \brief Mangles the name of the declaration D and emits that name - /// to the given output stream. + /// \brief Mangles the name of the declaration D and emits that name to the + /// given output stream. /// - /// If the declaration D requires a mangled name, this routine will - /// emit that mangled name to \p os and return true. Otherwise, \p - /// os will be unchanged and this routine will return false. In this - /// case, the caller should just emit the identifier of the declaration - /// (\c D->getIdentifier()) as its name. - bool mangleName(const NamedDecl *D, ASTContext &Context, + /// If the declaration D requires a mangled name, this routine will emit that + /// mangled name to \p os and return true. Otherwise, \p os will be unchanged + /// and this routine will return false. In this case, the caller should just + /// emit the identifier of the declaration (\c D->getIdentifier()) as its + /// name. + bool mangleName(MangleContext &Context, const NamedDecl *D, llvm::raw_ostream &os) { assert(!isa<CXXConstructorDecl>(D) && "Use mangleCXXCtor for constructor decls!"); assert(!isa<CXXDestructorDecl>(D) && "Use mangleCXXDtor for destructor decls!"); + + PrettyStackTraceDecl CrashInfo(const_cast<NamedDecl *>(D), SourceLocation(), + Context.getASTContext().getSourceManager(), + "Mangling declaration"); CXXNameMangler Mangler(Context, os); - if (!Mangler.mangle(D)) + if (!Mangler.mangle(cast<NamedDecl>(D->getCanonicalDecl()))) return false; - + os.flush(); return true; } - + + /// \brief Mangles the a thunk with the offset n for the declaration D and + /// emits that name to the given output stream. + void mangleThunk(MangleContext &Context, const FunctionDecl *FD, + int64_t nv, int64_t v, llvm::raw_ostream &os) { + // FIXME: Hum, we might have to thunk these, fix. + assert(!isa<CXXDestructorDecl>(FD) && + "Use mangleCXXDtor for destructor decls!"); + + CXXNameMangler Mangler(Context, os); + Mangler.mangleThunk(FD, nv, v); + os.flush(); + } + + /// \brief Mangles the a covariant thunk for the declaration D and emits that + /// name to the given output stream. + void mangleCovariantThunk(MangleContext &Context, const FunctionDecl *FD, + int64_t nv_t, int64_t v_t, + int64_t nv_r, int64_t v_r, + llvm::raw_ostream &os) { + // FIXME: Hum, we might have to thunk these, fix. + assert(!isa<CXXDestructorDecl>(FD) && + "Use mangleCXXDtor for destructor decls!"); + + CXXNameMangler Mangler(Context, os); + Mangler.mangleCovariantThunk(FD, nv_t, v_t, nv_r, v_r); + os.flush(); + } + /// mangleGuardVariable - Returns the mangled name for a guard variable /// for the passed in VarDecl. - void mangleGuardVariable(const VarDecl *D, ASTContext &Context, + void mangleGuardVariable(MangleContext &Context, const VarDecl *D, llvm::raw_ostream &os) { CXXNameMangler Mangler(Context, os); Mangler.mangleGuardVariable(D); os.flush(); } - - void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - ASTContext &Context, llvm::raw_ostream &os) { + + void mangleCXXCtor(MangleContext &Context, const CXXConstructorDecl *D, + CXXCtorType Type, llvm::raw_ostream &os) { CXXNameMangler Mangler(Context, os); Mangler.mangleCXXCtor(D, Type); - + os.flush(); } - - void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - ASTContext &Context, llvm::raw_ostream &os) { + + void mangleCXXDtor(MangleContext &Context, const CXXDestructorDecl *D, + CXXDtorType Type, llvm::raw_ostream &os) { CXXNameMangler Mangler(Context, os); Mangler.mangleCXXDtor(D, Type); - + os.flush(); } - - -} + void mangleCXXVtable(MangleContext &Context, const CXXRecordDecl *RD, + llvm::raw_ostream &os) { + CXXNameMangler Mangler(Context, os); + Mangler.mangleCXXVtable(RD); + + os.flush(); + } + + void mangleCXXRtti(MangleContext &Context, const CXXRecordDecl *RD, + llvm::raw_ostream &os) { + CXXNameMangler Mangler(Context, os); + Mangler.mangleCXXRtti(RD); + + os.flush(); + } +} diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 77cbd97751916..2cdb4e23919da 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -19,6 +19,8 @@ #define LLVM_CLANG_CODEGEN_MANGLE_H #include "CGCXX.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" namespace llvm { class raw_ostream; @@ -28,17 +30,47 @@ namespace clang { class ASTContext; class CXXConstructorDecl; class CXXDestructorDecl; + class FunctionDecl; class NamedDecl; class VarDecl; - - bool mangleName(const NamedDecl *D, ASTContext &Context, + + class MangleContext { + ASTContext &Context; + + llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; + + public: + explicit MangleContext(ASTContext &Context) + : Context(Context) { } + + ASTContext &getASTContext() const { return Context; } + + uint64_t getAnonymousStructId(const TagDecl *TD) { + std::pair<llvm::DenseMap<const TagDecl *, + uint64_t>::iterator, bool> Result = + AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); + return Result.first->second; + } + }; + + bool mangleName(MangleContext &Context, const NamedDecl *D, llvm::raw_ostream &os); - void mangleGuardVariable(const VarDecl *D, ASTContext &Context, + void mangleThunk(MangleContext &Context, const FunctionDecl *FD, + int64_t n, int64_t vn, llvm::raw_ostream &os); + void mangleCovariantThunk(MangleContext &Context, const FunctionDecl *FD, + int64_t nv_t, int64_t v_t, + int64_t nv_r, int64_t v_r, + llvm::raw_ostream &os); + void mangleGuardVariable(MangleContext &Context, const VarDecl *D, llvm::raw_ostream &os); - void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, - ASTContext &Context, llvm::raw_ostream &os); - void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, - ASTContext &Context, llvm::raw_ostream &os); + void mangleCXXVtable(MangleContext &Context, const CXXRecordDecl *RD, + llvm::raw_ostream &os); + void mangleCXXRtti(MangleContext &Context, const CXXRecordDecl *RD, + llvm::raw_ostream &os); + void mangleCXXCtor(MangleContext &Context, const CXXConstructorDecl *D, + CXXCtorType Type, llvm::raw_ostream &os); + void mangleCXXDtor(MangleContext &Context, const CXXDestructorDecl *D, + CXXDtorType Type, llvm::raw_ostream &os); } -#endif +#endif diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 4835454b47df2..c8f686a06f50b 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -40,27 +40,27 @@ namespace { CodeGeneratorImpl(Diagnostic &diags, const std::string& ModuleName, const CompileOptions &CO, llvm::LLVMContext& C) : Diags(diags), CompileOpts(CO), M(new llvm::Module(ModuleName, C)) {} - + virtual ~CodeGeneratorImpl() {} - + virtual llvm::Module* GetModule() { return M.get(); } - + virtual llvm::Module* ReleaseModule() { return M.take(); } - + virtual void Initialize(ASTContext &Context) { Ctx = &Context; - - M->setTargetTriple(Ctx->Target.getTargetTriple()); + + M->setTargetTriple(Ctx->Target.getTriple().getTriple()); M->setDataLayout(Ctx->Target.getTargetDescription()); TD.reset(new llvm::TargetData(Ctx->Target.getTargetDescription())); Builder.reset(new CodeGen::CodeGenModule(Context, CompileOpts, *M, *TD, Diags)); } - + virtual void HandleTopLevelDecl(DeclGroupRef DG) { // Make sure to emit all elements of a Decl. for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) @@ -94,7 +94,7 @@ namespace { }; } -CodeGenerator *clang::CreateLLVMCodeGen(Diagnostic &Diags, +CodeGenerator *clang::CreateLLVMCodeGen(Diagnostic &Diags, const std::string& ModuleName, const CompileOptions &CO, llvm::LLVMContext& C) { diff --git a/lib/CodeGen/README.txt b/lib/CodeGen/README.txt index f60cd03ad6490..e6d61095bf234 100644 --- a/lib/CodeGen/README.txt +++ b/lib/CodeGen/README.txt @@ -45,21 +45,3 @@ On 176.gcc:expr.ll, it looks like over 12% of basic blocks are just direct branches! //===---------------------------------------------------------------------===// - -There are some more places where we could avoid generating unreachable code. For -example: - void f0(int a) { abort(); if (a) printf("hi"); } -still generates a call to printf. This doesn't occur much in real -code, but would still be nice to clean up. - -//===---------------------------------------------------------------------===// - -Deferred generation of statics incurs some additional -overhead. Currently it is even possible to construct test cases with -O(N^2) behavior! For at least simple cases where we can tell a global -is used, it is probably not worth deferring it. This doesn't solve the -O(N^2) cases, ,though... - -PR3810 - -//===---------------------------------------------------------------------===// diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp index 896dbd685037f..59f579f7b17e1 100644 --- a/lib/CodeGen/TargetABIInfo.cpp +++ b/lib/CodeGen/TargetABIInfo.cpp @@ -16,6 +16,8 @@ #include "CodeGenFunction.h" #include "clang/AST/RecordLayout.h" #include "llvm/Type.h" +#include "llvm/ADT/Triple.h" +#include <cstdio> using namespace clang; using namespace CodeGen; @@ -48,27 +50,30 @@ void ABIArgInfo::dump() const { fprintf(stderr, ")\n"); } -static bool isEmptyRecord(ASTContext &Context, QualType T); +static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays); /// isEmptyField - Return true iff a the field is "empty", that is it /// is an unnamed bit-field or an (array of) empty record(s). -static bool isEmptyField(ASTContext &Context, const FieldDecl *FD) { +static bool isEmptyField(ASTContext &Context, const FieldDecl *FD, + bool AllowArrays) { if (FD->isUnnamedBitfield()) return true; QualType FT = FD->getType(); - // Constant arrays of empty records count as empty, strip them off. - while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) - FT = AT->getElementType(); - return isEmptyRecord(Context, FT); + // Constant arrays of empty records count as empty, strip them off. + if (AllowArrays) + while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) + FT = AT->getElementType(); + + return isEmptyRecord(Context, FT, AllowArrays); } /// isEmptyRecord - Return true iff a structure contains only empty /// fields. Note that a structure with a flexible array member is not /// considered empty. -static bool isEmptyRecord(ASTContext &Context, QualType T) { - const RecordType *RT = T->getAsRecordType(); +static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) { + const RecordType *RT = T->getAs<RecordType>(); if (!RT) return 0; const RecordDecl *RD = RT->getDecl(); @@ -76,11 +81,32 @@ static bool isEmptyRecord(ASTContext &Context, QualType T) { return false; for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i) - if (!isEmptyField(Context, *i)) + if (!isEmptyField(Context, *i, AllowArrays)) return false; return true; } +/// hasNonTrivialDestructorOrCopyConstructor - Determine if a type has either +/// a non-trivial destructor or a non-trivial copy constructor. +static bool hasNonTrivialDestructorOrCopyConstructor(const RecordType *RT) { + const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); + if (!RD) + return false; + + return !RD->hasTrivialDestructor() || !RD->hasTrivialCopyConstructor(); +} + +/// isRecordWithNonTrivialDestructorOrCopyConstructor - Determine if a type is +/// a record type with either a non-trivial destructor or a non-trivial copy +/// constructor. +static bool isRecordWithNonTrivialDestructorOrCopyConstructor(QualType T) { + const RecordType *RT = T->getAs<RecordType>(); + if (!RT) + return false; + + return hasNonTrivialDestructorOrCopyConstructor(RT); +} + /// isSingleElementStruct - Determine if a structure is a "single /// element struct", i.e. it has exactly one non-empty field or /// exactly one field which is itself a single element @@ -105,7 +131,7 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) { QualType FT = FD->getType(); // Ignore empty fields. - if (isEmptyField(Context, FD)) + if (isEmptyField(Context, FD, true)) continue; // If we already found an element then this isn't a single-element @@ -133,7 +159,9 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) { } static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) { - if (!Ty->getAsBuiltinType() && !Ty->isPointerType()) + if (!Ty->getAs<BuiltinType>() && !Ty->isAnyPointerType() && + !Ty->isAnyComplexType() && !Ty->isEnumeralType() && + !Ty->isBlockPointerType()) return false; uint64_t Size = Context.getTypeSize(Ty); @@ -168,7 +196,7 @@ static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) { Context.getTypeSize(FD->getType()) >= 128) return true; - if (const RecordType* RT = FD->getType()->getAsRecordType()) + if (const RecordType* RT = FD->getType()->getAs<RecordType>()) if (typeContainsSSEVector(RT->getDecl(), Context)) return true; } @@ -183,16 +211,20 @@ namespace { /// conform to any particular ABI. class DefaultABIInfo : public ABIInfo { ABIArgInfo classifyReturnType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; ABIArgInfo classifyArgumentType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; - virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context); + virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context, + VMContext); for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) - it->info = classifyArgumentType(it->type, Context); + it->info = classifyArgumentType(it->type, Context, VMContext); } virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, @@ -202,7 +234,8 @@ class DefaultABIInfo : public ABIInfo { /// X86_32ABIInfo - The X86-32 ABI information. class X86_32ABIInfo : public ABIInfo { ASTContext &Context; - bool IsDarwin; + bool IsDarwinVectorABI; + bool IsSmallStructInRegABI; static bool isRegisterSize(unsigned Size) { return (Size == 8 || Size == 16 || Size == 32 || Size == 64); @@ -215,23 +248,28 @@ class X86_32ABIInfo : public ABIInfo { public: ABIArgInfo classifyReturnType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; ABIArgInfo classifyArgumentType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; - virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context); + virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context, + VMContext); for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) - it->info = classifyArgumentType(it->type, Context); + it->info = classifyArgumentType(it->type, Context, VMContext); } virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const; - X86_32ABIInfo(ASTContext &Context, bool d) - : ABIInfo(), Context(Context), IsDarwin(d) {} + X86_32ABIInfo(ASTContext &Context, bool d, bool p) + : ABIInfo(), Context(Context), IsDarwinVectorABI(d), + IsSmallStructInRegABI(p) {} }; } @@ -255,8 +293,10 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, return true; } - // If this is a builtin, pointer, or complex type, it is ok. - if (Ty->getAsBuiltinType() || Ty->isPointerType() || Ty->isAnyComplexType()) + // If this is a builtin, pointer, enum, or complex type, it is ok. + if (Ty->getAs<BuiltinType>() || Ty->isAnyPointerType() || + Ty->isAnyComplexType() || Ty->isEnumeralType() || + Ty->isBlockPointerType()) return true; // Arrays are treated like records. @@ -264,7 +304,7 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, return shouldReturnTypeInRegister(AT->getElementType(), Context); // Otherwise, it must be a record type. - const RecordType *RT = Ty->getAsRecordType(); + const RecordType *RT = Ty->getAs<RecordType>(); if (!RT) return false; // Structure types are passed in register if all fields would be @@ -274,7 +314,7 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, const FieldDecl *FD = *i; // Empty fields are ignored. - if (isEmptyField(Context, FD)) + if (isEmptyField(Context, FD, true)) continue; // Check fields recursively. @@ -286,26 +326,27 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, } ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, - ASTContext &Context) const { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { if (RetTy->isVoidType()) { return ABIArgInfo::getIgnore(); - } else if (const VectorType *VT = RetTy->getAsVectorType()) { + } else if (const VectorType *VT = RetTy->getAs<VectorType>()) { // On Darwin, some vectors are returned in registers. - if (IsDarwin) { + if (IsDarwinVectorABI) { uint64_t Size = Context.getTypeSize(RetTy); // 128-bit vectors are a special case; they are returned in // registers and we need to make sure to pick a type the LLVM // backend will like. if (Size == 128) - return ABIArgInfo::getCoerce(llvm::VectorType::get(llvm::Type::Int64Ty, - 2)); + return ABIArgInfo::getCoerce(llvm::VectorType::get( + llvm::Type::getInt64Ty(VMContext), 2)); // Always return in register if it fits in a general purpose // register, or if it is 64 bits and has a single element. if ((Size == 8 || Size == 16 || Size == 32) || (Size == 64 && VT->getNumElements() == 1)) - return ABIArgInfo::getCoerce(llvm::IntegerType::get(Size)); + return ABIArgInfo::getCoerce(llvm::IntegerType::get(VMContext, Size)); return ABIArgInfo::getIndirect(0); } @@ -317,33 +358,33 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, if (RT->getDecl()->hasFlexibleArrayMember()) return ABIArgInfo::getIndirect(0); - // Outside of Darwin, structs and unions are always indirect. - if (!IsDarwin && !RetTy->isAnyComplexType()) + // If specified, structs and unions are always indirect. + if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType()) return ABIArgInfo::getIndirect(0); // Classify "single element" structs as their element type. if (const Type *SeltTy = isSingleElementStruct(RetTy, Context)) { - if (const BuiltinType *BT = SeltTy->getAsBuiltinType()) { + if (const BuiltinType *BT = SeltTy->getAs<BuiltinType>()) { if (BT->isIntegerType()) { // We need to use the size of the structure, padding // bit-fields can adjust that to be larger than the single // element type. uint64_t Size = Context.getTypeSize(RetTy); - return ABIArgInfo::getCoerce(llvm::IntegerType::get((unsigned) Size)); + return ABIArgInfo::getCoerce( + llvm::IntegerType::get(VMContext, (unsigned) Size)); } else if (BT->getKind() == BuiltinType::Float) { assert(Context.getTypeSize(RetTy) == Context.getTypeSize(SeltTy) && "Unexpect single element structure size!"); - return ABIArgInfo::getCoerce(llvm::Type::FloatTy); + return ABIArgInfo::getCoerce(llvm::Type::getFloatTy(VMContext)); } else if (BT->getKind() == BuiltinType::Double) { assert(Context.getTypeSize(RetTy) == Context.getTypeSize(SeltTy) && "Unexpect single element structure size!"); - return ABIArgInfo::getCoerce(llvm::Type::DoubleTy); + return ABIArgInfo::getCoerce(llvm::Type::getDoubleTy(VMContext)); } } else if (SeltTy->isPointerType()) { // FIXME: It would be really nice if this could come out as the proper // pointer type. - llvm::Type *PtrTy = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); return ABIArgInfo::getCoerce(PtrTy); } else if (SeltTy->isVectorType()) { // 64- and 128-bit vectors are never returned in a @@ -352,7 +393,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, if (Size == 64 || Size == 128) return ABIArgInfo::getIndirect(0); - return classifyReturnType(QualType(SeltTy, 0), Context); + return classifyReturnType(QualType(SeltTy, 0), Context, VMContext); } } @@ -360,7 +401,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, // in a register. if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, Context)) { uint64_t Size = Context.getTypeSize(RetTy); - return ABIArgInfo::getCoerce(llvm::IntegerType::get(Size)); + return ABIArgInfo::getCoerce(llvm::IntegerType::get(VMContext, Size)); } return ABIArgInfo::getIndirect(0); @@ -374,20 +415,21 @@ unsigned X86_32ABIInfo::getIndirectArgumentAlignment(QualType Ty, ASTContext &Context) { unsigned Align = Context.getTypeAlign(Ty); if (Align < 128) return 0; - if (const RecordType* RT = Ty->getAsRecordType()) + if (const RecordType* RT = Ty->getAs<RecordType>()) if (typeContainsSSEVector(RT->getDecl(), Context)) return 16; return 0; } ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, - ASTContext &Context) const { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { // FIXME: Set alignment on indirect arguments. if (CodeGenFunction::hasAggregateLLVMType(Ty)) { // Structures with flexible arrays are always indirect. if (const RecordType *RT = Ty->getAsStructureType()) if (RT->getDecl()->hasFlexibleArrayMember()) - return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, + return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context)); // Ignore empty structs. @@ -412,7 +454,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { - const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); const llvm::Type *BPP = llvm::PointerType::getUnqual(BP); CGBuilderTy &Builder = CGF.Builder; @@ -426,8 +468,8 @@ llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, uint64_t Offset = llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4); llvm::Value *NextAddr = - Builder.CreateGEP(Addr, - llvm::ConstantInt::get(llvm::Type::Int32Ty, Offset), + Builder.CreateGEP(Addr, llvm::ConstantInt::get( + llvm::Type::getInt32Ty(CGF.getLLVMContext()), Offset), "ap.next"); Builder.CreateStore(NextAddr, VAListAddrAsBPP); @@ -502,15 +544,18 @@ class X86_64ABIInfo : public ABIInfo { ASTContext &Context) const; ABIArgInfo classifyReturnType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; ABIArgInfo classifyArgumentType(QualType Ty, ASTContext &Context, + llvm::LLVMContext &VMContext, unsigned &neededInt, unsigned &neededSSE) const; public: - virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context) const; + virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const; virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const; @@ -576,7 +621,7 @@ void X86_64ABIInfo::classify(QualType Ty, Class &Current = OffsetBase < 64 ? Lo : Hi; Current = Memory; - if (const BuiltinType *BT = Ty->getAsBuiltinType()) { + if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) { BuiltinType::Kind k = BT->getKind(); if (k == BuiltinType::Void) { @@ -594,12 +639,12 @@ void X86_64ABIInfo::classify(QualType Ty, } // FIXME: _Decimal32 and _Decimal64 are SSE. // FIXME: _float128 and _Decimal128 are (SSE, SSEUp). - } else if (const EnumType *ET = Ty->getAsEnumType()) { + } else if (const EnumType *ET = Ty->getAs<EnumType>()) { // Classify the underlying integer type. classify(ET->getDecl()->getIntegerType(), Context, OffsetBase, Lo, Hi); } else if (Ty->hasPointerRepresentation()) { Current = Integer; - } else if (const VectorType *VT = Ty->getAsVectorType()) { + } else if (const VectorType *VT = Ty->getAs<VectorType>()) { uint64_t Size = Context.getTypeSize(VT); if (Size == 32) { // gcc passes all <4 x char>, <2 x short>, <1 x int>, <1 x @@ -631,7 +676,7 @@ void X86_64ABIInfo::classify(QualType Ty, Lo = SSE; Hi = SSEUp; } - } else if (const ComplexType *CT = Ty->getAsComplexType()) { + } else if (const ComplexType *CT = Ty->getAs<ComplexType>()) { QualType ET = Context.getCanonicalType(CT->getElementType()); uint64_t Size = Context.getTypeSize(Ty); @@ -688,7 +733,7 @@ void X86_64ABIInfo::classify(QualType Ty, if (Hi == Memory) Lo = Memory; assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp array classification."); - } else if (const RecordType *RT = Ty->getAsRecordType()) { + } else if (const RecordType *RT = Ty->getAs<RecordType>()) { uint64_t Size = Context.getTypeSize(Ty); // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger @@ -696,6 +741,12 @@ void X86_64ABIInfo::classify(QualType Ty, if (Size > 128) return; + // AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial + // copy constructor or a non-trivial destructor, it is passed by invisible + // reference. + if (hasNonTrivialDestructorOrCopyConstructor(RT)) + return; + const RecordDecl *RD = RT->getDecl(); // Assume variable sized types are passed in memory. @@ -781,13 +832,13 @@ void X86_64ABIInfo::classify(QualType Ty, ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty, const llvm::Type *CoerceTo, ASTContext &Context) const { - if (CoerceTo == llvm::Type::Int64Ty) { + if (CoerceTo == llvm::Type::getInt64Ty(CoerceTo->getContext())) { // Integer and pointer types will end up in a general purpose // register. - if (Ty->isIntegralType() || Ty->isPointerType()) + if (Ty->isIntegralType() || Ty->hasPointerRepresentation()) return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); - } else if (CoerceTo == llvm::Type::DoubleTy) { + } else if (CoerceTo == llvm::Type::getDoubleTy(CoerceTo->getContext())) { // FIXME: It would probably be better to make CGFunctionInfo only map using // canonical types than to canonize here. QualType CTy = Context.getCanonicalType(Ty); @@ -809,12 +860,15 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + bool ByVal = !isRecordWithNonTrivialDestructorOrCopyConstructor(Ty); + // FIXME: Set alignment correctly. - return ABIArgInfo::getIndirect(0); + return ABIArgInfo::getIndirect(0, ByVal); } ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, - ASTContext &Context) const { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the // classification algorithm. X86_64ABIInfo::Class Lo, Hi; @@ -842,25 +896,25 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next // available register of the sequence %rax, %rdx is used. case Integer: - ResType = llvm::Type::Int64Ty; break; + ResType = llvm::Type::getInt64Ty(VMContext); break; // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next // available SSE register of the sequence %xmm0, %xmm1 is used. case SSE: - ResType = llvm::Type::DoubleTy; break; + ResType = llvm::Type::getDoubleTy(VMContext); break; // AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is // returned on the X87 stack in %st0 as 80-bit x87 number. case X87: - ResType = llvm::Type::X86_FP80Ty; break; + ResType = llvm::Type::getX86_FP80Ty(VMContext); break; // AMD64-ABI 3.2.3p4: Rule 8. If the class is COMPLEX_X87, the real // part of the value is returned in %st0 and the imaginary part in // %st1. case ComplexX87: assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification."); - ResType = llvm::StructType::get(llvm::Type::X86_FP80Ty, - llvm::Type::X86_FP80Ty, + ResType = llvm::StructType::get(VMContext, llvm::Type::getX86_FP80Ty(VMContext), + llvm::Type::getX86_FP80Ty(VMContext), NULL); break; } @@ -876,10 +930,12 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, case NoClass: break; case Integer: - ResType = llvm::StructType::get(ResType, llvm::Type::Int64Ty, NULL); + ResType = llvm::StructType::get(VMContext, ResType, + llvm::Type::getInt64Ty(VMContext), NULL); break; case SSE: - ResType = llvm::StructType::get(ResType, llvm::Type::DoubleTy, NULL); + ResType = llvm::StructType::get(VMContext, ResType, + llvm::Type::getDoubleTy(VMContext), NULL); break; // AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte @@ -888,7 +944,7 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, // SSEUP should always be preceeded by SSE, just widen. case SSEUp: assert(Lo == SSE && "Unexpected SSEUp classification."); - ResType = llvm::VectorType::get(llvm::Type::DoubleTy, 2); + ResType = llvm::VectorType::get(llvm::Type::getDoubleTy(VMContext), 2); break; // AMD64-ABI 3.2.3p4: Rule 7. If the class is X87UP, the value is @@ -899,7 +955,8 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, // preceeded by X87. In such situations we follow gcc and pass the // extra bits in an SSE reg. if (Lo != X87) - ResType = llvm::StructType::get(ResType, llvm::Type::DoubleTy, NULL); + ResType = llvm::StructType::get(VMContext, ResType, + llvm::Type::getDoubleTy(VMContext), NULL); break; } @@ -907,6 +964,7 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, } ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, + llvm::LLVMContext &VMContext, unsigned &neededInt, unsigned &neededSSE) const { X86_64ABIInfo::Class Lo, Hi; @@ -944,7 +1002,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, // and %r9 is used. case Integer: ++neededInt; - ResType = llvm::Type::Int64Ty; + ResType = llvm::Type::getInt64Ty(VMContext); break; // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next @@ -952,7 +1010,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, // order from %xmm0 to %xmm7. case SSE: ++neededSSE; - ResType = llvm::Type::DoubleTy; + ResType = llvm::Type::getDoubleTy(VMContext); break; } @@ -968,7 +1026,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, case NoClass: break; case Integer: - ResType = llvm::StructType::get(ResType, llvm::Type::Int64Ty, NULL); + ResType = llvm::StructType::get(VMContext, ResType, + llvm::Type::getInt64Ty(VMContext), NULL); ++neededInt; break; @@ -976,7 +1035,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, // memory), except in situations involving unions. case X87Up: case SSE: - ResType = llvm::StructType::get(ResType, llvm::Type::DoubleTy, NULL); + ResType = llvm::StructType::get(VMContext, ResType, + llvm::Type::getDoubleTy(VMContext), NULL); ++neededSSE; break; @@ -985,15 +1045,17 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, // register. case SSEUp: assert(Lo == SSE && "Unexpected SSEUp classification."); - ResType = llvm::VectorType::get(llvm::Type::DoubleTy, 2); + ResType = llvm::VectorType::get(llvm::Type::getDoubleTy(VMContext), 2); break; } return getCoerceResult(Ty, ResType, Context); } -void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context); +void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), + Context, VMContext); // Keep track of the number of assigned registers. unsigned freeIntRegs = 6, freeSSERegs = 8; @@ -1008,7 +1070,8 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) { unsigned neededInt, neededSSE; - it->info = classifyArgumentType(it->type, Context, neededInt, neededSSE); + it->info = classifyArgumentType(it->type, Context, VMContext, + neededInt, neededSSE); // AMD64-ABI 3.2.3p3: If there are no registers available for any // eightbyte of an argument, the whole argument is passed on the @@ -1040,11 +1103,13 @@ static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr, // shouldn't ever matter in practice. // overflow_arg_area = (overflow_arg_area + 15) & ~15; - llvm::Value *Offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, 15); + llvm::Value *Offset = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), 15); overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset); llvm::Value *AsInt = CGF.Builder.CreatePtrToInt(overflow_arg_area, - llvm::Type::Int64Ty); - llvm::Value *Mask = llvm::ConstantInt::get(llvm::Type::Int64Ty, ~15LL); + llvm::Type::getInt64Ty(CGF.getLLVMContext())); + llvm::Value *Mask = llvm::ConstantInt::get( + llvm::Type::getInt64Ty(CGF.getLLVMContext()), ~15LL); overflow_arg_area = CGF.Builder.CreateIntToPtr(CGF.Builder.CreateAnd(AsInt, Mask), overflow_arg_area->getType(), @@ -1063,7 +1128,8 @@ static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr, // an 8 byte boundary. uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8; - llvm::Value *Offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, + llvm::Value *Offset = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), (SizeInBytes + 7) & ~7); overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset, "overflow_arg_area.next"); @@ -1075,6 +1141,10 @@ static llvm::Value *EmitVAArgFromMemory(llvm::Value *VAListAddr, llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { + llvm::LLVMContext &VMContext = CGF.getLLVMContext(); + const llvm::Type *i32Ty = llvm::Type::getInt32Ty(VMContext); + const llvm::Type *DoubleTy = llvm::Type::getDoubleTy(VMContext); + // Assume that va_list type is correct; should be pointer to LLVM type: // struct { // i32 gp_offset; @@ -1083,7 +1153,7 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // i8* reg_save_area; // }; unsigned neededInt, neededSSE; - ABIArgInfo AI = classifyArgumentType(Ty, CGF.getContext(), + ABIArgInfo AI = classifyArgumentType(Ty, CGF.getContext(), VMContext, neededInt, neededSSE); // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed @@ -1110,7 +1180,7 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, gp_offset = CGF.Builder.CreateLoad(gp_offset_p, "gp_offset"); InRegs = CGF.Builder.CreateICmpULE(gp_offset, - llvm::ConstantInt::get(llvm::Type::Int32Ty, + llvm::ConstantInt::get(i32Ty, 48 - neededInt * 8), "fits_in_gp"); } @@ -1120,7 +1190,7 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, fp_offset = CGF.Builder.CreateLoad(fp_offset_p, "fp_offset"); llvm::Value *FitsInFP = CGF.Builder.CreateICmpULE(fp_offset, - llvm::ConstantInt::get(llvm::Type::Int32Ty, + llvm::ConstantInt::get(i32Ty, 176 - neededSSE * 16), "fits_in_fp"); InRegs = InRegs ? CGF.Builder.CreateAnd(InRegs, FitsInFP) : FitsInFP; @@ -1171,7 +1241,8 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegHiAddr, PTyHi)); CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); - RegAddr = CGF.Builder.CreateBitCast(Tmp, llvm::PointerType::getUnqual(LTy)); + RegAddr = CGF.Builder.CreateBitCast(Tmp, + llvm::PointerType::getUnqual(LTy)); } else if (neededInt) { RegAddr = CGF.Builder.CreateGEP(RegAddr, gp_offset); RegAddr = CGF.Builder.CreateBitCast(RegAddr, @@ -1188,12 +1259,11 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, llvm::Value *RegAddrLo = CGF.Builder.CreateGEP(RegAddr, fp_offset); llvm::Value *RegAddrHi = CGF.Builder.CreateGEP(RegAddrLo, - llvm::ConstantInt::get(llvm::Type::Int32Ty, 16)); + llvm::ConstantInt::get(i32Ty, 16)); const llvm::Type *DblPtrTy = - llvm::PointerType::getUnqual(llvm::Type::DoubleTy); - const llvm::StructType *ST = llvm::StructType::get(llvm::Type::DoubleTy, - llvm::Type::DoubleTy, - NULL); + llvm::PointerType::getUnqual(DoubleTy); + const llvm::StructType *ST = llvm::StructType::get(VMContext, DoubleTy, + DoubleTy, NULL); llvm::Value *V, *Tmp = CGF.CreateTempAlloca(ST); V = CGF.Builder.CreateLoad(CGF.Builder.CreateBitCast(RegAddrLo, DblPtrTy)); @@ -1210,14 +1280,12 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, // l->gp_offset = l->gp_offset + num_gp * 8 // l->fp_offset = l->fp_offset + num_fp * 16. if (neededInt) { - llvm::Value *Offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, - neededInt * 8); + llvm::Value *Offset = llvm::ConstantInt::get(i32Ty, neededInt * 8); CGF.Builder.CreateStore(CGF.Builder.CreateAdd(gp_offset, Offset), gp_offset_p); } if (neededSSE) { - llvm::Value *Offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, - neededSSE * 16); + llvm::Value *Offset = llvm::ConstantInt::get(i32Ty, neededSSE * 16); CGF.Builder.CreateStore(CGF.Builder.CreateAdd(fp_offset, Offset), fp_offset_p); } @@ -1240,28 +1308,37 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, return ResAddr; } -// ABI Info for PIC16 +// PIC16 ABI Implementation + +namespace { + class PIC16ABIInfo : public ABIInfo { ABIArgInfo classifyReturnType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; ABIArgInfo classifyArgumentType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; - virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context); + virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context, + VMContext); for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) - it->info = classifyArgumentType(it->type, Context); + it->info = classifyArgumentType(it->type, Context, VMContext); } virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const; - }; +} + ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy, - ASTContext &Context) const { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { if (RetTy->isVoidType()) { return ABIArgInfo::getIgnore(); } else { @@ -1270,7 +1347,8 @@ ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy, } ABIArgInfo PIC16ABIInfo::classifyArgumentType(QualType Ty, - ASTContext &Context) const { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { return ABIArgInfo::getDirect(); } @@ -1279,72 +1357,238 @@ llvm::Value *PIC16ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, return 0; } +// ARM ABI Implementation + +namespace { + class ARMABIInfo : public ABIInfo { +public: + enum ABIKind { + APCS = 0, + AAPCS = 1, + AAPCS_VFP + }; + +private: + ABIKind Kind; + +public: + ARMABIInfo(ABIKind _Kind) : Kind(_Kind) {} + +private: + ABIKind getABIKind() const { return Kind; } + ABIArgInfo classifyReturnType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMCOntext) const; ABIArgInfo classifyArgumentType(QualType RetTy, - ASTContext &Context) const; + ASTContext &Context, + llvm::LLVMContext &VMContext) const; - virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context) const; + virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const; virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const; }; -void ARMABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context); +} + +void ARMABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context, + VMContext); for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); it != ie; ++it) { - it->info = classifyArgumentType(it->type, Context); + it->info = classifyArgumentType(it->type, Context, VMContext); + } + + // ARM always overrides the calling convention. + switch (getABIKind()) { + case APCS: + FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_APCS); + break; + + case AAPCS: + FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS); + break; + + case AAPCS_VFP: + FI.setEffectiveCallingConvention(llvm::CallingConv::ARM_AAPCS_VFP); + break; } } ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, - ASTContext &Context) const { - if (!CodeGenFunction::hasAggregateLLVMType(Ty)) { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { + if (!CodeGenFunction::hasAggregateLLVMType(Ty)) return (Ty->isPromotableIntegerType() ? ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); - } + + // Ignore empty records. + if (isEmptyRecord(Context, Ty, true)) + return ABIArgInfo::getIgnore(); + // FIXME: This is kind of nasty... but there isn't much choice because the ARM // backend doesn't support byval. // FIXME: This doesn't handle alignment > 64 bits. const llvm::Type* ElemTy; unsigned SizeRegs; if (Context.getTypeAlign(Ty) > 32) { - ElemTy = llvm::Type::Int64Ty; + ElemTy = llvm::Type::getInt64Ty(VMContext); SizeRegs = (Context.getTypeSize(Ty) + 63) / 64; } else { - ElemTy = llvm::Type::Int32Ty; + ElemTy = llvm::Type::getInt32Ty(VMContext); SizeRegs = (Context.getTypeSize(Ty) + 31) / 32; } std::vector<const llvm::Type*> LLVMFields; LLVMFields.push_back(llvm::ArrayType::get(ElemTy, SizeRegs)); - const llvm::Type* STy = llvm::StructType::get(LLVMFields, true); + const llvm::Type* STy = llvm::StructType::get(VMContext, LLVMFields, true); return ABIArgInfo::getCoerce(STy); } +static bool isIntegerLikeType(QualType Ty, + ASTContext &Context, + llvm::LLVMContext &VMContext) { + // APCS, C Language Calling Conventions, Non-Simple Return Values: A structure + // is called integer-like if its size is less than or equal to one word, and + // the offset of each of its addressable sub-fields is zero. + + uint64_t Size = Context.getTypeSize(Ty); + + // Check that the type fits in a word. + if (Size > 32) + return false; + + // FIXME: Handle vector types! + if (Ty->isVectorType()) + return false; + + // Float types are never treated as "integer like". + if (Ty->isRealFloatingType()) + return false; + + // If this is a builtin or pointer type then it is ok. + if (Ty->getAs<BuiltinType>() || Ty->isPointerType()) + return true; + + // Complex types "should" be ok by the definition above, but they are not. + if (Ty->isAnyComplexType()) + return false; + + // Single element and zero sized arrays should be allowed, by the definition + // above, but they are not. + + // Otherwise, it must be a record type. + const RecordType *RT = Ty->getAs<RecordType>(); + if (!RT) return false; + + // Ignore records with flexible arrays. + const RecordDecl *RD = RT->getDecl(); + if (RD->hasFlexibleArrayMember()) + return false; + + // Check that all sub-fields are at offset 0, and are themselves "integer + // like". + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + bool HadField = false; + unsigned idx = 0; + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i, ++idx) { + const FieldDecl *FD = *i; + + // Check if this field is at offset 0. + uint64_t Offset = Layout.getFieldOffset(idx); + if (Offset != 0) { + // Allow padding bit-fields, but only if they are all at the end of the + // structure (despite the wording above, this matches gcc). + if (FD->isBitField() && + !FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { + for (; i != e; ++i) + if (!i->isBitField() || + i->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) + return false; + + // All remaining fields are padding, allow this. + return true; + } + + return false; + } + + if (!isIntegerLikeType(FD->getType(), Context, VMContext)) + return false; + + // Only allow at most one field in a structure. Again this doesn't match the + // wording above, but follows gcc. + if (!RD->isUnion()) { + if (HadField) + return false; + + HadField = true; + } + } + + return true; +} + ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, - ASTContext &Context) const { - if (RetTy->isVoidType()) { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { + if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); - } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) { - // Aggregates <= 4 bytes are returned in r0; other aggregates - // are returned indirectly. - uint64_t Size = Context.getTypeSize(RetTy); - if (Size <= 32) - return ABIArgInfo::getCoerce(llvm::Type::Int32Ty); - return ABIArgInfo::getIndirect(0); - } else { + + if (!CodeGenFunction::hasAggregateLLVMType(RetTy)) return (RetTy->isPromotableIntegerType() ? ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + + // Are we following APCS? + if (getABIKind() == APCS) { + if (isEmptyRecord(Context, RetTy, false)) + return ABIArgInfo::getIgnore(); + + // Integer like structures are returned in r0. + if (isIntegerLikeType(RetTy, Context, VMContext)) { + // Return in the smallest viable integer type. + uint64_t Size = Context.getTypeSize(RetTy); + if (Size <= 8) + return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(VMContext)); + if (Size <= 16) + return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(VMContext)); + return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(VMContext)); + } + + // Otherwise return in memory. + return ABIArgInfo::getIndirect(0); } + + // Otherwise this is an AAPCS variant. + + if (isEmptyRecord(Context, RetTy, true)) + return ABIArgInfo::getIgnore(); + + // Aggregates <= 4 bytes are returned in r0; other aggregates + // are returned indirectly. + uint64_t Size = Context.getTypeSize(RetTy); + if (Size <= 32) { + // Return in the smallest viable integer type. + if (Size <= 8) + return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(VMContext)); + if (Size <= 16) + return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(VMContext)); + return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(VMContext)); + } + + return ABIArgInfo::getIndirect(0); } llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { // FIXME: Need to handle alignment - const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); const llvm::Type *BPP = llvm::PointerType::getUnqual(BP); CGBuilderTy &Builder = CGF.Builder; @@ -1358,8 +1602,8 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, uint64_t Offset = llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 4); llvm::Value *NextAddr = - Builder.CreateGEP(Addr, - llvm::ConstantInt::get(llvm::Type::Int32Ty, Offset), + Builder.CreateGEP(Addr, llvm::ConstantInt::get( + llvm::Type::getInt32Ty(CGF.getLLVMContext()), Offset), "ap.next"); Builder.CreateStore(NextAddr, VAListAddrAsBPP); @@ -1367,7 +1611,8 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, } ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy, - ASTContext &Context) const { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { if (RetTy->isVoidType()) { return ABIArgInfo::getIgnore(); } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) { @@ -1378,8 +1623,88 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy, } } +// SystemZ ABI Implementation + +namespace { + +class SystemZABIInfo : public ABIInfo { + bool isPromotableIntegerType(QualType Ty) const; + + ABIArgInfo classifyReturnType(QualType RetTy, ASTContext &Context, + llvm::LLVMContext &VMContext) const; + + ABIArgInfo classifyArgumentType(QualType RetTy, ASTContext &Context, + llvm::LLVMContext &VMContext) const; + + virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context, + llvm::LLVMContext &VMContext) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), + Context, VMContext); + for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); + it != ie; ++it) + it->info = classifyArgumentType(it->type, Context, VMContext); + } + + virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, + CodeGenFunction &CGF) const; +}; + +} + +bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const { + // SystemZ ABI requires all 8, 16 and 32 bit quantities to be extended. + if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) + switch (BT->getKind()) { + case BuiltinType::Bool: + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::Int: + case BuiltinType::UInt: + return true; + default: + return false; + } + return false; +} + +llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, + CodeGenFunction &CGF) const { + // FIXME: Implement + return 0; +} + + +ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy, + ASTContext &Context, + llvm::LLVMContext &VMContext) const { + if (RetTy->isVoidType()) { + return ABIArgInfo::getIgnore(); + } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) { + return ABIArgInfo::getIndirect(0); + } else { + return (isPromotableIntegerType(RetTy) ? + ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + } +} + +ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty, + ASTContext &Context, + llvm::LLVMContext &VMContext) const { + if (CodeGenFunction::hasAggregateLLVMType(Ty)) { + return ABIArgInfo::getIndirect(0); + } else { + return (isPromotableIntegerType(Ty) ? + ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); + } +} + ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty, - ASTContext &Context) const { + ASTContext &Context, + llvm::LLVMContext &VMContext) const { if (CodeGenFunction::hasAggregateLLVMType(Ty)) { return ABIArgInfo::getIndirect(0); } else { @@ -1397,23 +1722,45 @@ const ABIInfo &CodeGenTypes::getABIInfo() const { if (TheABIInfo) return *TheABIInfo; - // For now we just cache this in the CodeGenTypes and don't bother - // to free it. - const char *TargetPrefix = getContext().Target.getTargetPrefix(); - if (strcmp(TargetPrefix, "x86") == 0) { - bool IsDarwin = strstr(getContext().Target.getTargetTriple(), "darwin"); - switch (getContext().Target.getPointerWidth(0)) { - case 32: - return *(TheABIInfo = new X86_32ABIInfo(Context, IsDarwin)); - case 64: - return *(TheABIInfo = new X86_64ABIInfo()); - } - } else if (strcmp(TargetPrefix, "arm") == 0) { - // FIXME: Support for OABI? - return *(TheABIInfo = new ARMABIInfo()); - } else if (strcmp(TargetPrefix, "pic16") == 0) { + // For now we just cache the ABIInfo in CodeGenTypes and don't free it. + + const llvm::Triple &Triple(getContext().Target.getTriple()); + switch (Triple.getArch()) { + default: + return *(TheABIInfo = new DefaultABIInfo); + + case llvm::Triple::arm: + case llvm::Triple::thumb: + // FIXME: We want to know the float calling convention as well. + if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0) + return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::APCS)); + + return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::AAPCS)); + + case llvm::Triple::pic16: return *(TheABIInfo = new PIC16ABIInfo()); - } - return *(TheABIInfo = new DefaultABIInfo); + case llvm::Triple::systemz: + return *(TheABIInfo = new SystemZABIInfo()); + + case llvm::Triple::x86: + if (Triple.getOS() == llvm::Triple::Darwin) + return *(TheABIInfo = new X86_32ABIInfo(Context, true, true)); + + switch (Triple.getOS()) { + case llvm::Triple::Cygwin: + case llvm::Triple::DragonFly: + case llvm::Triple::MinGW32: + case llvm::Triple::MinGW64: + case llvm::Triple::FreeBSD: + case llvm::Triple::OpenBSD: + return *(TheABIInfo = new X86_32ABIInfo(Context, false, true)); + + default: + return *(TheABIInfo = new X86_32ABIInfo(Context, false, false)); + } + + case llvm::Triple::x86_64: + return *(TheABIInfo = new X86_64ABIInfo()); + } } |