diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 92 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 65 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenABITypes.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 18 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.cpp | 140 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 15 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 5 |
11 files changed, 257 insertions, 115 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 471b7be9e2a..10493d396d0 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -342,6 +342,71 @@ Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) { return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue); } +/// Checks if using the result of __builtin_object_size(p, @p From) in place of +/// __builtin_object_size(p, @p To) is correct +static bool areBOSTypesCompatible(int From, int To) { + // Note: Our __builtin_object_size implementation currently treats Type=0 and + // Type=2 identically. Encoding this implementation detail here may make + // improving __builtin_object_size difficult in the future, so it's omitted. + return From == To || (From == 0 && To == 1) || (From == 3 && To == 2); +} + +static llvm::Value * +getDefaultBuiltinObjectSizeResult(unsigned Type, llvm::IntegerType *ResType) { + return ConstantInt::get(ResType, (Type & 2) ? 0 : -1, /*isSigned=*/true); +} + +llvm::Value * +CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType) { + uint64_t ObjectSize; + if (!E->tryEvaluateObjectSize(ObjectSize, getContext(), Type)) + return emitBuiltinObjectSize(E, Type, ResType); + return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true); +} + +/// Returns a Value corresponding to the size of the given expression. +/// This Value may be either of the following: +/// - A llvm::Argument (if E is a param with the pass_object_size attribute on +/// it) +/// - A call to the @llvm.objectsize intrinsic +llvm::Value * +CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType) { + // We need to reference an argument if the pointer is a parameter with the + // pass_object_size attribute. + if (auto *D = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) { + auto *Param = dyn_cast<ParmVarDecl>(D->getDecl()); + auto *PS = D->getDecl()->getAttr<PassObjectSizeAttr>(); + if (Param != nullptr && PS != nullptr && + areBOSTypesCompatible(PS->getType(), Type)) { + auto Iter = SizeArguments.find(Param); + assert(Iter != SizeArguments.end()); + + const ImplicitParamDecl *D = Iter->second; + auto DIter = LocalDeclMap.find(D); + assert(DIter != LocalDeclMap.end()); + + return EmitLoadOfScalar(DIter->second, /*volatile=*/false, + getContext().getSizeType(), E->getLocStart()); + } + } + + // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't + // evaluate E for side-effects. In either case, we shouldn't lower to + // @llvm.objectsize. + if (Type == 3 || E->HasSideEffects(getContext())) + return getDefaultBuiltinObjectSizeResult(Type, ResType); + + // LLVM only supports 0 and 2, make sure that we pass along that + // as a boolean. + auto *CI = ConstantInt::get(Builder.getInt1Ty(), (Type & 2) >> 1); + // FIXME: Get right address space. + llvm::Type *Tys[] = {ResType, Builder.getInt8PtrTy(0)}; + Value *F = CGM.getIntrinsic(Intrinsic::objectsize, Tys); + return Builder.CreateCall(F, {EmitScalarExpr(E), CI}); +} + RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -586,26 +651,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateCall(F, ArgValue)); } case Builtin::BI__builtin_object_size: { - // We rely on constant folding to deal with expressions with side effects. - assert(!E->getArg(0)->HasSideEffects(getContext()) && - "should have been constant folded"); - - // We pass this builtin onto the optimizer so that it can - // figure out the object size in more complex cases. - llvm::Type *ResType = ConvertType(E->getType()); - - // LLVM only supports 0 and 2, make sure that we pass along that - // as a boolean. - Value *Ty = EmitScalarExpr(E->getArg(1)); - ConstantInt *CI = dyn_cast<ConstantInt>(Ty); - assert(CI); - uint64_t val = CI->getZExtValue(); - CI = ConstantInt::get(Builder.getInt1Ty(), (val & 0x2) >> 1); - // FIXME: Get right address space. - llvm::Type *Tys[] = { ResType, Builder.getInt8PtrTy(0) }; - Value *F = CGM.getIntrinsic(Intrinsic::objectsize, Tys); - return RValue::get( - Builder.CreateCall(F, {EmitScalarExpr(E->getArg(0)), CI})); + unsigned Type = + E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue(); + auto *ResType = cast<llvm::IntegerType>(ConvertType(E->getType())); + + // We pass this builtin onto the optimizer so that it can figure out the + // object size in more complex cases. + return RValue::get(emitBuiltinObjectSize(E->getArg(0), Type, ResType)); } case Builtin::BI__builtin_prefetch: { Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 078b98d40df..e4da447eddc 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -85,7 +85,7 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer( const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( - CGM.getTypes().arrangeCXXMethodType(RD, FPT)); + CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); return llvm::Constant::getNullValue(FTy->getPointerTo()); } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 70cb4713e69..80f88fb8d15 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -92,15 +92,41 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) { FTNP->getExtInfo(), RequiredArgs(0)); } +/// Adds the formal paramaters in FPT to the given prefix. If any parameter in +/// FPT has pass_object_size attrs, then we'll add parameters for those, too. +static void appendParameterTypes(const CodeGenTypes &CGT, + SmallVectorImpl<CanQualType> &prefix, + const CanQual<FunctionProtoType> &FPT, + const FunctionDecl *FD) { + // Fast path: unknown target. + if (FD == nullptr) { + prefix.append(FPT->param_type_begin(), FPT->param_type_end()); + return; + } + + // In the vast majority cases, we'll have precisely FPT->getNumParams() + // parameters; the only thing that can change this is the presence of + // pass_object_size. So, we preallocate for the common case. + prefix.reserve(prefix.size() + FPT->getNumParams()); + + assert(FD->getNumParams() == FPT->getNumParams()); + for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { + prefix.push_back(FPT->getParamType(I)); + if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>()) + prefix.push_back(CGT.getContext().getSizeType()); + } +} + /// Arrange the LLVM function layout for a value of the given function /// type, on top of any implicit parameters already stored. static const CGFunctionInfo & arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, SmallVectorImpl<CanQualType> &prefix, - CanQual<FunctionProtoType> FTP) { + CanQual<FunctionProtoType> FTP, + const FunctionDecl *FD) { RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size()); // FIXME: Kill copy. - prefix.append(FTP->param_type_begin(), FTP->param_type_end()); + appendParameterTypes(CGT, prefix, FTP, FD); CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, /*chainCall=*/false, prefix, @@ -110,10 +136,11 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, /// Arrange the argument and result information for a value of the /// given freestanding function type. const CGFunctionInfo & -CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) { +CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP, + const FunctionDecl *FD) { SmallVector<CanQualType, 16> argTypes; return ::arrangeLLVMFunctionInfo(*this, /*instanceMethod=*/false, argTypes, - FTP); + FTP, FD); } static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { @@ -156,7 +183,8 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { /// constructor or destructor. const CGFunctionInfo & CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, - const FunctionProtoType *FTP) { + const FunctionProtoType *FTP, + const CXXMethodDecl *MD) { SmallVector<CanQualType, 16> argTypes; // Add the 'this' pointer. @@ -167,7 +195,7 @@ CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, return ::arrangeLLVMFunctionInfo( *this, true, argTypes, - FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>()); + FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>(), MD); } /// Arrange the argument and result information for a declaration or @@ -184,10 +212,10 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { if (MD->isInstance()) { // The abstract case is perfectly fine. const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(MD); - return arrangeCXXMethodType(ThisType, prototype.getTypePtr()); + return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD); } - return arrangeFreeFunctionType(prototype); + return arrangeFreeFunctionType(prototype, MD); } const CGFunctionInfo & @@ -208,7 +236,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, CanQual<FunctionProtoType> FTP = GetFormalType(MD); // Add the formal parameters. - argTypes.append(FTP->param_type_begin(), FTP->param_type_end()); + appendParameterTypes(*this, argTypes, FTP, MD); TheCXXABI.buildStructorSignature(MD, Type, argTypes); @@ -274,7 +302,7 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { } assert(isa<FunctionProtoType>(FTy)); - return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>()); + return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>(), FD); } /// Arrange the argument and result information for the declaration or @@ -2803,6 +2831,21 @@ void CodeGenFunction::EmitCallArgs( llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, const FunctionDecl *CalleeDecl, unsigned ParamsToSkip) { assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin())); + + auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg) { + if (CalleeDecl == nullptr || I >= CalleeDecl->getNumParams()) + return; + auto *PS = CalleeDecl->getParamDecl(I)->getAttr<PassObjectSizeAttr>(); + if (PS == nullptr) + return; + + const auto &Context = getContext(); + auto SizeTy = Context.getSizeType(); + auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); + llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T); + Args.add(RValue::get(V), SizeTy); + }; + // We *have* to evaluate arguments from right to left in the MS C++ ABI, // because arguments are destroyed left to right in the callee. if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { @@ -2823,6 +2866,7 @@ void CodeGenFunction::EmitCallArgs( EmitCallArg(Args, *Arg, ArgTypes[I]); EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), CalleeDecl, ParamsToSkip + I); + MaybeEmitImplicitObjectSize(I, *Arg); } // Un-reverse the arguments we just evaluated so they match up with the LLVM @@ -2837,6 +2881,7 @@ void CodeGenFunction::EmitCallArgs( EmitCallArg(Args, *Arg, ArgTypes[I]); EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), CalleeDecl, ParamsToSkip + I); + MaybeEmitImplicitObjectSize(I, *Arg); } } diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp index 85495eeaedf..643c996e2ec 100644 --- a/clang/lib/CodeGen/CodeGenABITypes.cpp +++ b/clang/lib/CodeGen/CodeGenABITypes.cpp @@ -44,8 +44,9 @@ CodeGenABITypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, } const CGFunctionInfo & -CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty) { - return CGM->getTypes().arrangeFreeFunctionType(Ty); +CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty, + const FunctionDecl *FD) { + return CGM->getTypes().arrangeFreeFunctionType(Ty, FD); } const CGFunctionInfo & @@ -55,8 +56,9 @@ CodeGenABITypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty) { const CGFunctionInfo & CodeGenABITypes::arrangeCXXMethodType(const CXXRecordDecl *RD, - const FunctionProtoType *FTP) { - return CGM->getTypes().arrangeCXXMethodType(RD, FTP); + const FunctionProtoType *FTP, + const CXXMethodDecl *MD) { + return CGM->getTypes().arrangeCXXMethodType(RD, FTP, MD); } const CGFunctionInfo &CodeGenABITypes::arrangeFreeFunctionCall( diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 4c1d6af7530..31a93e001f8 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -920,7 +920,18 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, CGM.getCXXABI().buildThisParam(*this, Args); } - Args.append(FD->param_begin(), FD->param_end()); + for (auto *Param : FD->params()) { + Args.push_back(Param); + if (!Param->hasAttr<PassObjectSizeAttr>()) + continue; + + IdentifierInfo *NoID = nullptr; + auto *Implicit = ImplicitParamDecl::Create( + getContext(), Param->getDeclContext(), Param->getLocation(), NoID, + getContext().getSizeType()); + SizeArguments[Param] = Implicit; + Args.push_back(Implicit); + } if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))) CGM.getCXXABI().addImplicitStructorParams(*this, ResTy, Args); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a5ce921cd53..802386b5106 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -914,6 +914,12 @@ private: /// decls. DeclMapTy LocalDeclMap; + /// SizeArguments - If a ParmVarDecl had the pass_object_size attribute, this + /// will contain a mapping from said ParmVarDecl to its implicit "object_size" + /// parameter. + llvm::SmallDenseMap<const ParmVarDecl *, const ImplicitParamDecl *, 2> + SizeArguments; + /// Track escaped local variables with auto storage. Used during SEH /// outlining to produce a call to llvm.localescape. llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals; @@ -3062,6 +3068,18 @@ private: std::string &ConstraintStr, SourceLocation Loc); + /// \brief Attempts to statically evaluate the object size of E. If that + /// fails, emits code to figure the size of E out for us. This is + /// pass_object_size aware. + llvm::Value *evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType); + + /// \brief Emits the size of E, as required by __builtin_object_size. This + /// function is aware of pass_object_size parameters, and will act accordingly + /// if E is a parameter with the pass_object_size attribute. + llvm::Value *emitBuiltinObjectSize(const Expr *E, unsigned Type, + llvm::IntegerType *ResType); + public: #ifndef NDEBUG // Determine whether the given argument is an Objective-C method diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index a15c43c313a..faae080ff8e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1830,8 +1830,11 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD, bool DontDefer, bool IsForDefinition) { // If there was no specific requested type, just convert it now. - if (!Ty) - Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType()); + if (!Ty) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + auto CanonTy = Context.getCanonicalType(FD->getType()); + Ty = getTypes().ConvertFunctionType(CanonTy, FD); + } StringRef MangledName = getMangledName(GD); return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer, diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index f0a25ba4290..fcda0532055 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -294,6 +294,76 @@ static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext, llvm_unreachable("Unknown float format!"); } +llvm::Type *CodeGenTypes::ConvertFunctionType(QualType QFT, + const FunctionDecl *FD) { + assert(QFT.isCanonical()); + const Type *Ty = QFT.getTypePtr(); + const FunctionType *FT = cast<FunctionType>(QFT.getTypePtr()); + // First, check whether we can build the full function type. If the + // function type depends on an incomplete type (e.g. a struct or enum), we + // cannot lower the function type. + if (!isFuncTypeConvertible(FT)) { + // This function's type depends on an incomplete tag type. + + // Force conversion of all the relevant record types, to make sure + // we re-convert the FunctionType when appropriate. + if (const RecordType *RT = FT->getReturnType()->getAs<RecordType>()) + ConvertRecordDeclType(RT->getDecl()); + if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) + for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++) + if (const RecordType *RT = FPT->getParamType(i)->getAs<RecordType>()) + ConvertRecordDeclType(RT->getDecl()); + + SkippedLayout = true; + + // Return a placeholder type. + return llvm::StructType::get(getLLVMContext()); + } + + // While we're converting the parameter types for a function, we don't want + // to recursively convert any pointed-to structs. Converting directly-used + // structs is ok though. + if (!RecordsBeingLaidOut.insert(Ty).second) { + SkippedLayout = true; + return llvm::StructType::get(getLLVMContext()); + } + + // The function type can be built; call the appropriate routines to + // build it. + const CGFunctionInfo *FI; + if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) { + FI = &arrangeFreeFunctionType( + CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0)), FD); + } else { + const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(FT); + FI = &arrangeFreeFunctionType( + CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0))); + } + + llvm::Type *ResultType = nullptr; + // If there is something higher level prodding our CGFunctionInfo, then + // don't recurse into it again. + if (FunctionsBeingProcessed.count(FI)) { + + ResultType = llvm::StructType::get(getLLVMContext()); + SkippedLayout = true; + } else { + + // Otherwise, we're good to go, go ahead and convert it. + ResultType = GetFunctionType(*FI); + } + + RecordsBeingLaidOut.erase(Ty); + + if (SkippedLayout) + TypeCache.clear(); + + if (RecordsBeingLaidOut.empty()) + while (!DeferredRecords.empty()) + ConvertRecordDeclType(DeferredRecords.pop_back_val()); + return ResultType; +} + /// ConvertType - Convert the specified type to its LLVM form. llvm::Type *CodeGenTypes::ConvertType(QualType T) { T = Context.getCanonicalType(T); @@ -485,75 +555,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { break; } case Type::FunctionNoProto: - case Type::FunctionProto: { - const FunctionType *FT = cast<FunctionType>(Ty); - // First, check whether we can build the full function type. If the - // function type depends on an incomplete type (e.g. a struct or enum), we - // cannot lower the function type. - if (!isFuncTypeConvertible(FT)) { - // This function's type depends on an incomplete tag type. - - // Force conversion of all the relevant record types, to make sure - // we re-convert the FunctionType when appropriate. - if (const RecordType *RT = FT->getReturnType()->getAs<RecordType>()) - ConvertRecordDeclType(RT->getDecl()); - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) - for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++) - if (const RecordType *RT = FPT->getParamType(i)->getAs<RecordType>()) - ConvertRecordDeclType(RT->getDecl()); - - // Return a placeholder type. - ResultType = llvm::StructType::get(getLLVMContext()); - - SkippedLayout = true; - break; - } - - // While we're converting the parameter types for a function, we don't want - // to recursively convert any pointed-to structs. Converting directly-used - // structs is ok though. - if (!RecordsBeingLaidOut.insert(Ty).second) { - ResultType = llvm::StructType::get(getLLVMContext()); - - SkippedLayout = true; - break; - } - - // The function type can be built; call the appropriate routines to - // build it. - const CGFunctionInfo *FI; - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) { - FI = &arrangeFreeFunctionType( - CanQual<FunctionProtoType>::CreateUnsafe(QualType(FPT, 0))); - } else { - const FunctionNoProtoType *FNPT = cast<FunctionNoProtoType>(FT); - FI = &arrangeFreeFunctionType( - CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0))); - } - - // If there is something higher level prodding our CGFunctionInfo, then - // don't recurse into it again. - if (FunctionsBeingProcessed.count(FI)) { - - ResultType = llvm::StructType::get(getLLVMContext()); - SkippedLayout = true; - } else { - - // Otherwise, we're good to go, go ahead and convert it. - ResultType = GetFunctionType(*FI); - } - - RecordsBeingLaidOut.erase(Ty); - - if (SkippedLayout) - TypeCache.clear(); - - if (RecordsBeingLaidOut.empty()) - while (!DeferredRecords.empty()) - ConvertRecordDeclType(DeferredRecords.pop_back_val()); + case Type::FunctionProto: + ResultType = ConvertFunctionType(T); break; - } - case Type::ObjCObject: ResultType = ConvertType(cast<ObjCObjectType>(Ty)->getBaseType()); break; diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index c40c2b740c2..a96f23c4489 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -178,6 +178,14 @@ public: /// ConvertType - Convert type T into a llvm::Type. llvm::Type *ConvertType(QualType T); + /// \brief Converts the GlobalDecl into an llvm::Type. This should be used + /// when we know the target of the function we want to convert. This is + /// because some functions (explicitly, those with pass_object_size + /// parameters) may not have the same signature as their type portrays, and + /// can only be called directly. + llvm::Type *ConvertFunctionType(QualType FT, + const FunctionDecl *FD = nullptr); + /// 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 @@ -264,11 +272,12 @@ public: const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD); const CGFunctionInfo &arrangeMSCtorClosure(const CXXConstructorDecl *CD, CXXCtorType CT); - - const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty); + const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty, + const FunctionDecl *FD); const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty); const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD, - const FunctionProtoType *FTP); + const FunctionProtoType *FTP, + const CXXMethodDecl *MD); /// "Arrange" the LLVM information for a call or type with the given /// signature. This is largely an internal method; other clients diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index f5b2d90d509..44f64569e2c 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -534,9 +534,8 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); - llvm::FunctionType *FTy = - CGM.getTypes().GetFunctionType( - CGM.getTypes().arrangeCXXMethodType(RD, FPT)); + llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( + CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1); diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index d99efda3abc..711b08e6a29 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -3225,9 +3225,8 @@ llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( const FunctionProtoType *FPT = MPT->getPointeeType()->castAs<FunctionProtoType>(); const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - llvm::FunctionType *FTy = - CGM.getTypes().GetFunctionType( - CGM.getTypes().arrangeCXXMethodType(RD, FPT)); + llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( + CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); CGBuilderTy &Builder = CGF.Builder; MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); |