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); }
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); } }