void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo) { assert(!CurGD.getDecl() && "CurGD was already set!"); CurGD = GD; // Build FunctionArgs. const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); QualType ThisType = MD->getThisType(getContext()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); QualType ResultType = CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getReturnType(); FunctionArgList FunctionArgs; // Create the implicit 'this' parameter declaration. CGM.getCXXABI().buildThisParam(*this, FunctionArgs); // Add the rest of the parameters. for (FunctionDecl::param_const_iterator I = MD->param_begin(), E = MD->param_end(); I != E; ++I) FunctionArgs.push_back(*I); if (isa<CXXDestructorDecl>(MD)) CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, FunctionArgs); // Start defining the function. StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, MD->getLocation(), SourceLocation()); // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves. CGM.getCXXABI().EmitInstanceFunctionProlog(*this); CXXThisValue = CXXABIThisValue; }
void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { BuildThisParam(CGF, Params); if (needThisReturn(CGF.CurGD)) { ResTy = Params[0]->getType(); } ASTContext &Context = getContext(); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { ImplicitParamDecl *IsMostDerived = ImplicitParamDecl::Create(Context, 0, CGF.CurGD.getDecl()->getLocation(), &Context.Idents.get("is_most_derived"), Context.IntTy); Params.push_back(IsMostDerived); getStructorImplicitParamDecl(CGF) = IsMostDerived; } else if (IsDeletingDtor(CGF.CurGD)) { ImplicitParamDecl *ShouldDelete = ImplicitParamDecl::Create(Context, 0, CGF.CurGD.getDecl()->getLocation(), &Context.Idents.get("should_call_delete"), Context.BoolTy); Params.push_back(ShouldDelete); getStructorImplicitParamDecl(CGF) = ShouldDelete; } }
/// GenerateCXXAggrDestructorHelper - Generates a helper function which when /// invoked, calls the default destructor on array elements in reverse order of /// construction. llvm::Function * CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, const ArrayType *Array, llvm::Value *This) { FunctionArgList Args; ImplicitParamDecl *Dst = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Dst, Dst->getType())); const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(getContext().VoidTy, Args, FunctionType::ExtInfo()); const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false); llvm::Function *Fn = CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); StartFunction(GlobalDecl(), getContext().VoidTy, Fn, Args, SourceLocation()); QualType BaseElementTy = getContext().getBaseElementType(Array); const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo(); llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr); EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); FinishFunction(); return Fn; }
/// generateDestroyHelper - Generates a helper function which, when /// invoked, destroys the given object. llvm::Function * CodeGenFunction::generateDestroyHelper(llvm::Constant *addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray) { FunctionArgList args; ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy); args.push_back(&dst); const CGFunctionInfo &FI = CGM.getTypes().arrangeFunctionDeclaration(getContext().VoidTy, args, FunctionType::ExtInfo(), /*variadic*/ false); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); llvm::Function *fn = CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor"); StartFunction(GlobalDecl(), getContext().VoidTy, fn, FI, args, SourceLocation()); emitDestroy(addr, type, destroyer, useEHCleanupForArray); FinishFunction(); return fn; }
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); // Check if we should generate debug info for this function. if (CGM.getModuleDebugInfo() && !FD->hasAttr<NoDebugAttr>()) DebugInfo = CGM.getModuleDebugInfo(); FunctionArgList Args; QualType ResTy = FD->getResultType(); CurGD = GD; if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance()) CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args); for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) Args.push_back(FD->getParamDecl(i)); SourceRange BodyRange; if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); // Emit the standard function prologue. StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin()); // Generate the body of the function. if (isa<CXXDestructorDecl>(FD)) EmitDestructorBody(Args); else if (isa<CXXConstructorDecl>(FD)) EmitConstructorBody(Args); else if (getContext().getLangOpts().CUDA && !CGM.getCodeGenOpts().CUDAIsDevice && FD->hasAttr<CUDAGlobalAttr>()) CGM.getCUDARuntime().EmitDeviceStubBody(*this, Args); else if (isa<CXXConversionDecl>(FD) && cast<CXXConversionDecl>(FD)->isLambdaToBlockPointerConversion()) { // The lambda conversion to block pointer is special; the semantics can't be // expressed in the AST, so IRGen needs to special-case it. EmitLambdaToBlockPointerBody(Args); } else if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) { // The lambda "__invoke" function is special, because it forwards or // clones the body of the function call operator (but is actually static). EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD)); } else EmitFunctionBody(Args); // Emit the standard function epilogue. FinishFunction(BodyRange.getEnd()); // If we haven't marked the function nothrow through other means, do // a quick pass now to see if we can. if (!CurFn->doesNotThrow()) TryMarkNoThrow(CurFn); }
void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo, bool IsUnprototyped) { assert(!CurGD.getDecl() && "CurGD was already set!"); CurGD = GD; CurFuncIsThunk = true; // Build FunctionArgs. const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); QualType ThisType = MD->getThisType(); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); QualType ResultType; if (IsUnprototyped) ResultType = CGM.getContext().VoidTy; else if (CGM.getCXXABI().HasThisReturn(GD)) ResultType = ThisType; else if (CGM.getCXXABI().hasMostDerivedReturn(GD)) ResultType = CGM.getContext().VoidPtrTy; else ResultType = FPT->getReturnType(); FunctionArgList FunctionArgs; // Create the implicit 'this' parameter declaration. CGM.getCXXABI().buildThisParam(*this, FunctionArgs); // Add the rest of the parameters, if we have a prototype to work with. if (!IsUnprototyped) { FunctionArgs.append(MD->param_begin(), MD->param_end()); if (isa<CXXDestructorDecl>(MD)) CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, FunctionArgs); } // Start defining the function. auto NL = ApplyDebugLocation::CreateEmpty(*this); StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, MD->getLocation()); // Create a scope with an artificial location for the body of this function. auto AL = ApplyDebugLocation::CreateArtificial(*this); // Since we didn't pass a GlobalDecl to StartFunction, do this ourselves. CGM.getCXXABI().EmitInstanceFunctionProlog(*this); CXXThisValue = CXXABIThisValue; CurCodeDecl = MD; CurFuncDecl = MD; }
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); // Check if we should generate debug info for this function. if (CGM.getModuleDebugInfo() && !FD->hasAttr<NoDebugAttr>()) DebugInfo = CGM.getModuleDebugInfo(); FunctionArgList Args; QualType ResTy = FD->getResultType(); CurGD = GD; if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance()) CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args); if (FD->getNumParams()) for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) Args.push_back(FD->getParamDecl(i)); SourceRange BodyRange; if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); // Emit the standard function prologue. StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin()); // Generate the body of the function. if (isa<CXXDestructorDecl>(FD)) EmitDestructorBody(Args); else if (isa<CXXConstructorDecl>(FD)) EmitConstructorBody(Args); else if (getContext().getLangOptions().CUDA && !CGM.getCodeGenOpts().CUDAIsDevice && FD->hasAttr<CUDAGlobalAttr>()) CGM.getCUDARuntime().EmitDeviceStubBody(*this, Args); else EmitFunctionBody(Args); // Emit the standard function epilogue. FinishFunction(BodyRange.getEnd()); // If we haven't marked the function nothrow through other means, do // a quick pass now to see if we can. if (!CurFn->doesNotThrow()) TryMarkNoThrow(CurFn); }
void CodeGenFunction::GenerateCode(GlobalDefn GD, llvm::Function *Fn) { const FunctionDefn *FD = cast<FunctionDefn>(GD.getDefn()); // Check if we should generate debug info for this function. if (CGM.getModuleDebugInfo() /*&& !FD->hasAttr<NoDebugAttr>()*/) DebugInfo = CGM.getModuleDebugInfo(); FunctionArgList Args; Type ResTy = FD->getResultType(); CurGD = GD; if (isa<ClassMethodDefn>(FD) && cast<ClassMethodDefn>(FD)->isInstance()) CGM.getOOPABI().BuildInstanceFunctionParams(*this, ResTy, Args); if (FD->getNumParams()) { 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(FD->getParamDefn(i)); } SourceRange BodyRange; if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); // Emit the standard function prologue. StartFunction(GD, ResTy, Fn, Args, BodyRange.getBegin()); // Generate the body of the function. if (isa<ClassDestructorDefn>(FD)) { // EmitDestructorBody(Args); } else if (isa<ClassConstructorDefn>(FD)) { // EmitConstructorBody(Args); } else EmitFunctionBody(Args); // Emit the standard function epilogue. FinishFunction(BodyRange.getEnd()); // If we haven't marked the function nothrow through other means, do // a quick pass now to see if we can. if (!CurFn->doesNotThrow()) TryMarkNoThrow(CurFn); }
void CGNVCUDARuntime::EmitDeviceStubBody(CodeGenFunction &CGF, FunctionArgList &Args) { // Build the argument value list and the argument stack struct type. SmallVector<llvm::Value *, 16> ArgValues; std::vector<llvm::Type *> ArgTypes; for (FunctionArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { llvm::Value *V = CGF.GetAddrOfLocalVar(*I); ArgValues.push_back(V); assert(isa<llvm::PointerType>(V->getType()) && "Arg type not PointerType"); ArgTypes.push_back(cast<llvm::PointerType>(V->getType())->getElementType()); } llvm::StructType *ArgStackTy = llvm::StructType::get( CGF.getLLVMContext(), ArgTypes); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); // Emit the calls to cudaSetupArgument llvm::Constant *cudaSetupArgFn = getSetupArgumentFn(); for (unsigned I = 0, E = Args.size(); I != E; ++I) { llvm::Value *Args[3]; llvm::BasicBlock *NextBlock = CGF.createBasicBlock("setup.next"); Args[0] = CGF.Builder.CreatePointerCast(ArgValues[I], VoidPtrTy); Args[1] = CGF.Builder.CreateIntCast( llvm::ConstantExpr::getSizeOf(ArgTypes[I]), SizeTy, false); Args[2] = CGF.Builder.CreateIntCast( llvm::ConstantExpr::getOffsetOf(ArgStackTy, I), SizeTy, false); llvm::CallSite CS = CGF.EmitRuntimeCallOrInvoke(cudaSetupArgFn, Args); llvm::Constant *Zero = llvm::ConstantInt::get(IntTy, 0); llvm::Value *CSZero = CGF.Builder.CreateICmpEQ(CS.getInstruction(), Zero); CGF.Builder.CreateCondBr(CSZero, NextBlock, EndBlock); CGF.EmitBlock(NextBlock); } // Emit the call to cudaLaunch llvm::Constant *cudaLaunchFn = getLaunchFn(); llvm::Value *Arg = CGF.Builder.CreatePointerCast(CGF.CurFn, CharPtrTy); CGF.EmitRuntimeCallOrInvoke(cudaLaunchFn, Arg); CGF.EmitBranch(EndBlock); CGF.EmitBlock(EndBlock); }
void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms, const CXXMethodDecl* MD) { // 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? ImplicitParamDecl *ThisDecl = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(), &CGM.getContext().Idents.get("this"), MD->getThisType(CGM.getContext())); params.push_back(ThisDecl); getThisDecl(CGF) = ThisDecl; }
/// generateDestroyHelper - Generates a helper function which, when /// invoked, destroys the given object. The address of the object /// should be in global memory. llvm::Function *CodeGenFunction::generateDestroyHelper( Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray, const VarDecl *VD) { FunctionArgList args; ImplicitParamDecl dst(getContext(), nullptr, SourceLocation(), nullptr, getContext().VoidPtrTy); args.push_back(&dst); const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( getContext().VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction( FTy, "__cxx_global_array_dtor", FI, VD->getLocation()); CurEHLocation = VD->getLocStart(); StartFunction(VD, getContext().VoidTy, fn, FI, args); emitDestroy(addr, type, destroyer, useEHCleanupForArray); FinishFunction(); return fn; }
/// generateDestroyHelper - Generates a helper function which, when /// invoked, destroys the given object. The address of the object /// should be in global memory. llvm::Function *CodeGenFunction::generateDestroyHelper( Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray, const VarDecl *VD) { FunctionArgList args; ImplicitParamDecl Dst(getContext(), getContext().VoidPtrTy, ImplicitParamDecl::Other); args.push_back(&Dst); const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, args); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); llvm::Function *fn = CGM.CreateGlobalInitOrDestructFunction( FTy, "__cxx_global_array_dtor", FI, VD->getLocation()); CurEHLocation = VD->getBeginLoc(); StartFunction(VD, getContext().VoidTy, fn, FI, args); emitDestroy(addr, type, destroyer, useEHCleanupForArray); FinishFunction(); return fn; }
void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { BuildThisParam(CGF, Params); if (needThisReturn(CGF.CurGD)) { ResTy = Params[0]->getType(); } if (IsDeletingDtor(CGF.CurGD)) { ASTContext &Context = getContext(); ImplicitParamDecl *ShouldDelete = ImplicitParamDecl::Create(Context, 0, CGF.CurGD.getDecl()->getLocation(), &Context.Idents.get("should_call_delete"), Context.BoolTy); Params.push_back(ShouldDelete); getStructorImplicitParamDecl(CGF) = ShouldDelete; } }
void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, QualType &ResTy, FunctionArgList &Params) { /// Create the 'this' variable. BuildThisParam(CGF, Params); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); assert(MD->isInstance()); // Check if we need a VTT parameter as well. if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { ASTContext &Context = getContext(); // FIXME: avoid the fake decl QualType T = Context.getPointerType(Context.VoidPtrTy); ImplicitParamDecl *VTTDecl = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), &Context.Idents.get("vtt"), T); Params.push_back(VTTDecl); getVTTDecl(CGF) = VTTDecl; } }
void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList ¶ms) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); // 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? ImplicitParamDecl *ThisDecl = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(), &CGM.getContext().Idents.get("this"), MD->getThisType(CGM.getContext())); params.push_back(ThisDecl); CGF.CXXABIThisDecl = ThisDecl; // Compute the presumed alignment of 'this', which basically comes // down to whether we know it's a complete object or not. auto &Layout = CGF.getContext().getASTRecordLayout(MD->getParent()); if (MD->getParent()->getNumVBases() == 0 || // avoid vcall in common case MD->getParent()->hasAttr<FinalAttr>() || !isThisCompleteObject(CGF.CurGD)) { CGF.CXXABIThisAlignment = Layout.getAlignment(); } else { CGF.CXXABIThisAlignment = Layout.getNonVirtualAlignment(); } }
// CUDA 9.0+ uses new way to launch kernels. Parameters are packed in a local // array and kernels are launched using cudaLaunchKernel(). void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, FunctionArgList &Args) { // Build the shadow stack entry at the very start of the function. // Calculate amount of space we will need for all arguments. If we have no // args, allocate a single pointer so we still have a valid pointer to the // argument array that we can pass to runtime, even if it will be unused. Address KernelArgs = CGF.CreateTempAlloca( VoidPtrTy, CharUnits::fromQuantity(16), "kernel_args", llvm::ConstantInt::get(SizeTy, std::max<size_t>(1, Args.size()))); // Store pointers to the arguments in a locally allocated launch_args. for (unsigned i = 0; i < Args.size(); ++i) { llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer(); llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, VoidPtrTy); CGF.Builder.CreateDefaultAlignedStore( VoidVarPtr, CGF.Builder.CreateConstGEP1_32(KernelArgs.getPointer(), i)); } llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); // Lookup cudaLaunchKernel function. // cudaError_t cudaLaunchKernel(const void *func, dim3 gridDim, dim3 blockDim, // void **args, size_t sharedMem, // cudaStream_t stream); TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); IdentifierInfo &cudaLaunchKernelII = CGM.getContext().Idents.get("cudaLaunchKernel"); FunctionDecl *cudaLaunchKernelFD = nullptr; for (const auto &Result : DC->lookup(&cudaLaunchKernelII)) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Result)) cudaLaunchKernelFD = FD; } if (cudaLaunchKernelFD == nullptr) { CGM.Error(CGF.CurFuncDecl->getLocation(), "Can't find declaration for cudaLaunchKernel()"); return; } // Create temporary dim3 grid_dim, block_dim. ParmVarDecl *GridDimParam = cudaLaunchKernelFD->getParamDecl(1); QualType Dim3Ty = GridDimParam->getType(); Address GridDim = CGF.CreateMemTemp(Dim3Ty, CharUnits::fromQuantity(8), "grid_dim"); Address BlockDim = CGF.CreateMemTemp(Dim3Ty, CharUnits::fromQuantity(8), "block_dim"); Address ShmemSize = CGF.CreateTempAlloca(SizeTy, CGM.getSizeAlign(), "shmem_size"); Address Stream = CGF.CreateTempAlloca(VoidPtrTy, CGM.getPointerAlign(), "stream"); llvm::FunctionCallee cudaPopConfigFn = CGM.CreateRuntimeFunction( llvm::FunctionType::get(IntTy, {/*gridDim=*/GridDim.getType(), /*blockDim=*/BlockDim.getType(), /*ShmemSize=*/ShmemSize.getType(), /*Stream=*/Stream.getType()}, /*isVarArg=*/false), "__cudaPopCallConfiguration"); CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, {GridDim.getPointer(), BlockDim.getPointer(), ShmemSize.getPointer(), Stream.getPointer()}); // Emit the call to cudaLaunch llvm::Value *Kernel = CGF.Builder.CreatePointerCast(CGF.CurFn, VoidPtrTy); CallArgList LaunchKernelArgs; LaunchKernelArgs.add(RValue::get(Kernel), cudaLaunchKernelFD->getParamDecl(0)->getType()); LaunchKernelArgs.add(RValue::getAggregate(GridDim), Dim3Ty); LaunchKernelArgs.add(RValue::getAggregate(BlockDim), Dim3Ty); LaunchKernelArgs.add(RValue::get(KernelArgs.getPointer()), cudaLaunchKernelFD->getParamDecl(3)->getType()); LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(ShmemSize)), cudaLaunchKernelFD->getParamDecl(4)->getType()); LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(Stream)), cudaLaunchKernelFD->getParamDecl(5)->getType()); QualType QT = cudaLaunchKernelFD->getType(); QualType CQT = QT.getCanonicalType(); llvm::Type *Ty = CGM.getTypes().ConvertType(CQT); llvm::FunctionType *FTy = dyn_cast<llvm::FunctionType>(Ty); const CGFunctionInfo &FI = CGM.getTypes().arrangeFunctionDeclaration(cudaLaunchKernelFD); llvm::FunctionCallee cudaLaunchKernelFn = CGM.CreateRuntimeFunction(FTy, "cudaLaunchKernel"); CGF.EmitCall(FI, CGCallee::forDirect(cudaLaunchKernelFn), ReturnValueSlot(), LaunchKernelArgs); CGF.EmitBranch(EndBlock); CGF.EmitBlock(EndBlock); }
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(); for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i, ++info_it) { const VarDecl *Arg = i->first; QualType Ty = info_it->type; const ABIArgInfo &ArgI = info_it->info; switch (ArgI.getKind()) { case ABIArgInfo::Indirect: { llvm::Value* V = AI; if (hasAggregateLLVMType(Ty)) { // Do nothing, aggregates and complex variables are accessed by // reference. } else { // Load scalar value from indirect argument. V = EmitLoadOfScalar(V, false, Ty); if (!getContext().typesAreCompatible(Ty, Arg->getType())) { // This must be a promotion, for something like // "void a(x) short x; {..." V = EmitScalarConversion(V, Ty, Arg->getType()); } } EmitParmDecl(*Arg, V); break; } case ABIArgInfo::Extend: case ABIArgInfo::Direct: { assert(AI != Fn->arg_end() && "Argument mismatch!"); llvm::Value* V = AI; if (hasAggregateLLVMType(Ty)) { // Create a temporary alloca to hold the argument; the rest of // codegen expects to access aggregates & complex values by // reference. V = CreateTempAlloca(ConvertTypeForMem(Ty)); Builder.CreateStore(AI, V); } else { if (!getContext().typesAreCompatible(Ty, Arg->getType())) { // This must be a promotion, for something like // "void a(x) short x; {..." V = EmitScalarConversion(V, Ty, Arg->getType()); } } 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. llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(Ty), Arg->getName() + ".addr"); // FIXME: What are the right qualifiers here? 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(Arg->getName() + "." + llvm::Twine(Index)); continue; } case ABIArgInfo::Ignore: // Initialize the local variable appropriately. if (hasAggregateLLVMType(Ty)) { EmitParmDecl(*Arg, CreateTempAlloca(ConvertTypeForMem(Ty))); } else { EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType()))); } // Skip increment, no matching LLVM parameter. continue; case ABIArgInfo::Coerce: { assert(AI != Fn->arg_end() && "Argument mismatch!"); // FIXME: This is very wasteful; EmitParmDecl is just going to drop the // result in a new alloca anyway, so we could just store into that // directly if we broke the abstraction down more. llvm::Value *V = CreateTempAlloca(ConvertTypeForMem(Ty), "coerce"); CreateCoercedStore(AI, V, *this); // Match to what EmitParmDecl is expecting for this type. if (!CodeGenFunction::hasAggregateLLVMType(Ty)) { V = EmitLoadOfScalar(V, false, Ty); if (!getContext().typesAreCompatible(Ty, Arg->getType())) { // This must be a promotion, for something like // "void a(x) short x; {..." V = EmitScalarConversion(V, Ty, Arg->getType()); } } EmitParmDecl(*Arg, V); break; } } ++AI; } assert(AI == Fn->arg_end() && "Argument mismatch!"); }
void CodeGenFunction::GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, GlobalDecl GD, const ThunkInfo &Thunk) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); QualType ResultType = FPT->getResultType(); QualType ThisType = MD->getThisType(getContext()); FunctionArgList FunctionArgs; // FIXME: It would be nice if more of this code could be shared with // CodeGenFunction::GenerateCode. // Create the implicit 'this' parameter declaration. CurGD = GD; CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs); // Add the rest of the parameters. for (FunctionDecl::param_const_iterator I = MD->param_begin(), E = MD->param_end(); I != E; ++I) { ParmVarDecl *Param = *I; FunctionArgs.push_back(Param); } StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs, SourceLocation()); CGM.getCXXABI().EmitInstanceFunctionProlog(*this); CXXThisValue = CXXABIThisValue; // Adjust the 'this' pointer if necessary. llvm::Value *AdjustedThisPtr = PerformTypeAdjustment(*this, LoadCXXThis(), Thunk.This.NonVirtual, Thunk.This.VCallOffsetOffset, /*IsReturnAdjustment*/false); CallArgList CallArgs; // Add our adjusted 'this' pointer. CallArgs.add(RValue::get(AdjustedThisPtr), ThisType); // Add the rest of the parameters. for (FunctionDecl::param_const_iterator I = MD->param_begin(), E = MD->param_end(); I != E; ++I) { ParmVarDecl *param = *I; EmitDelegateCallArg(CallArgs, param); } // Get our callee. llvm::Type *Ty = CGM.getTypes().GetFunctionType(CGM.getTypes().arrangeGlobalDeclaration(GD)); llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true); #ifndef NDEBUG const CGFunctionInfo &CallFnInfo = CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT, RequiredArgs::forPrototypePlus(FPT, 1)); assert(CallFnInfo.getRegParm() == FnInfo.getRegParm() && CallFnInfo.isNoReturn() == FnInfo.isNoReturn() && CallFnInfo.getCallingConvention() == FnInfo.getCallingConvention()); assert(isa<CXXDestructorDecl>(MD) || // ignore dtor return types similar(CallFnInfo.getReturnInfo(), CallFnInfo.getReturnType(), FnInfo.getReturnInfo(), FnInfo.getReturnType())); assert(CallFnInfo.arg_size() == FnInfo.arg_size()); for (unsigned i = 0, e = FnInfo.arg_size(); i != e; ++i) assert(similar(CallFnInfo.arg_begin()[i].info, CallFnInfo.arg_begin()[i].type, FnInfo.arg_begin()[i].info, FnInfo.arg_begin()[i].type)); #endif // Determine whether we have a return value slot to use. ReturnValueSlot Slot; if (!ResultType->isVoidType() && FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect && hasAggregateLLVMType(CurFnInfo->getReturnType())) Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified()); // Now emit our call. RValue RV = EmitCall(FnInfo, Callee, Slot, CallArgs, MD); if (!Thunk.Return.isEmpty()) RV = PerformReturnAdjustment(*this, ResultType, RV, Thunk); if (!ResultType->isVoidType() && Slot.isNull()) CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType); // Disable the final ARC autorelease. AutoreleaseResult = false; FinishFunction(); // Set the right linkage. CGM.setFunctionLinkage(MD, Fn); // Set the right visibility. setThunkVisibility(CGM, MD, Thunk, Fn); }
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; CurFn = Fn; assert(CurFn->isDeclaration() && "Function already has body?"); // Pass inline keyword to optimizer if it appears explicitly on any // declaration. if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) for (FunctionDecl::redecl_iterator RI = FD->redecls_begin(), RE = FD->redecls_end(); RI != RE; ++RI) if (RI->isInlineSpecified()) { Fn->addFnAttr(llvm::Attribute::InlineHint); break; } llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); // 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::getInt32Ty(VMContext)); AllocaInsertPt = new llvm::BitCastInst(Undef, llvm::Type::getInt32Ty(VMContext), "", EntryBB); if (Builder.isNamePreserving()) AllocaInsertPt->setName("allocapt"); ReturnBlock = createBasicBlock("return"); Builder.SetInsertPoint(EntryBB); QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0, false, false, 0, 0, /*FIXME?*/false, /*FIXME?*/CC_Default); // Emit subprogram debug descriptor. if (CGDebugInfo *DI = getDebugInfo()) { DI->setLocation(StartLoc); DI->EmitFunctionStart(GD, FnType, CurFn, Builder); } // FIXME: Leaked. // CC info is ignored, hopefully? CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args, CC_Default, false); if (RetTy->isVoidType()) { // Void type; nothing to return. ReturnValue = 0; } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && hasAggregateLLVMType(CurFnInfo->getReturnType())) { // Indirect aggregate return; emit returned value directly into sret slot. // This reduces code size, and affects correctness in C++. ReturnValue = CurFn->arg_begin(); } else { ReturnValue = CreateIRTemp(RetTy, "retval"); } EmitStartEHSpec(CurCodeDecl); EmitFunctionProlog(*CurFnInfo, CurFn, Args); if (CXXThisDecl) CXXThisValue = Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); if (CXXVTTDecl) CXXVTTValue = Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt"); // 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(); i != e; ++i) { QualType Ty = i->second; if (Ty->isVariablyModifiedType()) EmitVLASize(Ty); } }
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>()) DebugInfo = CGM.getDebugInfo(); FunctionArgList Args; CurGD = GD; 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, FD->getLocation(), &getContext().Idents.get("this"), MD->getThisType(getContext())); Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType())); // Check if we need a VTT parameter as well. if (CGVtableInfo::needsVTTParameter(GD)) { // FIXME: The comment about using a fake decl above applies here too. QualType T = getContext().getPointerType(getContext().VoidPtrTy); CXXVTTDecl = ImplicitParamDecl::Create(getContext(), 0, FD->getLocation(), &getContext().Idents.get("vtt"), T); Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType())); } } } if (FD->getNumParams()) { 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), FProto->getArgType(i))); } SourceRange BodyRange; if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); // Emit the standard function prologue. StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin()); // Generate the body of the function. if (isa<CXXDestructorDecl>(FD)) EmitDestructorBody(Args); else if (isa<CXXConstructorDecl>(FD)) EmitConstructorBody(Args); else EmitFunctionBody(Args); // Emit the standard function epilogue. FinishFunction(BodyRange.getEnd()); // Destroy the 'this' declaration. if (CXXThisDecl) CXXThisDecl->Destroy(getContext()); // Destroy the VTT declaration. if (CXXVTTDecl) CXXVTTDecl->Destroy(getContext()); }
llvm::Constant * CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, GlobalDecl GD, bool Extern, const CovariantThunkAdjustment &Adjustment) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); QualType ResultType = FPT->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, ResultType, 0, Extern ? FunctionDecl::Extern : FunctionDecl::Static, false, true); StartFunction(FD, ResultType, Fn, Args, SourceLocation()); // generate body const llvm::Type *Ty = CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), FPT->isVariadic()); llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty); CallArgList CallArgs; bool ShouldAdjustReturnPointer = true; QualType ArgType = MD->getThisType(getContext()); llvm::Value *Arg = Builder.CreateLoad(LocalDeclMap[ThisDecl], "this"); if (!Adjustment.ThisAdjustment.isEmpty()) { // Do the this adjustment. const llvm::Type *OrigTy = Callee->getType(); Arg = DynamicTypeAdjust(Arg, Adjustment.ThisAdjustment); if (!Adjustment.ReturnAdjustment.isEmpty()) { const CovariantThunkAdjustment &ReturnAdjustment = CovariantThunkAdjustment(ThunkAdjustment(), Adjustment.ReturnAdjustment); Callee = CGM.BuildCovariantThunk(GD, Extern, ReturnAdjustment); Callee = Builder.CreateBitCast(Callee, OrigTy); ShouldAdjustReturnPointer = false; } } CallArgs.push_back(std::make_pair(RValue::get(Arg), ArgType)); for (FunctionDecl::param_const_iterator i = MD->param_begin(), e = MD->param_end(); i != e; ++i) { ParmVarDecl *D = *i; QualType ArgType = D->getType(); // llvm::Value *Arg = CGF.GetAddrOfLocalVar(Dst); Expr *Arg = new (getContext()) DeclRefExpr(D, ArgType.getNonReferenceType(), SourceLocation()); CallArgs.push_back(std::make_pair(EmitCallArg(Arg, ArgType), ArgType)); } RValue RV = EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs, FPT->getCallConv(), FPT->getNoReturnAttr()), Callee, ReturnValueSlot(), CallArgs, MD); if (ShouldAdjustReturnPointer && !Adjustment.ReturnAdjustment.isEmpty()) { bool CanBeZero = !(ResultType->isReferenceType() // FIXME: attr nonnull can't be zero either /* || ResultType->hasAttr<NonNullAttr>() */ ); // Do the return result adjustment. if (CanBeZero) { llvm::BasicBlock *NonZeroBlock = createBasicBlock(); llvm::BasicBlock *ZeroBlock = createBasicBlock(); llvm::BasicBlock *ContBlock = createBasicBlock(); const llvm::Type *Ty = RV.getScalarVal()->getType(); llvm::Value *Zero = llvm::Constant::getNullValue(Ty); Builder.CreateCondBr(Builder.CreateICmpNE(RV.getScalarVal(), Zero), NonZeroBlock, ZeroBlock); EmitBlock(NonZeroBlock); llvm::Value *NZ = DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment); EmitBranch(ContBlock); EmitBlock(ZeroBlock); llvm::Value *Z = RV.getScalarVal(); EmitBlock(ContBlock); llvm::PHINode *RVOrZero = Builder.CreatePHI(Ty); RVOrZero->reserveOperandSpace(2); RVOrZero->addIncoming(NZ, NonZeroBlock); RVOrZero->addIncoming(Z, ZeroBlock); RV = RValue::get(RVOrZero); } else RV = RValue::get(DynamicTypeAdjust(RV.getScalarVal(), Adjustment.ReturnAdjustment)); } if (!ResultType->isVoidType()) EmitReturnOfRValue(RV, ResultType); FinishFunction(); return Fn; }
llvm::Function *CGOpenMPRuntime::EmitOMPThreadPrivateVarDefinition( const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF) { VD = VD->getDefinition(CGM.getContext()); if (VD && ThreadPrivateWithDefinition.count(VD) == 0) { ThreadPrivateWithDefinition.insert(VD); QualType ASTTy = VD->getType(); llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; auto Init = VD->getAnyInitializer(); if (CGM.getLangOpts().CPlusPlus && PerformInit) { // Generate function that re-emits the declaration's initializer into the // threadprivate copy of the variable VD CodeGenFunction CtorCGF(CGM); FunctionArgList Args; ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, CGM.getContext().VoidPtrTy); Args.push_back(&Dst); auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false); auto FTy = CGM.getTypes().GetFunctionType(FI); auto Fn = CGM.CreateGlobalInitOrDestructFunction( FTy, ".__kmpc_global_ctor_.", Loc); CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, Args, SourceLocation()); auto ArgVal = CtorCGF.EmitLoadOfScalar( CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, CGM.PointerAlignInBytes, CGM.getContext().VoidPtrTy, Dst.getLocation()); auto Arg = CtorCGF.Builder.CreatePointerCast( ArgVal, CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy))); CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), /*IsInitializer=*/true); ArgVal = CtorCGF.EmitLoadOfScalar( CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, CGM.PointerAlignInBytes, CGM.getContext().VoidPtrTy, Dst.getLocation()); CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); CtorCGF.FinishFunction(); Ctor = Fn; } if (VD->getType().isDestructedType() != QualType::DK_none) { // Generate function that emits destructor call for the threadprivate copy // of the variable VD CodeGenFunction DtorCGF(CGM); FunctionArgList Args; ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, CGM.getContext().VoidPtrTy); Args.push_back(&Dst); auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false); auto FTy = CGM.getTypes().GetFunctionType(FI); auto Fn = CGM.CreateGlobalInitOrDestructFunction( FTy, ".__kmpc_global_dtor_.", Loc); DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, SourceLocation()); auto ArgVal = DtorCGF.EmitLoadOfScalar( DtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, CGM.PointerAlignInBytes, CGM.getContext().VoidPtrTy, Dst.getLocation()); DtorCGF.emitDestroy(ArgVal, ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); DtorCGF.FinishFunction(); Dtor = Fn; } // Do not emit init function if it is not required. if (!Ctor && !Dtor) return nullptr; llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; auto CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, /*isVarArg=*/false)->getPointerTo(); // Copying constructor for the threadprivate variable. // Must be NULL - reserved by runtime, but currently it requires that this // parameter is always NULL. Otherwise it fires assertion. CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); if (Ctor == nullptr) { auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, /*isVarArg=*/false)->getPointerTo(); Ctor = llvm::Constant::getNullValue(CtorTy); } if (Dtor == nullptr) { auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg=*/false)->getPointerTo(); Dtor = llvm::Constant::getNullValue(DtorTy); } if (!CGF) { auto InitFunctionTy = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); auto InitFunction = CGM.CreateGlobalInitOrDestructFunction( InitFunctionTy, ".__omp_threadprivate_init_."); CodeGenFunction InitCGF(CGM); FunctionArgList ArgList; InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, CGM.getTypes().arrangeNullaryFunction(), ArgList, Loc); EmitOMPThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); InitCGF.FinishFunction(); return InitFunction; } EmitOMPThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); } return nullptr; }
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation StartLoc) { const Decl *D = GD.getDecl(); DidCallStackSave = false; CurCodeDecl = CurFuncDecl = D; FnRetTy = RetTy; CurFn = Fn; CurFnInfo = &FnInfo; assert(CurFn->isDeclaration() && "Function already has body?"); // Pass inline keyword to optimizer if it appears explicitly on any // declaration. if (!CGM.getCodeGenOpts().NoInline) if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) for (FunctionDecl::redecl_iterator RI = FD->redecls_begin(), RE = FD->redecls_end(); RI != RE; ++RI) if (RI->isInlineSpecified()) { Fn->addFnAttr(llvm::Attribute::InlineHint); break; } if (getContext().getLangOpts().OpenCL) { // Add metadata for a kernel function. if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) EmitOpenCLKernelMetadata(FD, Fn); } llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); // 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(Int32Ty); AllocaInsertPt = new llvm::BitCastInst(Undef, Int32Ty, "", EntryBB); if (Builder.isNamePreserving()) AllocaInsertPt->setName("allocapt"); ReturnBlock = getJumpDestInCurrentScope("return"); Builder.SetInsertPoint(EntryBB); // Emit subprogram debug descriptor. if (CGDebugInfo *DI = getDebugInfo()) { unsigned NumArgs = 0; QualType *ArgsArray = new QualType[Args.size()]; for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i) { ArgsArray[NumArgs++] = (*i)->getType(); } QualType FnType = getContext().getFunctionType(RetTy, ArgsArray, NumArgs, FunctionProtoType::ExtProtoInfo()); delete[] ArgsArray; DI->setLocation(StartLoc); DI->EmitFunctionStart(GD, FnType, CurFn, Builder); } if (ShouldInstrumentFunction()) EmitFunctionInstrumentation("__cyg_profile_func_enter"); if (CGM.getCodeGenOpts().InstrumentForProfiling) EmitMCountInstrumentation(); if (RetTy->isVoidType()) { // Void type; nothing to return. ReturnValue = 0; } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && hasAggregateLLVMType(CurFnInfo->getReturnType())) { // Indirect aggregate return; emit returned value directly into sret slot. // This reduces code size, and affects correctness in C++. ReturnValue = CurFn->arg_begin(); } else { ReturnValue = CreateIRTemp(RetTy, "retval"); // Tell the epilog emitter to autorelease the result. We do this // now so that various specialized functions can suppress it // during their IR-generation. if (getLangOpts().ObjCAutoRefCount && !CurFnInfo->isReturnsRetained() && RetTy->isObjCRetainableType()) AutoreleaseResult = true; } EmitStartEHSpec(CurCodeDecl); PrologueCleanupDepth = EHStack.stable_begin(); EmitFunctionProlog(*CurFnInfo, CurFn, Args); if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) { CGM.getCXXABI().EmitInstanceFunctionProlog(*this); const CXXMethodDecl *MD = cast<CXXMethodDecl>(D); if (MD->getParent()->isLambda() && MD->getOverloadedOperator() == OO_Call) { // We're in a lambda; figure out the captures. MD->getParent()->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField); if (LambdaThisCaptureField) { // If this lambda captures this, load it. QualType LambdaTagType = getContext().getTagDeclType(LambdaThisCaptureField->getParent()); LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, LambdaTagType); LValue ThisLValue = EmitLValueForField(LambdaLV, LambdaThisCaptureField); CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal(); } } else { // Not in a lambda; just use 'this' from the method. // FIXME: Should we generate a new load for each use of 'this'? The // fast register allocator would be happier... CXXThisValue = CXXABIThisValue; } } // 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(); i != e; ++i) { QualType Ty = (*i)->getType(); if (Ty->isVariablyModifiedType()) EmitVariablyModifiedType(Ty); } // Emit a location at the end of the prologue. if (CGDebugInfo *DI = getDebugInfo()) DI->EmitLocation(Builder, StartLoc); }
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation StartLoc) { const Decl *D = GD.getDecl(); DidCallStackSave = false; CurCodeDecl = CurFuncDecl = D; FnRetTy = RetTy; CurFn = Fn; CurFnInfo = &FnInfo; assert(CurFn->isDeclaration() && "Function already has body?"); // Pass inline keyword to optimizer if it appears explicitly on any // declaration. if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) for (FunctionDecl::redecl_iterator RI = FD->redecls_begin(), RE = FD->redecls_end(); RI != RE; ++RI) if (RI->isInlineSpecified()) { Fn->addFnAttr(llvm::Attribute::InlineHint); break; } if (getContext().getLangOptions().OpenCL) { // Add metadata for a kernel function. if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) if (FD->hasAttr<OpenCLKernelAttr>()) { llvm::LLVMContext &Context = getLLVMContext(); llvm::NamedMDNode *OpenCLMetadata = CGM.getModule().getOrInsertNamedMetadata("opencl.kernels"); llvm::Value *Op = Fn; OpenCLMetadata->addOperand(llvm::MDNode::get(Context, Op)); } } llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); // 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(Int32Ty); AllocaInsertPt = new llvm::BitCastInst(Undef, Int32Ty, "", EntryBB); if (Builder.isNamePreserving()) AllocaInsertPt->setName("allocapt"); ReturnBlock = getJumpDestInCurrentScope("return"); Builder.SetInsertPoint(EntryBB); // Emit subprogram debug descriptor. if (CGDebugInfo *DI = getDebugInfo()) { // FIXME: what is going on here and why does it ignore all these // interesting type properties? QualType FnType = getContext().getFunctionType(RetTy, 0, 0, FunctionProtoType::ExtProtoInfo()); DI->setLocation(StartLoc); DI->EmitFunctionStart(GD, FnType, CurFn, Builder); } if (ShouldInstrumentFunction()) EmitFunctionInstrumentation("__cyg_profile_func_enter"); if (CGM.getCodeGenOpts().InstrumentForProfiling) EmitMCountInstrumentation(); if (RetTy->isVoidType()) { // Void type; nothing to return. ReturnValue = 0; } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect && hasAggregateLLVMType(CurFnInfo->getReturnType())) { // Indirect aggregate return; emit returned value directly into sret slot. // This reduces code size, and affects correctness in C++. ReturnValue = CurFn->arg_begin(); } else { ReturnValue = CreateIRTemp(RetTy, "retval"); // Tell the epilog emitter to autorelease the result. We do this // now so that various specialized functions can suppress it // during their IR-generation. if (getLangOptions().ObjCAutoRefCount && !CurFnInfo->isReturnsRetained() && RetTy->isObjCRetainableType()) AutoreleaseResult = true; } EmitStartEHSpec(CurCodeDecl); PrologueCleanupDepth = EHStack.stable_begin(); EmitFunctionProlog(*CurFnInfo, CurFn, Args); if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) CGM.getCXXABI().EmitInstanceFunctionProlog(*this); // 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(); i != e; ++i) { QualType Ty = (*i)->getType(); if (Ty->isVariablyModifiedType()) EmitVariablyModifiedType(Ty); } // Emit a location at the end of the prologue. if (CGDebugInfo *DI = getDebugInfo()) DI->EmitLocation(Builder, StartLoc); }