diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp | 180 |
1 files changed, 119 insertions, 61 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp index 8191f02..06e90b6 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp @@ -16,9 +16,7 @@ #include "CGCUDARuntime.h" #include "CGCXXABI.h" #include "CGDebugInfo.h" -#include "CGException.h" #include "clang/Basic/TargetInfo.h" -#include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -31,20 +29,29 @@ using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : CodeGenTypeCache(cgm), CGM(cgm), - Target(CGM.getContext().getTargetInfo()), Builder(cgm.getModule().getContext()), + Target(CGM.getContext().getTargetInfo()), + Builder(cgm.getModule().getContext()), AutoreleaseResult(false), BlockInfo(0), BlockPointer(0), - NormalCleanupDest(0), NextCleanupDestIndex(1), - EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0), + LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1), + FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0), DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), - CXXThisDecl(0), CXXThisValue(0), CXXVTTDecl(0), CXXVTTValue(0), - OutermostConditional(0), TerminateLandingPad(0), TerminateHandler(0), - TrapBB(0) { + CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXVTTDecl(0), + CXXVTTValue(0), OutermostConditional(0), TerminateLandingPad(0), + TerminateHandler(0), TrapBB(0) { - CatchUndefined = getContext().getLangOptions().CatchUndefined; + CatchUndefined = getContext().getLangOpts().CatchUndefined; CGM.getCXXABI().getMangleContext().startNewFunction(); } +CodeGenFunction::~CodeGenFunction() { + // If there are any unclaimed block infos, go ahead and destroy them + // now. This can happen if IR-gen gets clever and skips evaluating + // something. + if (FirstBlockInfo) + destroyBlockInfos(FirstBlockInfo); +} + llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { return CGM.getTypes().ConvertTypeForMem(T); @@ -222,8 +229,7 @@ void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) { llvm::PointerType *PointerTy = Int8PtrTy; llvm::Type *ProfileFuncArgs[] = { PointerTy, PointerTy }; llvm::FunctionType *FunctionTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), - ProfileFuncArgs, false); + llvm::FunctionType::get(VoidTy, ProfileFuncArgs, false); llvm::Constant *F = CGM.CreateRuntimeFunction(FunctionTy, Fn); llvm::CallInst *CallSite = Builder.CreateCall( @@ -237,8 +243,7 @@ void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) { } void CodeGenFunction::EmitMCountInstrumentation() { - llvm::FunctionType *FTy = - llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), false); + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); llvm::Constant *MCountFn = CGM.CreateRuntimeFunction(FTy, Target.getMCountName()); @@ -261,15 +266,16 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // 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 (!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().getLangOptions().OpenCL) { + if (getContext().getLangOpts().OpenCL) { // Add metadata for a kernel function. if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) if (FD->hasAttr<OpenCLKernelAttr>()) { @@ -298,12 +304,19 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // Emit subprogram debug descriptor. if (CGDebugInfo *DI = getDebugInfo()) { - // FIXME: what is going on here and why does it ignore all these - // interesting type properties? + 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, 0, 0, + getContext().getFunctionType(RetTy, ArgsArray, NumArgs, FunctionProtoType::ExtProtoInfo()); + delete[] ArgsArray; + DI->setLocation(StartLoc); DI->EmitFunctionStart(GD, FnType, CurFn, Builder); } @@ -328,7 +341,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // 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 && + if (getLangOpts().ObjCAutoRefCount && !CurFnInfo->isReturnsRetained() && RetTy->isObjCRetainableType()) AutoreleaseResult = true; @@ -339,8 +352,27 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, PrologueCleanupDepth = EHStack.stable_begin(); EmitFunctionProlog(*CurFnInfo, CurFn, Args); - if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) + 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. + LValue ThisLValue = EmitLValueForField(CXXABIThisValue, + LambdaThisCaptureField, 0); + 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. @@ -397,9 +429,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, 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)); + 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(); @@ -412,10 +443,21 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, EmitDestructorBody(Args); else if (isa<CXXConstructorDecl>(FD)) EmitConstructorBody(Args); - else if (getContext().getLangOptions().CUDA && + 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); @@ -505,15 +547,14 @@ bool CodeGenFunction:: ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APInt &ResultInt) { // FIXME: Rename and handle conversion of other evaluatable things // to bool. - Expr::EvalResult Result; - if (!Cond->Evaluate(Result, getContext()) || !Result.Val.isInt() || - Result.HasSideEffects) + llvm::APSInt Int; + if (!Cond->EvaluateAsInt(Int, getContext())) return false; // Not foldable, not integer or not fully evaluatable. - + if (CodeGenFunction::ContainsLabel(Cond)) return false; // Contains a label. - - ResultInt = Result.Val.getInt(); + + ResultInt = Int; return true; } @@ -606,29 +647,24 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, } if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(Cond)) { - // Handle ?: operator. - - // Just ignore GNU ?: extension. - if (CondOp->getLHS()) { - // br(c ? x : y, t, f) -> br(c, br(x, t, f), br(y, t, f)) - llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true"); - llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false"); + // br(c ? x : y, t, f) -> br(c, br(x, t, f), br(y, t, f)) + llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true"); + llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false"); - ConditionalEvaluation cond(*this); - EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock); + ConditionalEvaluation cond(*this); + EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock); - cond.begin(*this); - EmitBlock(LHSBlock); - EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock); - cond.end(*this); + cond.begin(*this); + EmitBlock(LHSBlock); + EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock); + cond.end(*this); - cond.begin(*this); - EmitBlock(RHSBlock); - EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock); - cond.end(*this); + cond.begin(*this); + EmitBlock(RHSBlock); + EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock); + cond.end(*this); - return; - } + return; } // Emit the code with the fully general case. @@ -696,7 +732,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, void CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) { // Ignore empty classes in C++. - if (getContext().getLangOptions().CPlusPlus) { + if (getContext().getLangOpts().CPlusPlus) { if (const RecordType *RT = Ty->getAs<RecordType>()) { if (cast<CXXRecordDecl>(RT->getDecl())->isEmpty()) return; @@ -916,19 +952,19 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { // We're going to walk down into the type and look for VLA // expressions. - type = type.getCanonicalType(); do { assert(type->isVariablyModifiedType()); const Type *ty = type.getTypePtr(); switch (ty->getTypeClass()) { + #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) #include "clang/AST/TypeNodes.def" - llvm_unreachable("unexpected dependent or non-canonical type!"); + llvm_unreachable("unexpected dependent type!"); // These types are never variably-modified. case Type::Builtin: @@ -937,6 +973,8 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::ExtVector: case Type::Record: case Type::Enum: + case Type::Elaborated: + case Type::TemplateSpecialization: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: @@ -986,11 +1024,31 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { break; } - case Type::FunctionProto: + case Type::FunctionProto: case Type::FunctionNoProto: type = cast<FunctionType>(ty)->getResultType(); break; + case Type::Paren: + case Type::TypeOf: + case Type::UnaryTransform: + case Type::Attributed: + case Type::SubstTemplateTypeParm: + // Keep walking after single level desugaring. + type = type.getSingleStepDesugaredType(getContext()); + break; + + case Type::Typedef: + case Type::Decltype: + case Type::Auto: + // Stop walking: nothing to do. + return; + + case Type::TypeOfExpr: + // Stop walking: emit typeof expression. + EmitIgnoredExpr(cast<TypeOfExprType>(ty)->getUnderlyingExpr()); + return; + case Type::Atomic: type = cast<AtomicType>(ty)->getValueType(); break; |