| //===--- CGCall.cpp - Encapsulate calling convention details --------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // These classes wrap the information about a call or function | |
| // definition used to handle ABI compliancy. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "CGCall.h" | |
| #include "ABIInfo.h" | |
| #include "ABIInfoImpl.h" | |
| #include "CGBlocks.h" | |
| #include "CGCXXABI.h" | |
| #include "CGCleanup.h" | |
| #include "CGDebugInfo.h" | |
| #include "CGRecordLayout.h" | |
| #include "CodeGenFunction.h" | |
| #include "CodeGenModule.h" | |
| #include "CodeGenPGO.h" | |
| #include "QualTypeMapper.h" | |
| #include "TargetInfo.h" | |
| #include "clang/AST/Attr.h" | |
| #include "clang/AST/Decl.h" | |
| #include "clang/AST/DeclCXX.h" | |
| #include "clang/AST/DeclObjC.h" | |
| #include "clang/AST/RecordLayout.h" | |
| #include "clang/Basic/CodeGenOptions.h" | |
| #include "clang/Basic/DiagnosticFrontend.h" | |
| #include "clang/Basic/TargetInfo.h" | |
| #include "clang/CodeGen/CGFunctionInfo.h" | |
| #include "clang/CodeGen/SwiftCallingConv.h" | |
| #include "clang/CodeGenUtils/CallUtils.h" | |
| #include "llvm/ABI/FunctionInfo.h" | |
| #include "llvm/ABI/IRTypeMapper.h" | |
| #include "llvm/ABI/TargetInfo.h" | |
| #include "llvm/ABI/Types.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/ADT/StringExtras.h" | |
| #include "llvm/Analysis/ValueTracking.h" | |
| #include "llvm/IR/Assumptions.h" | |
| #include "llvm/IR/AttributeMask.h" | |
| #include "llvm/IR/Attributes.h" | |
| #include "llvm/IR/CallingConv.h" | |
| #include "llvm/IR/DataLayout.h" | |
| #include "llvm/IR/DebugInfoMetadata.h" | |
| #include "llvm/IR/InlineAsm.h" | |
| #include "llvm/IR/IntrinsicInst.h" | |
| #include "llvm/IR/Intrinsics.h" | |
| #include "llvm/IR/Type.h" | |
| #include "llvm/Transforms/Utils/Local.h" | |
| #include <optional> | |
| using namespace clang; | |
| using namespace CodeGen; | |
| /***/ | |
| unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { | |
| switch (CC) { | |
| case CC_C: | |
| // On SPIR/SPIR-V, CC_C is the AST-level default calling convention, but | |
| // it still needs to lower to spir_func so IR consumers can rely on the | |
| // calling convention to distinguish device functions. | |
| if (Target.getTriple().isSPIROrSPIRV()) | |
| return llvm::CallingConv::SPIR_FUNC; | |
| return llvm::CallingConv::C; | |
| case CC_X86StdCall: | |
| return llvm::CallingConv::X86_StdCall; | |
| case CC_X86FastCall: | |
| return llvm::CallingConv::X86_FastCall; | |
| case CC_X86RegCall: | |
| return llvm::CallingConv::X86_RegCall; | |
| case CC_X86ThisCall: | |
| return llvm::CallingConv::X86_ThisCall; | |
| case CC_Win64: | |
| return llvm::CallingConv::Win64; | |
| case CC_X86_64SysV: | |
| return llvm::CallingConv::X86_64_SysV; | |
| case CC_AAPCS: | |
| return llvm::CallingConv::ARM_AAPCS; | |
| case CC_AAPCS_VFP: | |
| return llvm::CallingConv::ARM_AAPCS_VFP; | |
| case CC_IntelOclBicc: | |
| return llvm::CallingConv::Intel_OCL_BI; | |
| // TODO: Add support for __pascal to LLVM. | |
| case CC_X86Pascal: | |
| return llvm::CallingConv::C; | |
| // TODO: Add support for __vectorcall to LLVM. | |
| case CC_X86VectorCall: | |
| return llvm::CallingConv::X86_VectorCall; | |
| case CC_AArch64VectorCall: | |
| return llvm::CallingConv::AArch64_VectorCall; | |
| case CC_AArch64SVEPCS: | |
| return llvm::CallingConv::AArch64_SVE_VectorCall; | |
| case CC_DeviceKernel: | |
| return CGM.getTargetCodeGenInfo().getDeviceKernelCallingConv(); | |
| case CC_PreserveMost: | |
| return llvm::CallingConv::PreserveMost; | |
| case CC_PreserveAll: | |
| return llvm::CallingConv::PreserveAll; | |
| case CC_Swift: | |
| return llvm::CallingConv::Swift; | |
| case CC_SwiftAsync: | |
| return llvm::CallingConv::SwiftTail; | |
| case CC_M68kRTD: | |
| return llvm::CallingConv::M68k_RTD; | |
| case CC_PreserveNone: | |
| return llvm::CallingConv::PreserveNone; | |
| // clang-format off | |
| case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall; | |
| // clang-format on | |
| #define CC_VLS_CASE(ABI_VLEN) \ | |
| case CC_RISCVVLSCall_##ABI_VLEN: \ | |
| return llvm::CallingConv::RISCV_VLSCall_##ABI_VLEN; | |
| CC_VLS_CASE(32) | |
| CC_VLS_CASE(64) | |
| CC_VLS_CASE(128) | |
| CC_VLS_CASE(256) | |
| CC_VLS_CASE(512) | |
| CC_VLS_CASE(1024) | |
| CC_VLS_CASE(2048) | |
| CC_VLS_CASE(4096) | |
| CC_VLS_CASE(8192) | |
| CC_VLS_CASE(16384) | |
| CC_VLS_CASE(32768) | |
| CC_VLS_CASE(65536) | |
| #undef CC_VLS_CASE | |
| } | |
| llvm_unreachable("unhandled calling convention"); | |
| } | |
| /// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR | |
| /// qualification. Either or both of RD and MD may be null. A null RD indicates | |
| /// that there is no meaningful 'this' type, and a null MD can occur when | |
| /// calling a method pointer. | |
| CanQualType CodeGenTypes::DeriveThisType(const CXXRecordDecl *RD, | |
| const CXXMethodDecl *MD) { | |
| CanQualType RecTy; | |
| if (RD) | |
| RecTy = Context.getCanonicalTagType(RD); | |
| else | |
| RecTy = Context.VoidTy; | |
| if (MD) | |
| RecTy = CanQualType::CreateUnsafe(Context.getAddrSpaceQualType( | |
| RecTy, MD->getMethodQualifiers().getAddressSpace())); | |
| return Context.getPointerType(RecTy); | |
| } | |
| /// Returns the "extra-canonicalized" return type, which discards | |
| /// qualifiers on the return type. Codegen doesn't care about them, | |
| /// and it makes ABI code a little easier to be able to assume that | |
| /// all parameter and return types are top-level unqualified. | |
| static CanQualType GetReturnType(QualType RetTy) { | |
| return RetTy->getCanonicalTypeUnqualified(); | |
| } | |
| /// Arrange the argument and result information for a value of the given | |
| /// unprototyped freestanding function type. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) { | |
| // When translating an unprototyped function type, always use a | |
| // variadic type. | |
| return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(), | |
| FnInfoOpts::None, {}, FTNP->getExtInfo(), {}, | |
| RequiredArgs(0), /*ABIInfoFD=*/nullptr); | |
| } | |
| static void addExtParameterInfosForCall( | |
| llvm::SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, | |
| const FunctionProtoType *proto, unsigned prefixArgs, unsigned totalArgs) { | |
| assert(proto->hasExtParameterInfos()); | |
| assert(paramInfos.size() <= prefixArgs); | |
| assert(proto->getNumParams() + prefixArgs <= totalArgs); | |
| paramInfos.reserve(totalArgs); | |
| // Add default infos for any prefix args that don't already have infos. | |
| paramInfos.resize(prefixArgs); | |
| // Add infos for the prototype. | |
| for (const auto &ParamInfo : proto->getExtParameterInfos()) { | |
| paramInfos.push_back(ParamInfo); | |
| // pass_object_size params have no parameter info. | |
| if (ParamInfo.hasPassObjectSize()) | |
| paramInfos.emplace_back(); | |
| } | |
| assert(paramInfos.size() <= totalArgs && | |
| "Did we forget to insert pass_object_size args?"); | |
| // Add default infos for the variadic and/or suffix arguments. | |
| paramInfos.resize(totalArgs); | |
| } | |
| /// Adds the formal parameters 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, | |
| SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, | |
| CanQual<FunctionProtoType> FPT) { | |
| // Fast path: don't touch param info if we don't need to. | |
| if (!FPT->hasExtParameterInfos()) { | |
| assert(paramInfos.empty() && | |
| "We have paramInfos, but the prototype doesn't?"); | |
| prefix.append(FPT->param_type_begin(), FPT->param_type_end()); | |
| return; | |
| } | |
| unsigned PrefixSize = prefix.size(); | |
| // In the vast majority of 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()); | |
| auto ExtInfos = FPT->getExtParameterInfos(); | |
| assert(ExtInfos.size() == FPT->getNumParams()); | |
| for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { | |
| prefix.push_back(FPT->getParamType(I)); | |
| if (ExtInfos[I].hasPassObjectSize()) | |
| prefix.push_back(CGT.getContext().getCanonicalSizeType()); | |
| } | |
| addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize, | |
| prefix.size()); | |
| } | |
| using ExtParameterInfoList = | |
| SmallVector<FunctionProtoType::ExtParameterInfo, 16>; | |
| /// 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) { | |
| ExtParameterInfoList paramInfos; | |
| RequiredArgs Required = RequiredArgs::forPrototypePlus(FTP, prefix.size()); | |
| appendParameterTypes(CGT, prefix, paramInfos, FTP); | |
| CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); | |
| FnInfoOpts opts = | |
| instanceMethod ? FnInfoOpts::IsInstanceMethod : FnInfoOpts::None; | |
| return CGT.arrangeLLVMFunctionInfo(resultType, opts, prefix, | |
| FTP->getExtInfo(), paramInfos, Required, | |
| /*ABIInfoFD=*/nullptr); | |
| } | |
| using CanQualTypeList = SmallVector<CanQualType, 16>; | |
| /// Arrange the argument and result information for a value of the | |
| /// given freestanding function type. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) { | |
| CanQualTypeList argTypes; | |
| return ::arrangeLLVMFunctionInfo(*this, /*instanceMethod=*/false, argTypes, | |
| FTP); | |
| } | |
| static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D, | |
| bool IsTargetDefaultMSABI) { | |
| // Set the appropriate calling convention for the Function. | |
| if (D->hasAttr<StdCallAttr>()) | |
| return CC_X86StdCall; | |
| if (D->hasAttr<FastCallAttr>()) | |
| return CC_X86FastCall; | |
| if (D->hasAttr<RegCallAttr>()) | |
| return CC_X86RegCall; | |
| if (D->hasAttr<ThisCallAttr>()) | |
| return CC_X86ThisCall; | |
| if (D->hasAttr<VectorCallAttr>()) | |
| return CC_X86VectorCall; | |
| if (D->hasAttr<PascalAttr>()) | |
| return CC_X86Pascal; | |
| if (PcsAttr *PCS = D->getAttr<PcsAttr>()) | |
| return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP); | |
| if (D->hasAttr<AArch64VectorPcsAttr>()) | |
| return CC_AArch64VectorCall; | |
| if (D->hasAttr<AArch64SVEPcsAttr>()) | |
| return CC_AArch64SVEPCS; | |
| if (D->hasAttr<DeviceKernelAttr>()) | |
| return CC_DeviceKernel; | |
| if (D->hasAttr<IntelOclBiccAttr>()) | |
| return CC_IntelOclBicc; | |
| if (D->hasAttr<MSABIAttr>()) | |
| return IsTargetDefaultMSABI ? CC_C : CC_Win64; | |
| if (D->hasAttr<SysVABIAttr>()) | |
| return IsTargetDefaultMSABI ? CC_X86_64SysV : CC_C; | |
| if (D->hasAttr<PreserveMostAttr>()) | |
| return CC_PreserveMost; | |
| if (D->hasAttr<PreserveAllAttr>()) | |
| return CC_PreserveAll; | |
| if (D->hasAttr<M68kRTDAttr>()) | |
| return CC_M68kRTD; | |
| if (D->hasAttr<PreserveNoneAttr>()) | |
| return CC_PreserveNone; | |
| if (D->hasAttr<RISCVVectorCCAttr>()) | |
| return CC_RISCVVectorCall; | |
| if (RISCVVLSCCAttr *PCS = D->getAttr<RISCVVLSCCAttr>()) { | |
| switch (PCS->getVectorWidth()) { | |
| default: | |
| llvm_unreachable("Invalid RISC-V VLS ABI VLEN"); | |
| #define CC_VLS_CASE(ABI_VLEN) \ | |
| case ABI_VLEN: \ | |
| return CC_RISCVVLSCall_##ABI_VLEN; | |
| CC_VLS_CASE(32) | |
| CC_VLS_CASE(64) | |
| CC_VLS_CASE(128) | |
| CC_VLS_CASE(256) | |
| CC_VLS_CASE(512) | |
| CC_VLS_CASE(1024) | |
| CC_VLS_CASE(2048) | |
| CC_VLS_CASE(4096) | |
| CC_VLS_CASE(8192) | |
| CC_VLS_CASE(16384) | |
| CC_VLS_CASE(32768) | |
| CC_VLS_CASE(65536) | |
| #undef CC_VLS_CASE | |
| } | |
| } | |
| return CC_C; | |
| } | |
| /// Arrange the argument and result information for a call to an | |
| /// unknown C++ non-static member function of the given abstract type. | |
| /// (A null RD means we don't have any meaningful "this" argument type, | |
| /// so fall back to a generic pointer type). | |
| /// The member function must be an ordinary function, i.e. not a | |
| /// constructor or destructor. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD, | |
| const FunctionProtoType *FTP, | |
| const CXXMethodDecl *MD) { | |
| CanQualTypeList argTypes; | |
| // Add the 'this' pointer. | |
| argTypes.push_back(DeriveThisType(RD, MD)); | |
| auto CanonicalFTP = | |
| FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>(); | |
| ExtParameterInfoList paramInfos; | |
| RequiredArgs required = RequiredArgs::forPrototypePlus( | |
| CanonicalFTP.getTypePtr(), argTypes.size()); | |
| appendParameterTypes(*this, argTypes, paramInfos, CanonicalFTP); | |
| return arrangeLLVMFunctionInfo( | |
| CanonicalFTP->getReturnType().getUnqualifiedType(), | |
| FnInfoOpts::IsInstanceMethod, argTypes, CanonicalFTP->getExtInfo(), | |
| paramInfos, required, MD); | |
| } | |
| /// Set calling convention for CUDA/HIP kernel. | |
| static void setCUDAKernelCallingConvention(CanQualType &FTy, CodeGenModule &CGM, | |
| const FunctionDecl *FD) { | |
| if (FD->hasAttr<CUDAGlobalAttr>()) { | |
| const FunctionType *FT = FTy->getAs<FunctionType>(); | |
| CGM.getTargetCodeGenInfo().setCUDAKernelCallingConvention(FT); | |
| FTy = FT->getCanonicalTypeUnqualified(); | |
| } | |
| } | |
| /// Arrange the argument and result information for a declaration or | |
| /// definition of the given C++ non-static member function. The | |
| /// member function must be an ordinary function, i.e. not a | |
| /// constructor or destructor. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { | |
| assert(!isa<CXXConstructorDecl>(MD) && "wrong method for constructors!"); | |
| assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!"); | |
| CanQualType FT = CodeGenUtils::getFormalType(MD).getAs<Type>(); | |
| setCUDAKernelCallingConvention(FT, CGM, MD); | |
| auto prototype = FT.getAs<FunctionProtoType>(); | |
| if (MD->isImplicitObjectMemberFunction()) { | |
| // The abstract case is perfectly fine. | |
| const CXXRecordDecl *ThisType = | |
| getCXXABI().getThisArgumentTypeForMethod(MD); | |
| return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD); | |
| } | |
| CanQualTypeList argTypes; | |
| ExtParameterInfoList paramInfos; | |
| appendParameterTypes(*this, argTypes, paramInfos, prototype); | |
| return arrangeLLVMFunctionInfo( | |
| prototype->getReturnType().getUnqualifiedType(), FnInfoOpts::None, | |
| argTypes, prototype->getExtInfo(), paramInfos, | |
| RequiredArgs::forPrototypePlus(prototype.getTypePtr(), 0), MD); | |
| } | |
| bool CodeGenTypes::inheritingCtorHasParams( | |
| const InheritedConstructor &Inherited, CXXCtorType Type) { | |
| // Parameters are unnecessary if we're constructing a base class subobject | |
| // and the inherited constructor lives in a virtual base. | |
| return Type == Ctor_Complete || | |
| !Inherited.getShadowDecl()->constructsVirtualBase() || | |
| !Target.getCXXABI().hasConstructorVariants(); | |
| } | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) { | |
| auto *MD = cast<CXXMethodDecl>(GD.getDecl()); | |
| CanQualTypeList argTypes; | |
| ExtParameterInfoList paramInfos; | |
| const CXXRecordDecl *ThisType = getCXXABI().getThisArgumentTypeForMethod(GD); | |
| argTypes.push_back(DeriveThisType(ThisType, MD)); | |
| bool PassParams = true; | |
| if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { | |
| // A base class inheriting constructor doesn't get forwarded arguments | |
| // needed to construct a virtual base (or base class thereof). | |
| if (auto Inherited = CD->getInheritedConstructor()) | |
| PassParams = inheritingCtorHasParams(Inherited, GD.getCtorType()); | |
| } | |
| CanQual<FunctionProtoType> FTP = CodeGenUtils::getFormalType(MD); | |
| // Add the formal parameters. | |
| if (PassParams) | |
| appendParameterTypes(*this, argTypes, paramInfos, FTP); | |
| CGCXXABI::AddedStructorArgCounts AddedArgs = | |
| getCXXABI().buildStructorSignature(GD, argTypes); | |
| if (!paramInfos.empty()) { | |
| // Note: prefix implies after the first param. | |
| if (AddedArgs.Prefix) | |
| paramInfos.insert(paramInfos.begin() + 1, AddedArgs.Prefix, | |
| FunctionProtoType::ExtParameterInfo{}); | |
| if (AddedArgs.Suffix) | |
| paramInfos.append(AddedArgs.Suffix, | |
| FunctionProtoType::ExtParameterInfo{}); | |
| } | |
| RequiredArgs required = | |
| (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size()) | |
| : RequiredArgs::All); | |
| FunctionType::ExtInfo extInfo = FTP->getExtInfo(); | |
| CanQualType resultType = getCXXABI().HasThisReturn(GD) ? argTypes.front() | |
| : getCXXABI().hasMostDerivedReturn(GD) | |
| ? CGM.getContext().VoidPtrTy | |
| : Context.VoidTy; | |
| return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::IsInstanceMethod, | |
| argTypes, extInfo, paramInfos, required, MD); | |
| } | |
| static CanQualTypeList getArgTypesForCall(ASTContext &ctx, | |
| const CallArgList &args) { | |
| CanQualTypeList argTypes; | |
| for (auto &arg : args) | |
| argTypes.push_back(ctx.getCanonicalParamType(arg.Ty)); | |
| return argTypes; | |
| } | |
| static CanQualTypeList getArgTypesForDeclaration(ASTContext &ctx, | |
| const FunctionArgList &args) { | |
| CanQualTypeList argTypes; | |
| for (auto &arg : args) | |
| argTypes.push_back(ctx.getCanonicalParamType(arg->getType())); | |
| return argTypes; | |
| } | |
| static ExtParameterInfoList | |
| getExtParameterInfosForCall(const FunctionProtoType *proto, unsigned prefixArgs, | |
| unsigned totalArgs) { | |
| ExtParameterInfoList result; | |
| if (proto->hasExtParameterInfos()) { | |
| addExtParameterInfosForCall(result, proto, prefixArgs, totalArgs); | |
| } | |
| return result; | |
| } | |
| /// Arrange a call to a C++ method, passing the given arguments. | |
| /// | |
| /// ExtraPrefixArgs is the number of ABI-specific args passed after the `this` | |
| /// parameter. | |
| /// ExtraSuffixArgs is the number of ABI-specific args passed at the end of | |
| /// args. | |
| /// PassProtoArgs indicates whether `args` has args for the parameters in the | |
| /// given CXXConstructorDecl. | |
| const CGFunctionInfo &CodeGenTypes::arrangeCXXConstructorCall( | |
| const CallArgList &args, const CXXConstructorDecl *D, CXXCtorType CtorKind, | |
| unsigned ExtraPrefixArgs, unsigned ExtraSuffixArgs, | |
| const FunctionDecl *ABIInfoFD, bool PassProtoArgs) { | |
| CanQualTypeList ArgTypes; | |
| for (const auto &Arg : args) | |
| ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); | |
| // +1 for implicit this, which should always be args[0]. | |
| unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs; | |
| CanQual<FunctionProtoType> FPT = CodeGenUtils::getFormalType(D); | |
| RequiredArgs Required = PassProtoArgs | |
| ? RequiredArgs::forPrototypePlus( | |
| FPT, TotalPrefixArgs + ExtraSuffixArgs) | |
| : RequiredArgs::All; | |
| GlobalDecl GD(D, CtorKind); | |
| CanQualType ResultType = getCXXABI().HasThisReturn(GD) ? ArgTypes.front() | |
| : getCXXABI().hasMostDerivedReturn(GD) | |
| ? CGM.getContext().VoidPtrTy | |
| : Context.VoidTy; | |
| FunctionType::ExtInfo Info = FPT->getExtInfo(); | |
| ExtParameterInfoList ParamInfos; | |
| // If the prototype args are elided, we should only have ABI-specific args, | |
| // which never have param info. | |
| if (PassProtoArgs && FPT->hasExtParameterInfos()) { | |
| // ABI-specific suffix arguments are treated the same as variadic arguments. | |
| addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs, | |
| ArgTypes.size()); | |
| } | |
| return arrangeLLVMFunctionInfo(ResultType, FnInfoOpts::IsInstanceMethod, | |
| ArgTypes, Info, ParamInfos, Required, | |
| ABIInfoFD); | |
| } | |
| /// Arrange the argument and result information for the declaration or | |
| /// definition of the given function. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeFunctionDeclaration(const GlobalDecl GD) { | |
| const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); | |
| if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) | |
| if (MD->isImplicitObjectMemberFunction()) | |
| return arrangeCXXMethodDeclaration(MD); | |
| CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified(); | |
| assert(isa<FunctionType>(FTy)); | |
| setCUDAKernelCallingConvention(FTy, CGM, FD); | |
| if (DeviceKernelAttr::isOpenCLSpelling(FD->getAttr<DeviceKernelAttr>()) && | |
| GD.getKernelReferenceKind() == KernelReferenceKind::Stub) { | |
| const FunctionType *FT = FTy->getAs<FunctionType>(); | |
| CGM.getTargetCodeGenInfo().setOCLKernelStubCallingConvention(FT); | |
| FTy = FT->getCanonicalTypeUnqualified(); | |
| } | |
| // When declaring a function without a prototype, always use a | |
| // non-variadic type. | |
| if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) { | |
| return arrangeLLVMFunctionInfo(noProto->getReturnType(), FnInfoOpts::None, | |
| {}, noProto->getExtInfo(), {}, | |
| RequiredArgs::All, FD); | |
| } | |
| CanQual<FunctionProtoType> FTP = FTy.castAs<FunctionProtoType>(); | |
| CanQualTypeList argTypes; | |
| ExtParameterInfoList paramInfos; | |
| appendParameterTypes(*this, argTypes, paramInfos, FTP); | |
| return arrangeLLVMFunctionInfo(FTP->getReturnType().getUnqualifiedType(), | |
| FnInfoOpts::None, argTypes, FTP->getExtInfo(), | |
| paramInfos, | |
| RequiredArgs::forPrototypePlus(FTP, 0), FD); | |
| } | |
| /// Arrange the argument and result information for the declaration or | |
| /// definition of an Objective-C method. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD) { | |
| // It happens that this is the same as a call with no optional | |
| // arguments, except also using the formal 'self' type. | |
| return arrangeObjCMessageSendSignature(MD, MD->getSelfDecl()->getType()); | |
| } | |
| /// Arrange the argument and result information for the function type | |
| /// through which to perform a send to the given Objective-C method, | |
| /// using the given receiver type. The receiver type is not always | |
| /// the 'self' type of the method or even an Objective-C pointer type. | |
| /// This is *not* the right method for actually performing such a | |
| /// message send, due to the possibility of optional arguments. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, | |
| QualType receiverType) { | |
| CanQualTypeList argTys; | |
| ExtParameterInfoList extParamInfos(MD->isDirectMethod() ? 1 : 2); | |
| argTys.push_back(Context.getCanonicalParamType(receiverType)); | |
| if (!MD->isDirectMethod()) | |
| argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType())); | |
| for (const auto *I : MD->parameters()) { | |
| argTys.push_back(Context.getCanonicalParamType(I->getType())); | |
| auto extParamInfo = FunctionProtoType::ExtParameterInfo().withIsNoEscape( | |
| I->hasAttr<NoEscapeAttr>()); | |
| extParamInfos.push_back(extParamInfo); | |
| } | |
| FunctionType::ExtInfo einfo; | |
| bool IsTargetDefaultMSABI = | |
| getContext().getTargetInfo().getTriple().isOSWindows() || | |
| getContext().getTargetInfo().getTriple().isUEFI(); | |
| einfo = einfo.withCallingConv( | |
| getCallingConventionForDecl(MD, IsTargetDefaultMSABI)); | |
| if (getContext().getLangOpts().ObjCAutoRefCount && | |
| MD->hasAttr<NSReturnsRetainedAttr>()) | |
| einfo = einfo.withProducesResult(true); | |
| RequiredArgs required = | |
| (MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All); | |
| return arrangeLLVMFunctionInfo(GetReturnType(MD->getReturnType()), | |
| FnInfoOpts::None, argTys, einfo, extParamInfos, | |
| required, /*ABIInfoFD=*/nullptr); | |
| } | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType, | |
| const CallArgList &args) { | |
| CanQualTypeList argTypes = getArgTypesForCall(Context, args); | |
| FunctionType::ExtInfo einfo; | |
| return arrangeLLVMFunctionInfo(GetReturnType(returnType), FnInfoOpts::None, | |
| argTypes, einfo, {}, RequiredArgs::All, | |
| nullptr); | |
| } | |
| const CGFunctionInfo &CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) { | |
| // FIXME: Do we need to handle ObjCMethodDecl? | |
| if (isa<CXXConstructorDecl>(GD.getDecl()) || | |
| isa<CXXDestructorDecl>(GD.getDecl())) | |
| return arrangeCXXStructorDeclaration(GD); | |
| return arrangeFunctionDeclaration(GD); | |
| } | |
| /// Arrange a thunk that takes 'this' as the first parameter followed by | |
| /// varargs. Return a void pointer, regardless of the actual return type. | |
| /// The body of the thunk will end in a musttail call to a function of the | |
| /// correct type, and the caller will bitcast the function to the correct | |
| /// prototype. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) { | |
| assert(MD->isVirtual() && "only methods have thunks"); | |
| CanQual<FunctionProtoType> FTP = CodeGenUtils::getFormalType(MD); | |
| CanQualType ArgTys[] = {DeriveThisType(MD->getParent(), MD)}; | |
| return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::None, ArgTys, | |
| FTP->getExtInfo(), {}, RequiredArgs(1), MD); | |
| } | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD, | |
| CXXCtorType CT) { | |
| assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure); | |
| CanQual<FunctionProtoType> FTP = CodeGenUtils::getFormalType(CD); | |
| SmallVector<CanQualType, 2> ArgTys; | |
| const CXXRecordDecl *RD = CD->getParent(); | |
| ArgTys.push_back(DeriveThisType(RD, CD)); | |
| if (CT == Ctor_CopyingClosure) | |
| ArgTys.push_back(*FTP->param_type_begin()); | |
| if (RD->getNumVBases() > 0) | |
| ArgTys.push_back(Context.IntTy); | |
| CallingConv CC = Context.getDefaultCallingConvention( | |
| /*IsVariadic=*/false, /*IsCXXMethod=*/true); | |
| return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::IsInstanceMethod, | |
| ArgTys, FunctionType::ExtInfo(CC), {}, | |
| RequiredArgs::All, /*ABIInfoFD=*/nullptr); | |
| } | |
| /// Arrange a call as unto a free function, except possibly with an | |
| /// additional number of formal parameters considered required. | |
| static const CGFunctionInfo & | |
| arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, CodeGenModule &CGM, | |
| const CallArgList &args, const FunctionType *fnType, | |
| unsigned numExtraRequiredArgs, bool chainCall, | |
| const FunctionDecl *ABIInfoFD) { | |
| assert(args.size() >= numExtraRequiredArgs); | |
| ExtParameterInfoList paramInfos; | |
| // In most cases, there are no optional arguments. | |
| RequiredArgs required = RequiredArgs::All; | |
| // If we have a variadic prototype, the required arguments are the | |
| // extra prefix plus the arguments in the prototype. | |
| if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) { | |
| if (proto->isVariadic()) | |
| required = RequiredArgs::forPrototypePlus(proto, numExtraRequiredArgs); | |
| if (proto->hasExtParameterInfos()) | |
| addExtParameterInfosForCall(paramInfos, proto, numExtraRequiredArgs, | |
| args.size()); | |
| // If we don't have a prototype at all, but we're supposed to | |
| // explicitly use the variadic convention for unprototyped calls, | |
| // treat all of the arguments as required but preserve the nominal | |
| // possibility of variadics. | |
| } else if (CGM.getTargetCodeGenInfo().isNoProtoCallVariadic( | |
| args, cast<FunctionNoProtoType>(fnType))) { | |
| required = RequiredArgs(args.size()); | |
| } | |
| CanQualTypeList argTypes; | |
| for (const auto &arg : args) | |
| argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty)); | |
| FnInfoOpts opts = chainCall ? FnInfoOpts::IsChainCall : FnInfoOpts::None; | |
| return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), | |
| opts, argTypes, fnType->getExtInfo(), | |
| paramInfos, required, ABIInfoFD); | |
| } | |
| /// Figure out the rules for calling a function with the given formal | |
| /// type using the given arguments. The arguments are necessary | |
| /// because the function might be unprototyped, in which case it's | |
| /// target-dependent in crazy ways. | |
| const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionCall( | |
| const CallArgList &args, const FunctionType *fnType, bool chainCall, | |
| const FunctionDecl *ABIInfoFD) { | |
| return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, | |
| chainCall ? 1 : 0, chainCall, ABIInfoFD); | |
| } | |
| /// A block function is essentially a free function with an | |
| /// extra implicit argument. | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args, | |
| const FunctionType *fnType) { | |
| // FIXME: Pass the enclosing function's ABI information so block calls use | |
| // the caller's target features. | |
| return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1, | |
| /*chainCall=*/false, nullptr); | |
| } | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto, | |
| const FunctionArgList ¶ms) { | |
| ExtParameterInfoList paramInfos = | |
| getExtParameterInfosForCall(proto, 1, params.size()); | |
| CanQualTypeList argTypes = getArgTypesForDeclaration(Context, params); | |
| // FIXME: Use the block's target features when arranging its invoke function. | |
| return arrangeLLVMFunctionInfo( | |
| GetReturnType(proto->getReturnType()), FnInfoOpts::None, argTypes, | |
| proto->getExtInfo(), paramInfos, RequiredArgs::forPrototypePlus(proto, 1), | |
| /*ABIInfoFD=*/nullptr); | |
| } | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType, | |
| const CallArgList &args) { | |
| CanQualTypeList argTypes; | |
| for (const auto &Arg : args) | |
| argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); | |
| return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None, | |
| argTypes, FunctionType::ExtInfo(), | |
| /*paramInfos=*/{}, RequiredArgs::All, nullptr); | |
| } | |
| const CGFunctionInfo & | |
| CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType, | |
| const FunctionArgList &args) { | |
| CanQualTypeList argTypes = getArgTypesForDeclaration(Context, args); | |
| return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None, | |
| argTypes, FunctionType::ExtInfo(), {}, | |
| RequiredArgs::All, /*ABIInfoFD=*/nullptr); | |
| } | |
| const CGFunctionInfo &CodeGenTypes::arrangeBuiltinFunctionDeclaration( | |
| CanQualType resultType, ArrayRef<CanQualType> argTypes) { | |
| return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::None, argTypes, | |
| FunctionType::ExtInfo(), {}, RequiredArgs::All, | |
| /*ABIInfoFD=*/nullptr); | |
| } | |
| const CGFunctionInfo &CodeGenTypes::arrangeDeviceKernelCallerDeclaration( | |
| QualType resultType, const FunctionArgList &args) { | |
| CanQualTypeList argTypes = getArgTypesForDeclaration(Context, args); | |
| return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None, | |
| argTypes, | |
| FunctionType::ExtInfo(CC_DeviceKernel), | |
| /*paramInfos=*/{}, RequiredArgs::All, | |
| /*ABIInfoFD=*/nullptr); | |
| } | |
| /// Arrange a call to a C++ method, passing the given arguments. | |
| /// | |
| /// numPrefixArgs is the number of ABI-specific prefix arguments we have. It | |
| /// does not count `this`. | |
| const CGFunctionInfo &CodeGenTypes::arrangeCXXMethodCall( | |
| const CallArgList &args, const FunctionProtoType *proto, | |
| RequiredArgs required, unsigned numPrefixArgs, | |
| const FunctionDecl *ABIInfoFD) { | |
| assert(numPrefixArgs + 1 <= args.size() && | |
| "Emitting a call with less args than the required prefix?"); | |
| // Add one to account for `this`. It's a bit awkward here, but we don't count | |
| // `this` in similar places elsewhere. | |
| ExtParameterInfoList paramInfos = | |
| getExtParameterInfosForCall(proto, numPrefixArgs + 1, args.size()); | |
| CanQualTypeList argTypes = getArgTypesForCall(Context, args); | |
| FunctionType::ExtInfo info = proto->getExtInfo(); | |
| return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()), | |
| FnInfoOpts::IsInstanceMethod, argTypes, info, | |
| paramInfos, required, ABIInfoFD); | |
| } | |
| const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { | |
| return arrangeLLVMFunctionInfo(getContext().VoidTy, FnInfoOpts::None, {}, | |
| FunctionType::ExtInfo(), {}, RequiredArgs::All, | |
| /*ABIInfoFD=*/nullptr); | |
| } | |
| const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, | |
| const CallArgList &args, | |
| const FunctionDecl *ABIInfoFD) { | |
| assert(signature.arg_size() <= args.size()); | |
| unsigned X86ABIAVXLevel = | |
| CGM.getABIInfo().getX86ABIAVXLevel(ABIInfoFD, signature.getExtInfo()); | |
| if (signature.arg_size() == args.size() && | |
| signature.getX86ABIAVXLevel() == X86ABIAVXLevel) | |
| return signature; | |
| ExtParameterInfoList paramInfos; | |
| auto sigParamInfos = signature.getExtParameterInfos(); | |
| if (!sigParamInfos.empty()) { | |
| paramInfos.append(sigParamInfos.begin(), sigParamInfos.end()); | |
| paramInfos.resize(args.size()); | |
| } | |
| CanQualTypeList argTypes = getArgTypesForCall(Context, args); | |
| assert(signature.getRequiredArgs().allowsOptionalArgs()); | |
| FnInfoOpts opts = FnInfoOpts::None; | |
| if (signature.isInstanceMethod()) | |
| opts |= FnInfoOpts::IsInstanceMethod; | |
| if (signature.isChainCall()) | |
| opts |= FnInfoOpts::IsChainCall; | |
| if (signature.isDelegateCall()) | |
| opts |= FnInfoOpts::IsDelegateCall; | |
| const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo( | |
| signature.isInstanceMethod(), signature.isChainCall(), | |
| signature.isDelegateCall(), X86ABIAVXLevel, signature.getExtInfo(), | |
| paramInfos, signature.getRequiredArgs(), signature.getReturnType(), | |
| argTypes); | |
| return *newFI; | |
| } | |
| namespace clang { | |
| namespace CodeGen { | |
| void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); | |
| } // namespace CodeGen | |
| } // namespace clang | |
| #ifndef NDEBUG | |
| static const char *abiKindToString(ABIArgInfo::Kind K) { | |
| switch (K) { | |
| case ABIArgInfo::Direct: | |
| return "Direct"; | |
| case ABIArgInfo::Extend: | |
| return "Extend"; | |
| case ABIArgInfo::Indirect: | |
| return "Indirect"; | |
| case ABIArgInfo::IndirectAliased: | |
| return "IndirectAliased"; | |
| case ABIArgInfo::Ignore: | |
| return "Ignore"; | |
| case ABIArgInfo::Expand: | |
| return "Expand"; | |
| case ABIArgInfo::CoerceAndExpand: | |
| return "CoerceAndExpand"; | |
| case ABIArgInfo::TargetSpecific: | |
| return "TargetSpecific"; | |
| case ABIArgInfo::InAlloca: | |
| return "InAlloca"; | |
| } | |
| llvm_unreachable("Unknown kind"); | |
| } | |
| #endif | |
| void CodeGenModule::computeABIInfoUsingLib(CGFunctionInfo &FI) { | |
| SmallVector<const llvm::abi::Type *> MappedArgTypes; | |
| MappedArgTypes.reserve(FI.arg_size()); | |
| for (const auto &Arg : FI.arguments()) | |
| MappedArgTypes.push_back(AbiMapper->convertType(Arg.type)); | |
| RequiredArgs Required = FI.getRequiredArgs(); | |
| llvm::abi::RequiredArgs AbiRequired = llvm::abi::RequiredArgs::All; | |
| if (Required.allowsOptionalArgs()) | |
| AbiRequired = llvm::abi::RequiredArgs(Required.getNumRequiredArgs()); | |
| auto AbiFI = llvm::abi::FunctionInfo::create( | |
| FI.getCallingConvention(), AbiMapper->convertType(FI.getReturnType()), | |
| MappedArgTypes, AbiRequired); | |
| getLLVMABITargetInfo(AbiMapper->getTypeBuilder()).computeInfo(*AbiFI); | |
| #ifndef NDEBUG | |
| // With assertions enabled, also compute info using Clang ABI logic, | |
| // so we can ensure the results are consistent. | |
| getABIInfo().computeInfo(FI); | |
| auto ConvertABIArgInfo = [&](ABIArgInfo &Target, | |
| const llvm::abi::ArgInfo &AbiInfo, QualType Type, | |
| int ArgNo) { | |
| auto Check = [&](bool Cond, llvm::function_ref<void()> MessageFn) { | |
| if (Cond) | |
| return; | |
| if (ArgNo == -1) | |
| llvm::dbgs() << "For return value of type "; | |
| else | |
| llvm::dbgs() << "For argument " << ArgNo << " of type "; | |
| llvm::dbgs() << Type << ": "; | |
| MessageFn(); | |
| llvm::dbgs() << "\n"; | |
| abort(); | |
| }; | |
| auto CheckSimple = [&](auto TargetVal, auto ResVal, StringRef What) { | |
| Check(TargetVal == ResVal, [&]() { | |
| llvm::dbgs() << What << " mismatch (expected: " << TargetVal | |
| << ", given: " << ResVal << ")"; | |
| }); | |
| }; | |
| ABIArgInfo Res = convertABIArgInfo(AbiInfo, Type); | |
| Check(Target.getKind() == Res.getKind(), [&]() { | |
| llvm::dbgs() << "Kind mismatch (expected: " | |
| << abiKindToString(Target.getKind()) | |
| << ", given: " << abiKindToString(Res.getKind()) << ")"; | |
| }); | |
| if (Res.canHaveCoerceToType()) { | |
| // Normalize nullptr types. | |
| llvm::Type *TargetType = Target.getCoerceToType(); | |
| llvm::Type *ResType = Res.getCoerceToType(); | |
| if (!TargetType) | |
| TargetType = getTypes().ConvertType(Type); | |
| if (!ResType) | |
| ResType = getTypes().ConvertType(Type); | |
| Check(TargetType == ResType, [&]() { | |
| llvm::dbgs() << "CoerceToType mismatch (expected: " << *TargetType | |
| << ", given: " << *ResType << ")"; | |
| }); | |
| } | |
| switch (Res.getKind()) { | |
| case ABIArgInfo::Extend: | |
| CheckSimple(Target.isSignExt(), Res.isSignExt(), "SignExt"); | |
| CheckSimple(Target.isZeroExt(), Res.isZeroExt(), "ZeroExt"); | |
| [[fallthrough]]; | |
| case ABIArgInfo::Direct: | |
| CheckSimple(Target.getDirectAlign(), Res.getDirectAlign(), "DirectAlign"); | |
| CheckSimple(Target.getDirectOffset(), Res.getDirectOffset(), | |
| "DirectOffset"); | |
| // Extend falls through to here, and only Direct carries the flag. | |
| if (Res.isDirect()) | |
| CheckSimple(Target.getCanBeFlattened(), Res.getCanBeFlattened(), | |
| "CanBeFlattened"); | |
| break; | |
| case ABIArgInfo::Indirect: | |
| CheckSimple(Target.getIndirectByVal(), Res.getIndirectByVal(), | |
| "IndirectByVal"); | |
| [[fallthrough]]; | |
| case ABIArgInfo::IndirectAliased: | |
| CheckSimple(Target.getIndirectAddrSpace(), Res.getIndirectAddrSpace(), | |
| "IndirectAddrSpace"); | |
| CheckSimple(Target.getIndirectRealign(), Res.getIndirectRealign(), | |
| "IndirectRealign"); | |
| Check(Target.getIndirectAlign() == Res.getIndirectAlign(), [&]() { | |
| llvm::dbgs() << "IndirectAlign mismatch (expected: " | |
| << Target.getIndirectAlign().getQuantity() | |
| << ", given: " << Res.getIndirectAlign().getQuantity() | |
| << ")"; | |
| }); | |
| break; | |
| case ABIArgInfo::CoerceAndExpand: | |
| Check(Target.getUnpaddedCoerceAndExpandType() == | |
| Res.getUnpaddedCoerceAndExpandType(), | |
| [&]() { | |
| llvm::dbgs() << "UnpaddedCoerceAndExpandType mismatch (expected: " | |
| << *Target.getUnpaddedCoerceAndExpandType() | |
| << ", given: " | |
| << *Res.getUnpaddedCoerceAndExpandType() << ")"; | |
| }); | |
| break; | |
| default: | |
| break; | |
| } | |
| Target = Res; | |
| }; | |
| #else | |
| auto ConvertABIArgInfo = | |
| [&](ABIArgInfo &Target, const llvm::abi::ArgInfo &AbiInfo, QualType Type, | |
| int ArgNo) { Target = convertABIArgInfo(AbiInfo, Type); }; | |
| #endif | |
| ConvertABIArgInfo(FI.getReturnInfo(), AbiFI->getReturnInfo(), | |
| FI.getReturnType(), -1); | |
| int ArgNo = 0; | |
| for (auto [CGArg, AbiArg] : | |
| llvm::zip_equal(FI.arguments(), AbiFI->arguments())) | |
| ConvertABIArgInfo(CGArg.info, AbiArg.Info, CGArg.type, ArgNo++); | |
| } | |
| ABIArgInfo CodeGenModule::convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo, | |
| QualType Type) { | |
| switch (AbiInfo.getKind()) { | |
| case llvm::abi::ArgInfo::Direct: { | |
| llvm::Type *CoercedType = nullptr; | |
| if (AbiInfo.getCoerceToType()) | |
| CoercedType = AbiReverseMapper->convertType(AbiInfo.getCoerceToType()); | |
| if (!CoercedType) | |
| CoercedType = getTypes().ConvertType(Type); | |
| unsigned DirectAlign = 0; | |
| if (llvm::MaybeAlign Align = AbiInfo.getDirectAlign()) | |
| DirectAlign = Align->value(); | |
| // TODO: Move Padding into the ABIArgInfo struct when we add support for | |
| // targets that need a different setting than we have here. | |
| return ABIArgInfo::getDirect(CoercedType, AbiInfo.getDirectOffset(), | |
| /*Padding=*/nullptr, | |
| AbiInfo.getCanBeFlattened(), DirectAlign); | |
| } | |
| case llvm::abi::ArgInfo::Extend: { | |
| llvm::Type *CoercedType = nullptr; | |
| if (AbiInfo.getCoerceToType()) | |
| CoercedType = AbiReverseMapper->convertType(AbiInfo.getCoerceToType()); | |
| if (!CoercedType) | |
| CoercedType = getTypes().ConvertType(Type); | |
| // A transparent union is passed as its first field, so the extend keys off | |
| // that field's integral type, matching the classifier's | |
| // useFirstFieldIfTransparentUnion. Passing the union type to | |
| // ABIArgInfo::getSignExtend would trip its integral-type assert. | |
| QualType ExtendType = useFirstFieldIfTransparentUnion(Type); | |
| if (AbiInfo.isSignExt()) | |
| return ABIArgInfo::getSignExtend(ExtendType, CoercedType); | |
| if (AbiInfo.isZeroExt()) | |
| return ABIArgInfo::getZeroExtend(ExtendType, CoercedType); | |
| return ABIArgInfo::getExtend(ExtendType, CoercedType); | |
| } | |
| case llvm::abi::ArgInfo::Indirect: { | |
| CharUnits Alignment = | |
| CharUnits::fromQuantity(AbiInfo.getIndirectAlign().value()); | |
| return ABIArgInfo::getIndirect(Alignment, AbiInfo.getIndirectAddrSpace(), | |
| AbiInfo.getIndirectByVal(), | |
| AbiInfo.getIndirectRealign()); | |
| } | |
| case llvm::abi::ArgInfo::IndirectAliased: { | |
| // Aliased indirect carries an address space but never byval. | |
| CharUnits Alignment = | |
| CharUnits::fromQuantity(AbiInfo.getIndirectAlign().value()); | |
| return ABIArgInfo::getIndirectAliased(Alignment, | |
| AbiInfo.getIndirectAddrSpace(), | |
| AbiInfo.getIndirectRealign()); | |
| } | |
| case llvm::abi::ArgInfo::Ignore: | |
| return ABIArgInfo::getIgnore(); | |
| case llvm::abi::ArgInfo::CoerceAndExpand: { | |
| llvm::StructType *CoercedType = llvm::cast<llvm::StructType>( | |
| AbiReverseMapper->convertType(AbiInfo.getCoerceToType())); | |
| llvm::Type *UnpaddedType = | |
| AbiReverseMapper->convertType(AbiInfo.getUnpaddedCoerceAndExpandType()); | |
| return ABIArgInfo::getCoerceAndExpand(CoercedType, UnpaddedType); | |
| } | |
| } | |
| llvm_unreachable("Unexpected llvm::abi::ArgInfo kind"); | |
| } | |
| /// Arrange the argument and result information for an abstract value | |
| /// of a given function type. This is the method which all of the | |
| /// above functions ultimately defer to. | |
| const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo( | |
| CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes, | |
| FunctionType::ExtInfo info, | |
| ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, | |
| RequiredArgs required, const FunctionDecl *ABIInfoFD) { | |
| assert(llvm::all_of(argTypes, | |
| [](CanQualType T) { return T.isCanonicalAsParam(); })); | |
| // Lookup or create unique function info. | |
| bool isInstanceMethod = | |
| (opts & FnInfoOpts::IsInstanceMethod) == FnInfoOpts::IsInstanceMethod; | |
| bool isChainCall = | |
| (opts & FnInfoOpts::IsChainCall) == FnInfoOpts::IsChainCall; | |
| bool isDelegateCall = | |
| (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall; | |
| unsigned X86ABIAVXLevel = CGM.getABIInfo().getX86ABIAVXLevel(ABIInfoFD, info); | |
| const CGFunctionInfo *newFI = findOrInsertCGFunctionInfo( | |
| isInstanceMethod, isChainCall, isDelegateCall, X86ABIAVXLevel, info, | |
| paramInfos, required, resultType, argTypes); | |
| return *newFI; | |
| } | |
| CGFunctionInfo *CodeGenTypes::findOrInsertCGFunctionInfo( | |
| bool isInstanceMethod, bool isChainCall, bool isDelegateCall, | |
| unsigned X86ABIAVXLevel, const FunctionType::ExtInfo &info, | |
| ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, | |
| RequiredArgs required, CanQualType resultType, | |
| ArrayRef<CanQualType> argTypes) { | |
| llvm::FoldingSetNodeID ID; | |
| CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall, | |
| X86ABIAVXLevel, info, paramInfos, required, | |
| resultType, argTypes); | |
| llvm::FoldingSetInsertToken InsertToken; | |
| CGFunctionInfo *FI = FunctionInfos.lookup(ID, InsertToken); | |
| if (FI) | |
| return FI; | |
| unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); | |
| // Construct the function info. We co-allocate the ArgInfos. | |
| FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall, | |
| X86ABIAVXLevel, info, paramInfos, resultType, | |
| argTypes, required); | |
| FunctionInfos.insert(FI, InsertToken); | |
| bool inserted = FunctionsBeingProcessed.insert(FI).second; | |
| (void)inserted; | |
| assert(inserted && "Recursively being processed?"); | |
| // Compute ABI information. | |
| if (info.getCC() == CC_DeviceKernel && | |
| (CC == llvm::CallingConv::SPIR_KERNEL || CC == llvm::CallingConv::C)) { | |
| // Force target independent argument handling for the host visible | |
| // kernel functions. | |
| // | |
| // For CPU targets, this currently only works for OpenCL. | |
| assert(CC != llvm::CallingConv::C || getContext().getLangOpts().OpenCL); | |
| // SPIR-V lowers OpenCL types to target extension types, which the ABI | |
| // library cannot tell apart from the kernel pointers it coerces yet, so | |
| // such kernels keep Clang's own lowering. | |
| auto IsSPIRVOpenCLType = [&](const CGFunctionInfoArgInfo &Arg) { | |
| return CGM.getTriple().isSPIRV() && | |
| Arg.type.getTypePtr()->isOpenCLSpecificType(); | |
| }; | |
| if (CC == llvm::CallingConv::SPIR_KERNEL && | |
| CGM.shouldUseLLVMABILowering(CC) && | |
| llvm::none_of(FI->arguments(), IsSPIRVOpenCLType)) | |
| CGM.computeABIInfoUsingLib(*FI); | |
| else | |
| computeSPIRKernelABIInfo(CGM, *FI); | |
| } else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) { | |
| swiftcall::computeABIInfo(CGM, *FI); | |
| } else if (CGM.shouldUseLLVMABILowering(CC)) { | |
| CGM.computeABIInfoUsingLib(*FI); | |
| } else { | |
| CGM.getABIInfo().computeInfo(*FI); | |
| } | |
| // Loop over all of the computed argument and return value info. If any of | |
| // them are direct or extend without a specified coerce type, specify the | |
| // default now. | |
| ABIArgInfo &retInfo = FI->getReturnInfo(); | |
| if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr) | |
| retInfo.setCoerceToType(ConvertType(FI->getReturnType())); | |
| for (auto &I : FI->arguments()) | |
| if (I.info.canHaveCoerceToType() && I.info.getCoerceToType() == nullptr) | |
| I.info.setCoerceToType(ConvertType(I.type)); | |
| bool erased = FunctionsBeingProcessed.erase(FI); | |
| (void)erased; | |
| assert(erased && "Not in set?"); | |
| return FI; | |
| } | |
| CGFunctionInfo *CGFunctionInfo::create( | |
| unsigned llvmCC, bool instanceMethod, bool chainCall, bool delegateCall, | |
| unsigned X86ABIAVXLevel, const FunctionType::ExtInfo &info, | |
| ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, | |
| ArrayRef<CanQualType> argTypes, RequiredArgs required) { | |
| assert(paramInfos.empty() || paramInfos.size() == argTypes.size()); | |
| assert(!required.allowsOptionalArgs() || | |
| required.getNumRequiredArgs() <= argTypes.size()); | |
| void *buffer = operator new(totalSizeToAlloc<ArgInfo, ExtParameterInfo>( | |
| argTypes.size() + 1, paramInfos.size())); | |
| CGFunctionInfo *FI = new (buffer) CGFunctionInfo(); | |
| FI->CallingConvention = llvmCC; | |
| FI->EffectiveCallingConvention = llvmCC; | |
| FI->ASTCallingConvention = info.getCC(); | |
| FI->InstanceMethod = instanceMethod; | |
| FI->ChainCall = chainCall; | |
| FI->DelegateCall = delegateCall; | |
| FI->CmseNSCall = info.getCmseNSCall(); | |
| FI->NoReturn = info.getNoReturn(); | |
| FI->ReturnsRetained = info.getProducesResult(); | |
| FI->NoCallerSavedRegs = info.getNoCallerSavedRegs(); | |
| FI->NoCfCheck = info.getNoCfCheck(); | |
| FI->Required = required; | |
| FI->HasRegParm = info.getHasRegParm(); | |
| FI->RegParm = info.getRegParm(); | |
| FI->X86ABIAVXLevel = X86ABIAVXLevel; | |
| FI->ArgStruct = nullptr; | |
| FI->ArgStructAlign = 0; | |
| FI->NumArgs = argTypes.size(); | |
| FI->HasExtParameterInfos = !paramInfos.empty(); | |
| FI->getArgsBuffer()[0].type = resultType; | |
| FI->MaxVectorWidth = 0; | |
| for (unsigned i = 0, e = argTypes.size(); i != e; ++i) | |
| FI->getArgsBuffer()[i + 1].type = argTypes[i]; | |
| for (unsigned i = 0, e = paramInfos.size(); i != e; ++i) | |
| FI->getExtParameterInfosBuffer()[i] = paramInfos[i]; | |
| return FI; | |
| } | |
| /***/ | |
| namespace { | |
| // ABIArgInfo::Expand implementation. | |
| // Specifies the way QualType passed as ABIArgInfo::Expand is expanded. | |
| struct TypeExpansion { | |
| enum TypeExpansionKind { | |
| // Elements of constant arrays are expanded recursively. | |
| TEK_ConstantArray, | |
| // Record fields are expanded recursively (but if record is a union, only | |
| // the field with the largest size is expanded). | |
| TEK_Record, | |
| // For complex types, real and imaginary parts are expanded recursively. | |
| TEK_Complex, | |
| // All other types are not expandable. | |
| TEK_None | |
| }; | |
| const TypeExpansionKind Kind; | |
| TypeExpansion(TypeExpansionKind K) : Kind(K) {} | |
| virtual ~TypeExpansion() {} | |
| }; | |
| struct ConstantArrayExpansion : TypeExpansion { | |
| QualType EltTy; | |
| uint64_t NumElts; | |
| ConstantArrayExpansion(QualType EltTy, uint64_t NumElts) | |
| : TypeExpansion(TEK_ConstantArray), EltTy(EltTy), NumElts(NumElts) {} | |
| static bool classof(const TypeExpansion *TE) { | |
| return TE->Kind == TEK_ConstantArray; | |
| } | |
| }; | |
| struct RecordExpansion : TypeExpansion { | |
| SmallVector<const CXXBaseSpecifier *, 1> Bases; | |
| SmallVector<const FieldDecl *, 1> Fields; | |
| RecordExpansion(SmallVector<const CXXBaseSpecifier *, 1> &&Bases, | |
| SmallVector<const FieldDecl *, 1> &&Fields) | |
| : TypeExpansion(TEK_Record), Bases(std::move(Bases)), | |
| Fields(std::move(Fields)) {} | |
| static bool classof(const TypeExpansion *TE) { | |
| return TE->Kind == TEK_Record; | |
| } | |
| }; | |
| struct ComplexExpansion : TypeExpansion { | |
| QualType EltTy; | |
| ComplexExpansion(QualType EltTy) : TypeExpansion(TEK_Complex), EltTy(EltTy) {} | |
| static bool classof(const TypeExpansion *TE) { | |
| return TE->Kind == TEK_Complex; | |
| } | |
| }; | |
| struct NoExpansion : TypeExpansion { | |
| NoExpansion() : TypeExpansion(TEK_None) {} | |
| static bool classof(const TypeExpansion *TE) { return TE->Kind == TEK_None; } | |
| }; | |
| } // namespace | |
| static std::unique_ptr<TypeExpansion> | |
| getTypeExpansion(QualType Ty, const ASTContext &Context) { | |
| if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { | |
| return std::make_unique<ConstantArrayExpansion>(AT->getElementType(), | |
| AT->getZExtSize()); | |
| } | |
| if (const auto *RD = Ty->getAsRecordDecl()) { | |
| SmallVector<const CXXBaseSpecifier *, 1> Bases; | |
| SmallVector<const FieldDecl *, 1> Fields; | |
| assert(!RD->hasFlexibleArrayMember() && | |
| "Cannot expand structure with flexible array."); | |
| if (RD->isUnion()) { | |
| // Unions can be here only in degenerative cases - all the fields are same | |
| // after flattening. Thus we have to use the "largest" field. | |
| const FieldDecl *LargestFD = nullptr; | |
| CharUnits UnionSize = CharUnits::Zero(); | |
| for (const auto *FD : RD->fields()) { | |
| if (FD->isZeroLengthBitField()) | |
| continue; | |
| assert(!FD->isBitField() && | |
| "Cannot expand structure with bit-field members."); | |
| CharUnits FieldSize = Context.getTypeSizeInChars(FD->getType()); | |
| if (UnionSize < FieldSize) { | |
| UnionSize = FieldSize; | |
| LargestFD = FD; | |
| } | |
| } | |
| if (LargestFD) | |
| Fields.push_back(LargestFD); | |
| } else { | |
| if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { | |
| assert(!CXXRD->isDynamicClass() && | |
| "cannot expand vtable pointers in dynamic classes"); | |
| llvm::append_range(Bases, llvm::make_pointer_range(CXXRD->bases())); | |
| } | |
| for (const auto *FD : RD->fields()) { | |
| if (FD->isZeroLengthBitField()) | |
| continue; | |
| assert(!FD->isBitField() && | |
| "Cannot expand structure with bit-field members."); | |
| Fields.push_back(FD); | |
| } | |
| } | |
| return std::make_unique<RecordExpansion>(std::move(Bases), | |
| std::move(Fields)); | |
| } | |
| if (const ComplexType *CT = Ty->getAs<ComplexType>()) { | |
| return std::make_unique<ComplexExpansion>(CT->getElementType()); | |
| } | |
| return std::make_unique<NoExpansion>(); | |
| } | |
| static int getExpansionSize(QualType Ty, const ASTContext &Context) { | |
| auto Exp = getTypeExpansion(Ty, Context); | |
| if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { | |
| return CAExp->NumElts * getExpansionSize(CAExp->EltTy, Context); | |
| } | |
| if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { | |
| int Res = 0; | |
| for (auto BS : RExp->Bases) | |
| Res += getExpansionSize(BS->getType(), Context); | |
| for (auto FD : RExp->Fields) | |
| Res += getExpansionSize(FD->getType(), Context); | |
| return Res; | |
| } | |
| if (isa<ComplexExpansion>(Exp.get())) | |
| return 2; | |
| assert(isa<NoExpansion>(Exp.get())); | |
| return 1; | |
| } | |
| void CodeGenTypes::getExpandedTypes( | |
| QualType Ty, SmallVectorImpl<llvm::Type *>::iterator &TI) { | |
| auto Exp = getTypeExpansion(Ty, Context); | |
| if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { | |
| for (int i = 0, n = CAExp->NumElts; i < n; i++) { | |
| getExpandedTypes(CAExp->EltTy, TI); | |
| } | |
| } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { | |
| for (auto BS : RExp->Bases) | |
| getExpandedTypes(BS->getType(), TI); | |
| for (auto FD : RExp->Fields) | |
| getExpandedTypes(FD->getType(), TI); | |
| } else if (auto CExp = dyn_cast<ComplexExpansion>(Exp.get())) { | |
| llvm::Type *EltTy = ConvertType(CExp->EltTy); | |
| *TI++ = EltTy; | |
| *TI++ = EltTy; | |
| } else { | |
| assert(isa<NoExpansion>(Exp.get())); | |
| *TI++ = ConvertType(Ty); | |
| } | |
| } | |
| static void forConstantArrayExpansion(CodeGenFunction &CGF, | |
| ConstantArrayExpansion *CAE, | |
| Address BaseAddr, | |
| llvm::function_ref<void(Address)> Fn) { | |
| for (int i = 0, n = CAE->NumElts; i < n; i++) { | |
| Address EltAddr = CGF.Builder.CreateConstGEP2_32(BaseAddr, 0, i); | |
| Fn(EltAddr); | |
| } | |
| } | |
| void CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, | |
| llvm::Function::arg_iterator &AI) { | |
| assert(LV.isSimple() && | |
| "Unexpected non-simple lvalue during struct expansion."); | |
| auto Exp = getTypeExpansion(Ty, getContext()); | |
| if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { | |
| forConstantArrayExpansion( | |
| *this, CAExp, LV.getAddress(), [&](Address EltAddr) { | |
| LValue LV = MakeAddrLValue(EltAddr, CAExp->EltTy); | |
| ExpandTypeFromArgs(CAExp->EltTy, LV, AI); | |
| }); | |
| } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { | |
| Address This = LV.getAddress(); | |
| for (const CXXBaseSpecifier *BS : RExp->Bases) { | |
| // Perform a single step derived-to-base conversion. | |
| Address Base = | |
| GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1, | |
| /*NullCheckValue=*/false, SourceLocation()); | |
| LValue SubLV = MakeAddrLValue(Base, BS->getType()); | |
| // Recurse onto bases. | |
| ExpandTypeFromArgs(BS->getType(), SubLV, AI); | |
| } | |
| for (auto FD : RExp->Fields) { | |
| // FIXME: What are the right qualifiers here? | |
| LValue SubLV = EmitLValueForFieldInitialization(LV, FD); | |
| ExpandTypeFromArgs(FD->getType(), SubLV, AI); | |
| } | |
| } else if (isa<ComplexExpansion>(Exp.get())) { | |
| auto realValue = &*AI++; | |
| auto imagValue = &*AI++; | |
| EmitStoreOfComplex(ComplexPairTy(realValue, imagValue), LV, /*init*/ true); | |
| } else { | |
| // Call EmitStoreOfScalar except when the lvalue is a bitfield to emit a | |
| // primitive store. | |
| assert(isa<NoExpansion>(Exp.get())); | |
| llvm::Value *Arg = &*AI++; | |
| if (LV.isBitField()) { | |
| EmitStoreThroughLValue(RValue::get(Arg), LV); | |
| } else { | |
| // TODO: currently there are some places are inconsistent in what LLVM | |
| // pointer type they use (see D118744). Once clang uses opaque pointers | |
| // all LLVM pointer types will be the same and we can remove this check. | |
| if (Arg->getType()->isPointerTy()) { | |
| Address Addr = LV.getAddress(); | |
| Arg = Builder.CreateBitCast(Arg, Addr.getElementType()); | |
| } | |
| EmitStoreOfScalar(Arg, LV); | |
| } | |
| } | |
| } | |
| void CodeGenFunction::ExpandTypeToArgs( | |
| QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy, | |
| SmallVectorImpl<llvm::Value *> &IRCallArgs, unsigned &IRCallArgPos) { | |
| auto Exp = getTypeExpansion(Ty, getContext()); | |
| if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) { | |
| Address Addr = Arg.hasLValue() ? Arg.getKnownLValue().getAddress() | |
| : Arg.getKnownRValue().getAggregateAddress(); | |
| forConstantArrayExpansion(*this, CAExp, Addr, [&](Address EltAddr) { | |
| CallArg EltArg = | |
| CallArg(convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation()), | |
| CAExp->EltTy); | |
| ExpandTypeToArgs(CAExp->EltTy, EltArg, IRFuncTy, IRCallArgs, | |
| IRCallArgPos); | |
| }); | |
| } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) { | |
| Address This = Arg.hasLValue() ? Arg.getKnownLValue().getAddress() | |
| : Arg.getKnownRValue().getAggregateAddress(); | |
| for (const CXXBaseSpecifier *BS : RExp->Bases) { | |
| // Perform a single step derived-to-base conversion. | |
| Address Base = | |
| GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1, | |
| /*NullCheckValue=*/false, SourceLocation()); | |
| CallArg BaseArg = CallArg(RValue::getAggregate(Base), BS->getType()); | |
| // Recurse onto bases. | |
| ExpandTypeToArgs(BS->getType(), BaseArg, IRFuncTy, IRCallArgs, | |
| IRCallArgPos); | |
| } | |
| LValue LV = MakeAddrLValue(This, Ty); | |
| for (auto FD : RExp->Fields) { | |
| CallArg FldArg = | |
| CallArg(EmitRValueForField(LV, FD, SourceLocation()), FD->getType()); | |
| ExpandTypeToArgs(FD->getType(), FldArg, IRFuncTy, IRCallArgs, | |
| IRCallArgPos); | |
| } | |
| } else if (isa<ComplexExpansion>(Exp.get())) { | |
| ComplexPairTy CV = Arg.getKnownRValue().getComplexVal(); | |
| IRCallArgs[IRCallArgPos++] = CV.first; | |
| IRCallArgs[IRCallArgPos++] = CV.second; | |
| } else { | |
| assert(isa<NoExpansion>(Exp.get())); | |
| auto RV = Arg.getKnownRValue(); | |
| assert(RV.isScalar() && | |
| "Unexpected non-scalar rvalue during struct expansion."); | |
| // Insert a bitcast as needed. | |
| llvm::Value *V = RV.getScalarVal(); | |
| if (IRCallArgPos < IRFuncTy->getNumParams() && | |
| V->getType() != IRFuncTy->getParamType(IRCallArgPos)) | |
| V = Builder.CreateBitCast(V, IRFuncTy->getParamType(IRCallArgPos)); | |
| IRCallArgs[IRCallArgPos++] = V; | |
| } | |
| } | |
| /// Create a temporary allocation for the purposes of coercion. | |
| static RawAddress CreateTempAllocaForCoercion(CodeGenFunction &CGF, | |
| llvm::Type *Ty, | |
| CharUnits MinAlign, | |
| const Twine &Name = "tmp") { | |
| // Don't use an alignment that's worse than what LLVM would prefer. | |
| auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlign(Ty); | |
| CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign)); | |
| return CGF.CreateTempAlloca(Ty, Align, Name + ".coerce"); | |
| } | |
| /// EnterStructPointerForCoercedAccess - Given a struct pointer that we are | |
| /// accessing some number of bytes out of it, try to gep into the struct to get | |
| /// at its inner goodness. Dive as deep as possible without entering an element | |
| /// with an in-memory size smaller than DstSize. | |
| static Address EnterStructPointerForCoercedAccess(Address SrcPtr, | |
| llvm::StructType *SrcSTy, | |
| uint64_t DstSize, | |
| CodeGenFunction &CGF) { | |
| // We can't dive into a zero-element struct. | |
| if (SrcSTy->getNumElements() == 0) | |
| return SrcPtr; | |
| llvm::Type *FirstElt = SrcSTy->getElementType(0); | |
| // If the first elt is at least as large as what we're looking for, or if the | |
| // first element is the same size as the whole struct, we can enter it. The | |
| // comparison must be made on the store size and not the alloca size. Using | |
| // the alloca size may overstate the size of the load. | |
| uint64_t FirstEltSize = CGF.CGM.getDataLayout().getTypeStoreSize(FirstElt); | |
| if (FirstEltSize < DstSize && | |
| FirstEltSize < CGF.CGM.getDataLayout().getTypeStoreSize(SrcSTy)) | |
| return SrcPtr; | |
| // GEP into the first element. | |
| SrcPtr = CGF.Builder.CreateStructGEP(SrcPtr, 0, "coerce.dive"); | |
| // If the first element is a struct, recurse. | |
| llvm::Type *SrcTy = SrcPtr.getElementType(); | |
| if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) | |
| return EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF); | |
| return SrcPtr; | |
| } | |
| /// CoerceIntOrPtrToIntOrPtr - Convert a value Val to the specific Ty where both | |
| /// are either integers or pointers. This does a truncation of the value if it | |
| /// is too large or a zero extension if it is too small. | |
| /// | |
| /// This behaves as if the value were coerced through memory, so on big-endian | |
| /// targets the high bits are preserved in a truncation, while little-endian | |
| /// targets preserve the low bits. | |
| static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val, llvm::Type *Ty, | |
| CodeGenFunction &CGF) { | |
| if (Val->getType() == Ty) | |
| return Val; | |
| if (isa<llvm::PointerType>(Val->getType())) { | |
| // If this is Pointer->Pointer avoid conversion to and from int. | |
| if (isa<llvm::PointerType>(Ty)) | |
| return CGF.Builder.CreateBitCast(Val, Ty, "coerce.val"); | |
| // Convert the pointer to an integer so we can play with its width. | |
| Val = CGF.Builder.CreatePtrToInt(Val, CGF.IntPtrTy, "coerce.val.pi"); | |
| } | |
| llvm::Type *DestIntTy = Ty; | |
| if (isa<llvm::PointerType>(DestIntTy)) | |
| DestIntTy = CGF.IntPtrTy; | |
| if (Val->getType() != DestIntTy) { | |
| const llvm::DataLayout &DL = CGF.CGM.getDataLayout(); | |
| if (DL.isBigEndian()) { | |
| // Preserve the high bits on big-endian targets. | |
| // That is what memory coercion does. | |
| uint64_t SrcSize = DL.getTypeSizeInBits(Val->getType()); | |
| uint64_t DstSize = DL.getTypeSizeInBits(DestIntTy); | |
| if (SrcSize > DstSize) { | |
| Val = CGF.Builder.CreateLShr(Val, SrcSize - DstSize, "coerce.highbits"); | |
| Val = CGF.Builder.CreateTrunc(Val, DestIntTy, "coerce.val.ii"); | |
| } else { | |
| Val = CGF.Builder.CreateZExt(Val, DestIntTy, "coerce.val.ii"); | |
| Val = CGF.Builder.CreateShl(Val, DstSize - SrcSize, "coerce.highbits"); | |
| } | |
| } else { | |
| // Little-endian targets preserve the low bits. No shifts required. | |
| Val = CGF.Builder.CreateIntCast(Val, DestIntTy, false, "coerce.val.ii"); | |
| } | |
| } | |
| if (isa<llvm::PointerType>(Ty)) | |
| Val = CGF.Builder.CreateIntToPtr(Val, Ty, "coerce.val.ip"); | |
| return Val; | |
| } | |
| static llvm::Value *CreatePFPCoercedLoad(Address Src, QualType SrcFETy, | |
| llvm::Type *Ty, CodeGenFunction &CGF) { | |
| std::vector<PFPField> PFPFields = CGF.getContext().findPFPFields(SrcFETy); | |
| if (PFPFields.empty()) | |
| return nullptr; | |
| auto LoadCoercedField = [&](CharUnits Offset, | |
| llvm::Type *FieldType) -> llvm::Value * { | |
| // Check whether the field at Offset is a PFP field. This function is called | |
| // in ascending order of offset, and PFPFields is sorted by offset. This | |
| // means that we only need to check the first element (and remove it from | |
| // PFPFields if matching). | |
| if (!PFPFields.empty() && PFPFields[0].Offset == Offset) { | |
| auto FieldAddr = CGF.EmitAddressOfPFPField(Src, PFPFields[0]); | |
| llvm::Value *FieldVal = CGF.Builder.CreateLoad(FieldAddr); | |
| if (isa<llvm::IntegerType>(FieldType)) | |
| FieldVal = CGF.Builder.CreatePtrToInt(FieldVal, FieldType); | |
| PFPFields.erase(PFPFields.begin()); | |
| return FieldVal; | |
| } | |
| auto FieldAddr = | |
| CGF.Builder | |
| .CreateConstInBoundsByteGEP(Src.withElementType(CGF.Int8Ty), Offset) | |
| .withElementType(FieldType); | |
| return CGF.Builder.CreateLoad(FieldAddr); | |
| }; | |
| // The types handled by this function are the only ones that may be generated | |
| // by AArch64ABIInfo::classify{Argument,Return}Type for struct types with | |
| // pointers. PFP is only supported on AArch64. | |
| if (isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) { | |
| auto Addr = CGF.EmitAddressOfPFPField(Src, PFPFields[0]); | |
| llvm::Value *Val = CGF.Builder.CreateLoad(Addr); | |
| if (isa<llvm::IntegerType>(Ty)) | |
| Val = CGF.Builder.CreatePtrToInt(Val, Ty); | |
| return Val; | |
| } | |
| auto *AT = cast<llvm::ArrayType>(Ty); | |
| auto *ET = AT->getElementType(); | |
| CharUnits WordSize = CGF.getContext().toCharUnitsFromBits( | |
| CGF.CGM.getDataLayout().getTypeSizeInBits(ET)); | |
| CharUnits Offset = CharUnits::Zero(); | |
| llvm::Value *Val = llvm::PoisonValue::get(AT); | |
| for (unsigned Idx = 0; Idx != AT->getNumElements(); ++Idx, Offset += WordSize) | |
| Val = CGF.Builder.CreateInsertValue(Val, LoadCoercedField(Offset, ET), Idx); | |
| return Val; | |
| } | |
| /// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as | |
| /// a pointer to an object of type \arg Ty, known to be aligned to | |
| /// \arg SrcAlign bytes. | |
| /// | |
| /// This safely handles the case when the src type is smaller than the | |
| /// destination type; in this situation the values of bits which not | |
| /// present in the src are undefined. | |
| static llvm::Value *CreateCoercedLoad(Address Src, QualType SrcFETy, | |
| llvm::Type *Ty, CodeGenFunction &CGF) { | |
| llvm::Type *SrcTy = Src.getElementType(); | |
| // If SrcTy and Ty are the same, just do a load. | |
| if (SrcTy == Ty) | |
| return CGF.Builder.CreateLoad(Src); | |
| if (llvm::Value *V = CreatePFPCoercedLoad(Src, SrcFETy, Ty, CGF)) | |
| return V; | |
| llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty); | |
| if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) { | |
| Src = EnterStructPointerForCoercedAccess(Src, SrcSTy, | |
| DstSize.getFixedValue(), CGF); | |
| SrcTy = Src.getElementType(); | |
| } | |
| llvm::TypeSize SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy); | |
| // If the source and destination are integer or pointer types, just do an | |
| // extension or truncation to the desired type. | |
| if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) && | |
| (isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) { | |
| llvm::Value *Load = CGF.Builder.CreateLoad(Src); | |
| return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF); | |
| } | |
| // If load is legal, just bitcast the src pointer. | |
| if (!SrcSize.isScalable() && !DstSize.isScalable() && | |
| SrcSize.getFixedValue() >= DstSize.getFixedValue()) { | |
| // Generally SrcSize is never greater than DstSize, since this means we are | |
| // losing bits. However, this can happen in cases where the structure has | |
| // additional padding, for example due to a user specified alignment. | |
| // | |
| // FIXME: Assert that we aren't truncating non-padding bits when have access | |
| // to that information. | |
| Src = Src.withElementType(Ty); | |
| return CGF.Builder.CreateLoad(Src); | |
| } | |
| // If coercing a fixed vector to a scalable vector for ABI compatibility, and | |
| // the types match, use the llvm.vector.insert intrinsic to perform the | |
| // conversion. | |
| if (auto *ScalableDstTy = dyn_cast<llvm::ScalableVectorType>(Ty)) { | |
| if (auto *FixedSrcTy = dyn_cast<llvm::FixedVectorType>(SrcTy)) { | |
| // If we are casting a fixed i8 vector to a scalable i1 predicate | |
| // vector, use a vector insert and bitcast the result. | |
| if (ScalableDstTy->getElementType()->isIntegerTy(1) && | |
| FixedSrcTy->getElementType()->isIntegerTy(8)) { | |
| ScalableDstTy = llvm::ScalableVectorType::get( | |
| FixedSrcTy->getElementType(), | |
| llvm::divideCeil( | |
| ScalableDstTy->getElementCount().getKnownMinValue(), 8)); | |
| } | |
| if (ScalableDstTy->getElementType() == FixedSrcTy->getElementType()) { | |
| auto *Load = CGF.Builder.CreateLoad(Src); | |
| auto *PoisonVec = llvm::PoisonValue::get(ScalableDstTy); | |
| llvm::Value *Result = CGF.Builder.CreateInsertVector( | |
| ScalableDstTy, PoisonVec, Load, uint64_t(0), "cast.scalable"); | |
| ScalableDstTy = cast<llvm::ScalableVectorType>( | |
| llvm::VectorType::getWithSizeAndScalar(ScalableDstTy, Ty)); | |
| if (Result->getType() != ScalableDstTy) | |
| Result = CGF.Builder.CreateBitCast(Result, ScalableDstTy); | |
| if (Result->getType() != Ty) | |
| Result = CGF.Builder.CreateExtractVector(Ty, Result, uint64_t(0)); | |
| return Result; | |
| } | |
| } | |
| } | |
| // Otherwise do coercion through memory. This is stupid, but simple. | |
| RawAddress Tmp = | |
| CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName()); | |
| CGF.Builder.CreateMemCpy( | |
| Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), | |
| Src.emitRawPointer(CGF), Src.getAlignment().getAsAlign(), | |
| llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinValue())); | |
| return CGF.Builder.CreateLoad(Tmp); | |
| } | |
| static bool CreatePFPCoercedStore(llvm::Value *Src, QualType SrcFETy, | |
| Address Dst, CodeGenFunction &CGF) { | |
| std::vector<PFPField> PFPFields = CGF.getContext().findPFPFields(SrcFETy); | |
| if (PFPFields.empty()) | |
| return false; | |
| llvm::Type *SrcTy = Src->getType(); | |
| auto StoreCoercedField = [&](CharUnits Offset, llvm::Value *FieldVal) { | |
| if (!PFPFields.empty() && PFPFields[0].Offset == Offset) { | |
| auto FieldAddr = CGF.EmitAddressOfPFPField(Dst, PFPFields[0]); | |
| if (isa<llvm::IntegerType>(FieldVal->getType())) | |
| FieldVal = CGF.Builder.CreateIntToPtr(FieldVal, CGF.VoidPtrTy); | |
| CGF.Builder.CreateStore(FieldVal, FieldAddr); | |
| PFPFields.erase(PFPFields.begin()); | |
| } else { | |
| auto FieldAddr = CGF.Builder | |
| .CreateConstInBoundsByteGEP( | |
| Dst.withElementType(CGF.Int8Ty), Offset) | |
| .withElementType(FieldVal->getType()); | |
| CGF.Builder.CreateStore(FieldVal, FieldAddr); | |
| } | |
| }; | |
| // The types handled by this function are the only ones that may be generated | |
| // by AArch64ABIInfo::classify{Argument,Return}Type for struct types with | |
| // pointers. PFP is only supported on AArch64. | |
| if (isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy)) { | |
| if (isa<llvm::IntegerType>(SrcTy)) | |
| Src = CGF.Builder.CreateIntToPtr(Src, CGF.VoidPtrTy); | |
| auto Addr = CGF.EmitAddressOfPFPField(Dst, PFPFields[0]); | |
| CGF.Builder.CreateStore(Src, Addr); | |
| } else { | |
| auto *AT = cast<llvm::ArrayType>(SrcTy); | |
| auto *ET = AT->getElementType(); | |
| CharUnits WordSize = CGF.getContext().toCharUnitsFromBits( | |
| CGF.CGM.getDataLayout().getTypeSizeInBits(ET)); | |
| CharUnits Offset = CharUnits::Zero(); | |
| for (unsigned i = 0; i != AT->getNumElements(); ++i, Offset += WordSize) | |
| StoreCoercedField(Offset, CGF.Builder.CreateExtractValue(Src, i)); | |
| } | |
| return true; | |
| } | |
| void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, QualType SrcFETy, | |
| Address Dst, llvm::TypeSize DstSize, | |
| bool DstIsVolatile) { | |
| if (!DstSize) | |
| return; | |
| llvm::Type *SrcTy = Src->getType(); | |
| llvm::TypeSize SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy); | |
| // GEP into structs to try to make types match. | |
| // FIXME: This isn't really that useful with opaque types, but it impacts a | |
| // lot of regression tests. | |
| if (SrcTy != Dst.getElementType()) { | |
| if (llvm::StructType *DstSTy = | |
| dyn_cast<llvm::StructType>(Dst.getElementType())) { | |
| assert(!SrcSize.isScalable()); | |
| Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy, | |
| SrcSize.getFixedValue(), *this); | |
| } | |
| } | |
| if (CreatePFPCoercedStore(Src, SrcFETy, Dst, *this)) | |
| return; | |
| if (SrcSize.isScalable() || SrcSize <= DstSize) { | |
| if (SrcTy->isIntegerTy() && Dst.getElementType()->isPointerTy() && | |
| SrcSize == CGM.getDataLayout().getTypeAllocSize(Dst.getElementType())) { | |
| // If the value is supposed to be a pointer, convert it before storing it. | |
| Src = CoerceIntOrPtrToIntOrPtr(Src, Dst.getElementType(), *this); | |
| auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile); | |
| addInstToCurrentSourceAtom(I, Src); | |
| } else if (llvm::StructType *STy = | |
| dyn_cast<llvm::StructType>(Src->getType())) { | |
| // Prefer scalar stores to first-class aggregate stores. | |
| Dst = Dst.withElementType(SrcTy); | |
| for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { | |
| Address EltPtr = Builder.CreateStructGEP(Dst, i); | |
| llvm::Value *Elt = Builder.CreateExtractValue(Src, i); | |
| auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile); | |
| addInstToCurrentSourceAtom(I, Elt); | |
| } | |
| } else { | |
| auto *I = | |
| Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile); | |
| addInstToCurrentSourceAtom(I, Src); | |
| } | |
| } else if (SrcTy->isIntegerTy()) { | |
| // If the source is a simple integer, coerce it directly. | |
| llvm::Type *DstIntTy = Builder.getIntNTy(DstSize.getFixedValue() * 8); | |
| Src = CoerceIntOrPtrToIntOrPtr(Src, DstIntTy, *this); | |
| auto *I = | |
| Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile); | |
| addInstToCurrentSourceAtom(I, Src); | |
| } else { | |
| // Otherwise do coercion through memory. This is stupid, but | |
| // simple. | |
| // Generally SrcSize is never greater than DstSize, since this means we are | |
| // losing bits. However, this can happen in cases where the structure has | |
| // additional padding, for example due to a user specified alignment. | |
| // | |
| // FIXME: Assert that we aren't truncating non-padding bits when have access | |
| // to that information. | |
| RawAddress Tmp = | |
| CreateTempAllocaForCoercion(*this, SrcTy, Dst.getAlignment()); | |
| Builder.CreateStore(Src, Tmp); | |
| auto *I = Builder.CreateMemCpy( | |
| Dst.emitRawPointer(*this), Dst.getAlignment().getAsAlign(), | |
| Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), | |
| Builder.CreateTypeSize(IntPtrTy, DstSize)); | |
| addInstToCurrentSourceAtom(I, Src); | |
| } | |
| } | |
| static Address emitAddressAtOffset(CodeGenFunction &CGF, Address addr, | |
| const ABIArgInfo &info) { | |
| if (unsigned offset = info.getDirectOffset()) { | |
| addr = addr.withElementType(CGF.Int8Ty); | |
| addr = CGF.Builder.CreateConstInBoundsByteGEP( | |
| addr, CharUnits::fromQuantity(offset)); | |
| addr = addr.withElementType(info.getCoerceToType()); | |
| } | |
| return addr; | |
| } | |
| static std::pair<llvm::Value *, bool> | |
| CoerceScalableToFixed(CodeGenFunction &CGF, llvm::FixedVectorType *ToTy, | |
| llvm::ScalableVectorType *FromTy, llvm::Value *V, | |
| StringRef Name = "") { | |
| // If we are casting a scalable i1 predicate vector to a fixed i8 | |
| // vector, first bitcast the source. | |
| if (FromTy->getElementType()->isIntegerTy(1) && | |
| ToTy->getElementType() == CGF.Builder.getInt8Ty()) { | |
| if (!FromTy->getElementCount().isKnownMultipleOf(8)) { | |
| FromTy = llvm::ScalableVectorType::get( | |
| FromTy->getElementType(), | |
| llvm::alignTo<8>(FromTy->getElementCount().getKnownMinValue())); | |
| llvm::Value *ZeroVec = llvm::Constant::getNullValue(FromTy); | |
| V = CGF.Builder.CreateInsertVector(FromTy, ZeroVec, V, uint64_t(0)); | |
| } | |
| FromTy = llvm::ScalableVectorType::get( | |
| ToTy->getElementType(), | |
| FromTy->getElementCount().getKnownMinValue() / 8); | |
| V = CGF.Builder.CreateBitCast(V, FromTy); | |
| } | |
| if (FromTy->getElementType() == ToTy->getElementType()) { | |
| V->setName(Name + ".coerce"); | |
| V = CGF.Builder.CreateExtractVector(ToTy, V, uint64_t(0), "cast.fixed"); | |
| return {V, true}; | |
| } | |
| return {V, false}; | |
| } | |
| namespace { | |
| /// Encapsulates information about the way function arguments from | |
| /// CGFunctionInfo should be passed to actual LLVM IR function. | |
| class ClangToLLVMArgMapping { | |
| static const unsigned InvalidIndex = ~0U; | |
| unsigned InallocaArgNo; | |
| unsigned SRetArgNo; | |
| unsigned TotalIRArgs; | |
| /// Arguments of LLVM IR function corresponding to single Clang argument. | |
| struct IRArgs { | |
| unsigned PaddingArgIndex; | |
| // Argument is expanded to IR arguments at positions | |
| // [FirstArgIndex, FirstArgIndex + NumberOfArgs). | |
| unsigned FirstArgIndex; | |
| unsigned NumberOfArgs; | |
| IRArgs() | |
| : PaddingArgIndex(InvalidIndex), FirstArgIndex(InvalidIndex), | |
| NumberOfArgs(0) {} | |
| }; | |
| SmallVector<IRArgs, 8> ArgInfo; | |
| public: | |
| ClangToLLVMArgMapping(const ASTContext &Context, const CGFunctionInfo &FI, | |
| bool OnlyRequiredArgs = false) | |
| : InallocaArgNo(InvalidIndex), SRetArgNo(InvalidIndex), TotalIRArgs(0), | |
| ArgInfo(OnlyRequiredArgs ? FI.getNumRequiredArgs() : FI.arg_size()) { | |
| construct(Context, FI, OnlyRequiredArgs); | |
| } | |
| bool hasInallocaArg() const { return InallocaArgNo != InvalidIndex; } | |
| unsigned getInallocaArgNo() const { | |
| assert(hasInallocaArg()); | |
| return InallocaArgNo; | |
| } | |
| bool hasSRetArg() const { return SRetArgNo != InvalidIndex; } | |
| unsigned getSRetArgNo() const { | |
| assert(hasSRetArg()); | |
| return SRetArgNo; | |
| } | |
| unsigned totalIRArgs() const { return TotalIRArgs; } | |
| bool hasPaddingArg(unsigned ArgNo) const { | |
| assert(ArgNo < ArgInfo.size()); | |
| return ArgInfo[ArgNo].PaddingArgIndex != InvalidIndex; | |
| } | |
| unsigned getPaddingArgNo(unsigned ArgNo) const { | |
| assert(hasPaddingArg(ArgNo)); | |
| return ArgInfo[ArgNo].PaddingArgIndex; | |
| } | |
| /// Returns index of first IR argument corresponding to ArgNo, and their | |
| /// quantity. | |
| std::pair<unsigned, unsigned> getIRArgs(unsigned ArgNo) const { | |
| assert(ArgNo < ArgInfo.size()); | |
| return std::make_pair(ArgInfo[ArgNo].FirstArgIndex, | |
| ArgInfo[ArgNo].NumberOfArgs); | |
| } | |
| private: | |
| void construct(const ASTContext &Context, const CGFunctionInfo &FI, | |
| bool OnlyRequiredArgs); | |
| }; | |
| void ClangToLLVMArgMapping::construct(const ASTContext &Context, | |
| const CGFunctionInfo &FI, | |
| bool OnlyRequiredArgs) { | |
| unsigned IRArgNo = 0; | |
| bool SwapThisWithSRet = false; | |
| const ABIArgInfo &RetAI = FI.getReturnInfo(); | |
| if (RetAI.getKind() == ABIArgInfo::Indirect) { | |
| SwapThisWithSRet = RetAI.isSRetAfterThis(); | |
| SRetArgNo = SwapThisWithSRet ? 1 : IRArgNo++; | |
| } | |
| unsigned ArgNo = 0; | |
| unsigned NumArgs = OnlyRequiredArgs ? FI.getNumRequiredArgs() : FI.arg_size(); | |
| for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(); ArgNo < NumArgs; | |
| ++I, ++ArgNo) { | |
| assert(I != FI.arg_end()); | |
| QualType ArgType = I->type; | |
| const ABIArgInfo &AI = I->info; | |
| // Collect data about IR arguments corresponding to Clang argument ArgNo. | |
| auto &IRArgs = ArgInfo[ArgNo]; | |
| if (AI.getPaddingType()) | |
| IRArgs.PaddingArgIndex = IRArgNo++; | |
| switch (AI.getKind()) { | |
| case ABIArgInfo::TargetSpecific: | |
| case ABIArgInfo::Extend: | |
| case ABIArgInfo::Direct: { | |
| // FIXME: handle sseregparm someday... | |
| llvm::StructType *STy = dyn_cast<llvm::StructType>(AI.getCoerceToType()); | |
| if (AI.isDirect() && AI.getCanBeFlattened() && STy) { | |
| IRArgs.NumberOfArgs = STy->getNumElements(); | |
| } else { | |
| IRArgs.NumberOfArgs = 1; | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::Indirect: | |
| case ABIArgInfo::IndirectAliased: | |
| IRArgs.NumberOfArgs = 1; | |
| break; | |
| case ABIArgInfo::Ignore: | |
| case ABIArgInfo::InAlloca: | |
| // ignore and inalloca doesn't have matching LLVM parameters. | |
| IRArgs.NumberOfArgs = 0; | |
| break; | |
| case ABIArgInfo::CoerceAndExpand: | |
| IRArgs.NumberOfArgs = AI.getCoerceAndExpandTypeSequence().size(); | |
| break; | |
| case ABIArgInfo::Expand: | |
| IRArgs.NumberOfArgs = getExpansionSize(ArgType, Context); | |
| break; | |
| } | |
| if (IRArgs.NumberOfArgs > 0) { | |
| IRArgs.FirstArgIndex = IRArgNo; | |
| IRArgNo += IRArgs.NumberOfArgs; | |
| } | |
| // Skip over the sret parameter when it comes second. We already handled it | |
| // above. | |
| if (IRArgNo == 1 && SwapThisWithSRet) | |
| IRArgNo++; | |
| } | |
| assert(ArgNo == ArgInfo.size()); | |
| if (FI.usesInAlloca()) | |
| InallocaArgNo = IRArgNo++; | |
| TotalIRArgs = IRArgNo; | |
| } | |
| } // namespace | |
| /***/ | |
| bool CodeGenModule::ReturnTypeUsesSRet(const CGFunctionInfo &FI) { | |
| const auto &RI = FI.getReturnInfo(); | |
| return RI.isIndirect() || (RI.isInAlloca() && RI.getInAllocaSRet()); | |
| } | |
| bool CodeGenModule::ReturnTypeHasInReg(const CGFunctionInfo &FI) { | |
| const auto &RI = FI.getReturnInfo(); | |
| return RI.getInReg(); | |
| } | |
| bool CodeGenModule::ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI) { | |
| return ReturnTypeUsesSRet(FI) && | |
| getTargetCodeGenInfo().doesReturnSlotInterfereWithArgs(); | |
| } | |
| bool CodeGenModule::ReturnTypeUsesFPRet(QualType ResultType) { | |
| if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) { | |
| switch (BT->getKind()) { | |
| default: | |
| return false; | |
| case BuiltinType::Float: | |
| return getTarget().useObjCFPRetForRealType(FloatModeKind::Float); | |
| case BuiltinType::Double: | |
| return getTarget().useObjCFPRetForRealType(FloatModeKind::Double); | |
| case BuiltinType::LongDouble: | |
| return getTarget().useObjCFPRetForRealType(FloatModeKind::LongDouble); | |
| } | |
| } | |
| return false; | |
| } | |
| bool CodeGenModule::ReturnTypeUsesFP2Ret(QualType ResultType) { | |
| if (const ComplexType *CT = ResultType->getAs<ComplexType>()) { | |
| if (const BuiltinType *BT = CT->getElementType()->getAs<BuiltinType>()) { | |
| if (BT->getKind() == BuiltinType::LongDouble) | |
| return getTarget().useObjCFP2RetForComplexLongDouble(); | |
| } | |
| } | |
| return false; | |
| } | |
| llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) { | |
| const CGFunctionInfo &FI = arrangeGlobalDeclaration(GD); | |
| return GetFunctionType(FI); | |
| } | |
| llvm::FunctionType *CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { | |
| bool Inserted = FunctionsBeingProcessed.insert(&FI).second; | |
| (void)Inserted; | |
| assert(Inserted && "Recursively being processed?"); | |
| llvm::Type *resultType = nullptr; | |
| const ABIArgInfo &retAI = FI.getReturnInfo(); | |
| switch (retAI.getKind()) { | |
| case ABIArgInfo::Expand: | |
| case ABIArgInfo::IndirectAliased: | |
| llvm_unreachable("Invalid ABI kind for return argument"); | |
| case ABIArgInfo::TargetSpecific: | |
| case ABIArgInfo::Extend: | |
| case ABIArgInfo::Direct: | |
| resultType = retAI.getCoerceToType(); | |
| break; | |
| case ABIArgInfo::InAlloca: | |
| if (retAI.getInAllocaSRet()) { | |
| // sret things on win32 aren't void, they return the sret pointer. | |
| QualType ret = FI.getReturnType(); | |
| unsigned addressSpace = CGM.getTypes().getTargetAddressSpace(ret); | |
| resultType = llvm::PointerType::get(getLLVMContext(), addressSpace); | |
| } else { | |
| resultType = llvm::Type::getVoidTy(getLLVMContext()); | |
| } | |
| break; | |
| case ABIArgInfo::Indirect: | |
| case ABIArgInfo::Ignore: | |
| resultType = llvm::Type::getVoidTy(getLLVMContext()); | |
| break; | |
| case ABIArgInfo::CoerceAndExpand: | |
| resultType = retAI.getUnpaddedCoerceAndExpandType(); | |
| break; | |
| } | |
| ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI, true); | |
| SmallVector<llvm::Type *, 8> ArgTypes(IRFunctionArgs.totalIRArgs()); | |
| // Add type for sret argument. | |
| if (IRFunctionArgs.hasSRetArg()) { | |
| ArgTypes[IRFunctionArgs.getSRetArgNo()] = llvm::PointerType::get( | |
| getLLVMContext(), FI.getReturnInfo().getIndirectAddrSpace()); | |
| } | |
| // Add type for inalloca argument. | |
| if (IRFunctionArgs.hasInallocaArg()) | |
| ArgTypes[IRFunctionArgs.getInallocaArgNo()] = | |
| llvm::PointerType::getUnqual(getLLVMContext()); | |
| // Add in all of the required arguments. | |
| unsigned ArgNo = 0; | |
| CGFunctionInfo::const_arg_iterator it = FI.arg_begin(), | |
| ie = it + FI.getNumRequiredArgs(); | |
| for (; it != ie; ++it, ++ArgNo) { | |
| const ABIArgInfo &ArgInfo = it->info; | |
| // Insert a padding type to ensure proper alignment. | |
| if (IRFunctionArgs.hasPaddingArg(ArgNo)) | |
| ArgTypes[IRFunctionArgs.getPaddingArgNo(ArgNo)] = | |
| ArgInfo.getPaddingType(); | |
| unsigned FirstIRArg, NumIRArgs; | |
| std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); | |
| switch (ArgInfo.getKind()) { | |
| case ABIArgInfo::Ignore: | |
| case ABIArgInfo::InAlloca: | |
| assert(NumIRArgs == 0); | |
| break; | |
| case ABIArgInfo::Indirect: | |
| assert(NumIRArgs == 1); | |
| // indirect arguments are always on the stack, which is alloca addr space. | |
| ArgTypes[FirstIRArg] = llvm::PointerType::get( | |
| getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace()); | |
| break; | |
| case ABIArgInfo::IndirectAliased: | |
| assert(NumIRArgs == 1); | |
| ArgTypes[FirstIRArg] = llvm::PointerType::get( | |
| getLLVMContext(), ArgInfo.getIndirectAddrSpace()); | |
| break; | |
| case ABIArgInfo::TargetSpecific: | |
| case ABIArgInfo::Extend: | |
| case ABIArgInfo::Direct: { | |
| // Fast-isel and the optimizer generally like scalar values better than | |
| // FCAs, so we flatten them if this is safe to do for this argument. | |
| llvm::Type *argType = ArgInfo.getCoerceToType(); | |
| llvm::StructType *st = dyn_cast<llvm::StructType>(argType); | |
| if (st && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) { | |
| assert(NumIRArgs == st->getNumElements()); | |
| for (unsigned i = 0, e = st->getNumElements(); i != e; ++i) | |
| ArgTypes[FirstIRArg + i] = st->getElementType(i); | |
| } else { | |
| assert(NumIRArgs == 1); | |
| ArgTypes[FirstIRArg] = argType; | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::CoerceAndExpand: { | |
| auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; | |
| for (auto *EltTy : ArgInfo.getCoerceAndExpandTypeSequence()) { | |
| *ArgTypesIter++ = EltTy; | |
| } | |
| assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs); | |
| break; | |
| } | |
| case ABIArgInfo::Expand: | |
| auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; | |
| getExpandedTypes(it->type, ArgTypesIter); | |
| assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs); | |
| break; | |
| } | |
| } | |
| bool Erased = FunctionsBeingProcessed.erase(&FI); | |
| (void)Erased; | |
| assert(Erased && "Not in set?"); | |
| return llvm::FunctionType::get(resultType, ArgTypes, FI.isVariadic()); | |
| } | |
| llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) { | |
| const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); | |
| const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); | |
| if (!isFuncTypeConvertible(FPT)) | |
| return llvm::StructType::get(getLLVMContext()); | |
| return GetFunctionType(GD); | |
| } | |
| static void AddAttributesFromFunctionProtoType(ASTContext &Ctx, | |
| llvm::AttrBuilder &FuncAttrs, | |
| const FunctionProtoType *FPT) { | |
| if (!FPT) | |
| return; | |
| if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) && | |
| FPT->isNothrow()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); | |
| unsigned SMEBits = FPT->getAArch64SMEAttributes(); | |
| if (SMEBits & FunctionType::SME_PStateSMEnabledMask) | |
| FuncAttrs.addAttribute("aarch64_pstate_sm_enabled"); | |
| if (SMEBits & FunctionType::SME_PStateSMCompatibleMask) | |
| FuncAttrs.addAttribute("aarch64_pstate_sm_compatible"); | |
| if (SMEBits & FunctionType::SME_AgnosticZAStateMask) | |
| FuncAttrs.addAttribute("aarch64_za_state_agnostic"); | |
| // ZA | |
| if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves) | |
| FuncAttrs.addAttribute("aarch64_preserves_za"); | |
| if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In) | |
| FuncAttrs.addAttribute("aarch64_in_za"); | |
| if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out) | |
| FuncAttrs.addAttribute("aarch64_out_za"); | |
| if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut) | |
| FuncAttrs.addAttribute("aarch64_inout_za"); | |
| // ZT0 | |
| if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Preserves) | |
| FuncAttrs.addAttribute("aarch64_preserves_zt0"); | |
| if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_In) | |
| FuncAttrs.addAttribute("aarch64_in_zt0"); | |
| if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Out) | |
| FuncAttrs.addAttribute("aarch64_out_zt0"); | |
| if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_InOut) | |
| FuncAttrs.addAttribute("aarch64_inout_zt0"); | |
| unsigned RISCVBits = FPT->getRISCVAttributes(); | |
| switch (FunctionType::getRISCVXsfmmState(RISCVBits)) { | |
| case FunctionType::RISCVNone: | |
| break; | |
| case FunctionType::RISCVIn: | |
| FuncAttrs.addAttribute("riscv_in"); | |
| break; | |
| case FunctionType::RISCVOut: | |
| FuncAttrs.addAttribute("riscv_out"); | |
| break; | |
| case FunctionType::RISCVInOut: | |
| FuncAttrs.addAttribute("riscv_inout"); | |
| break; | |
| case FunctionType::RISCVPreserves: | |
| FuncAttrs.addAttribute("riscv_preserves"); | |
| break; | |
| case FunctionType::RISCVNew: | |
| FuncAttrs.addAttribute("riscv_new"); | |
| break; | |
| } | |
| } | |
| static void AddAttributesFromOMPAssumes(llvm::AttrBuilder &FuncAttrs, | |
| const Decl *Callee) { | |
| if (!Callee) | |
| return; | |
| SmallVector<StringRef, 4> Attrs; | |
| for (const OMPAssumeAttr *AA : Callee->specific_attrs<OMPAssumeAttr>()) | |
| AA->getAssumption().split(Attrs, ","); | |
| if (!Attrs.empty()) | |
| FuncAttrs.addAttribute(llvm::AssumptionAttrKey, | |
| llvm::join(Attrs.begin(), Attrs.end(), ",")); | |
| } | |
| bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context, | |
| QualType ReturnType) const { | |
| // We can't just discard the return value for a record type with a | |
| // complex destructor or a non-trivially copyable type. | |
| if (const RecordType *RT = | |
| ReturnType.getCanonicalType()->getAsCanonical<RecordType>()) { | |
| if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) | |
| return ClassDecl->hasTrivialDestructor(); | |
| } | |
| return ReturnType.isTriviallyCopyableType(Context); | |
| } | |
| static bool HasStrictReturn(const CodeGenModule &Module, QualType RetTy, | |
| const Decl *TargetDecl) { | |
| // As-is msan can not tolerate noundef mismatch between caller and | |
| // implementation. Mismatch is possible for e.g. indirect calls from C-caller | |
| // into C++. Such mismatches lead to confusing false reports. To avoid | |
| // expensive workaround on msan we enforce initialization event in uncommon | |
| // cases where it's allowed. | |
| if (Module.getLangOpts().Sanitize.has(SanitizerKind::Memory)) | |
| return true; | |
| // C++ explicitly makes returning undefined values UB. C's rule only applies | |
| // to used values, so we never mark them noundef for now. | |
| if (!Module.getLangOpts().CPlusPlus) | |
| return false; | |
| if (TargetDecl) { | |
| if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(TargetDecl)) { | |
| if (FDecl->isExternC()) | |
| return false; | |
| } else if (const VarDecl *VDecl = dyn_cast<VarDecl>(TargetDecl)) { | |
| // Function pointer. | |
| if (VDecl->isExternC()) | |
| return false; | |
| } | |
| } | |
| // We don't want to be too aggressive with the return checking, unless | |
| // it's explicit in the code opts or we're using an appropriate sanitizer. | |
| // Try to respect what the programmer intended. | |
| return Module.getCodeGenOpts().StrictReturn || | |
| !Module.MayDropFunctionReturn(Module.getContext(), RetTy) || | |
| Module.getLangOpts().Sanitize.has(SanitizerKind::Return); | |
| } | |
| /// Add denormal-fp-math and denormal-fp-math-f32 as appropriate for the | |
| /// requested denormal behavior, accounting for the overriding behavior of the | |
| /// -f32 case. | |
| static void addDenormalModeAttrs(llvm::DenormalMode FPDenormalMode, | |
| llvm::DenormalMode FP32DenormalMode, | |
| llvm::AttrBuilder &FuncAttrs) { | |
| llvm::DenormalFPEnv FPEnv(FPDenormalMode, FP32DenormalMode); | |
| if (FPEnv != llvm::DenormalFPEnv::getDefault()) | |
| FuncAttrs.addDenormalFPEnvAttr(FPEnv); | |
| } | |
| /// Add default attributes to a function, which have merge semantics under | |
| /// -mlink-builtin-bitcode and should not simply overwrite any existing | |
| /// attributes in the linked library. | |
| static void | |
| addMergableDefaultFunctionAttributes(const CodeGenOptions &CodeGenOpts, | |
| llvm::AttrBuilder &FuncAttrs) { | |
| addDenormalModeAttrs(CodeGenOpts.FPDenormalMode, CodeGenOpts.FP32DenormalMode, | |
| FuncAttrs); | |
| } | |
| static void getTrivialDefaultFunctionAttributes( | |
| StringRef Name, bool HasOptnone, const CodeGenOptions &CodeGenOpts, | |
| const LangOptions &LangOpts, bool AttrOnCallSite, | |
| llvm::AttrBuilder &FuncAttrs) { | |
| // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed. | |
| if (!HasOptnone) { | |
| if (CodeGenOpts.OptimizeSize) | |
| FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); | |
| if (CodeGenOpts.OptimizeSize == 2) | |
| FuncAttrs.addAttribute(llvm::Attribute::MinSize); | |
| } | |
| if (CodeGenOpts.DisableRedZone) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoRedZone); | |
| if (CodeGenOpts.IndirectTlsSegRefs) | |
| FuncAttrs.addAttribute("indirect-tls-seg-refs"); | |
| if (CodeGenOpts.NoImplicitFloat) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat); | |
| if (AttrOnCallSite) { | |
| // Attributes that should go on the call site only. | |
| // FIXME: Look for 'BuiltinAttr' on the function rather than re-checking | |
| // the -fno-builtin-foo list. | |
| if (!CodeGenOpts.SimplifyLibCalls || LangOpts.isNoBuiltinFunc(Name)) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); | |
| if (!CodeGenOpts.TrapFuncName.empty()) | |
| FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); | |
| } else { | |
| switch (CodeGenOpts.getFramePointer()) { | |
| case CodeGenOptions::FramePointerKind::None: | |
| // This is the default behavior. | |
| break; | |
| case CodeGenOptions::FramePointerKind::Reserved: | |
| case CodeGenOptions::FramePointerKind::NonLeafNoReserve: | |
| case CodeGenOptions::FramePointerKind::NonLeaf: | |
| case CodeGenOptions::FramePointerKind::All: | |
| FuncAttrs.addAttribute("frame-pointer", | |
| CodeGenOptions::getFramePointerKindName( | |
| CodeGenOpts.getFramePointer())); | |
| } | |
| if (CodeGenOpts.LessPreciseFPMAD) | |
| FuncAttrs.addAttribute("less-precise-fpmad", "true"); | |
| if (CodeGenOpts.NullPointerIsValid) | |
| FuncAttrs.addAttribute(llvm::Attribute::NullPointerIsValid); | |
| if (LangOpts.getDefaultExceptionMode() == LangOptions::FPE_Ignore) | |
| FuncAttrs.addAttribute("no-trapping-math", "true"); | |
| // TODO: Are these all needed? | |
| // unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags. | |
| if (CodeGenOpts.SoftFloat) | |
| FuncAttrs.addAttribute("use-soft-float", "true"); | |
| FuncAttrs.addAttribute("stack-protector-buffer-size", | |
| llvm::utostr(CodeGenOpts.SSPBufferSize)); | |
| if (LangOpts.NoSignedZero) | |
| FuncAttrs.addAttribute("no-signed-zeros-fp-math", "true"); | |
| // TODO: Reciprocal estimate codegen options should apply to instructions? | |
| const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals; | |
| if (!Recips.empty()) | |
| FuncAttrs.addAttribute("reciprocal-estimates", llvm::join(Recips, ",")); | |
| if (!CodeGenOpts.PreferVectorWidth.empty() && | |
| CodeGenOpts.PreferVectorWidth != "none") | |
| FuncAttrs.addAttribute("prefer-vector-width", | |
| CodeGenOpts.PreferVectorWidth); | |
| if (CodeGenOpts.StackRealignment) | |
| FuncAttrs.addAttribute("stackrealign"); | |
| if (CodeGenOpts.Backchain) | |
| FuncAttrs.addAttribute("backchain"); | |
| if (CodeGenOpts.EnableSegmentedStacks) | |
| FuncAttrs.addAttribute("split-stack"); | |
| if (CodeGenOpts.SpeculativeLoadHardening) | |
| FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); | |
| // Add zero-call-used-regs attribute. | |
| switch (CodeGenOpts.getZeroCallUsedRegs()) { | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip: | |
| FuncAttrs.removeAttribute("zero-call-used-regs"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPRArg: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "used-gpr-arg"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPR: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "used-gpr"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedArg: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "used-arg"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Used: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "used"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPRArg: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "all-gpr-arg"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPR: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "all-gpr"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllArg: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "all-arg"); | |
| break; | |
| case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::All: | |
| FuncAttrs.addAttribute("zero-call-used-regs", "all"); | |
| break; | |
| } | |
| } | |
| if (LangOpts.assumeFunctionsAreConvergent()) { | |
| // Conservatively, mark all functions and calls in CUDA and OpenCL as | |
| // convergent (meaning, they may call an intrinsically convergent op, such | |
| // as __syncthreads() / barrier(), and so can't have certain optimizations | |
| // applied around them). LLVM will remove this attribute where it safely | |
| // can. | |
| FuncAttrs.addAttribute(llvm::Attribute::Convergent); | |
| } | |
| // TODO: NoUnwind attribute should be added for other GPU modes HIP, | |
| // OpenMP offload. AFAIK, neither of them support exceptions in device code. | |
| if ((LangOpts.CUDA && LangOpts.CUDAIsDevice) || LangOpts.OpenCL || | |
| LangOpts.SYCLIsDevice) { | |
| FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); | |
| } | |
| if (CodeGenOpts.SaveRegParams && !AttrOnCallSite) | |
| FuncAttrs.addAttribute("save-reg-params"); | |
| for (StringRef Attr : CodeGenOpts.DefaultFunctionAttrs) { | |
| StringRef Var, Value; | |
| std::tie(Var, Value) = Attr.split('='); | |
| FuncAttrs.addAttribute(Var, Value); | |
| } | |
| if (!AttrOnCallSite) { | |
| TargetInfo::BranchProtectionInfo BPI(LangOpts); | |
| TargetCodeGenInfo::initBranchProtectionFnAttributes(BPI, FuncAttrs); | |
| } | |
| } | |
| /// Merges `target-features` from \TargetOpts and \F, and sets the result in | |
| /// \FuncAttr | |
| /// * features from \F are always kept | |
| /// * a feature from \TargetOpts is kept if itself and its opposite are absent | |
| /// from \F | |
| static void | |
| overrideFunctionFeaturesWithTargetFeatures(llvm::AttrBuilder &FuncAttr, | |
| const llvm::Function &F, | |
| const TargetOptions &TargetOpts) { | |
| auto FFeatures = F.getFnAttribute("target-features"); | |
| llvm::StringSet<> MergedNames; | |
| SmallVector<StringRef> MergedFeatures; | |
| MergedFeatures.reserve(TargetOpts.Features.size()); | |
| auto AddUnmergedFeatures = [&](auto &&FeatureRange) { | |
| for (StringRef Feature : FeatureRange) { | |
| if (Feature.empty()) | |
| continue; | |
| assert(Feature[0] == '+' || Feature[0] == '-'); | |
| StringRef Name = Feature.drop_front(1); | |
| bool Merged = !MergedNames.insert(Name).second; | |
| if (!Merged) | |
| MergedFeatures.push_back(Feature); | |
| } | |
| }; | |
| if (FFeatures.isValid()) | |
| AddUnmergedFeatures(llvm::split(FFeatures.getValueAsString(), ',')); | |
| AddUnmergedFeatures(TargetOpts.Features); | |
| if (!MergedFeatures.empty()) { | |
| llvm::sort(MergedFeatures); | |
| FuncAttr.addAttribute("target-features", llvm::join(MergedFeatures, ",")); | |
| } | |
| } | |
| void CodeGen::mergeDefaultFunctionDefinitionAttributes( | |
| llvm::Function &F, const CodeGenOptions &CodeGenOpts, | |
| const LangOptions &LangOpts, const TargetOptions &TargetOpts, | |
| bool WillInternalize) { | |
| llvm::AttrBuilder FuncAttrs(F.getContext()); | |
| // Here we only extract the options that are relevant compared to the version | |
| // from GetCPUAndFeaturesAttributes. | |
| if (!TargetOpts.CPU.empty()) | |
| FuncAttrs.addAttribute("target-cpu", TargetOpts.CPU); | |
| if (!TargetOpts.TuneCPU.empty()) | |
| FuncAttrs.addAttribute("tune-cpu", TargetOpts.TuneCPU); | |
| ::getTrivialDefaultFunctionAttributes(F.getName(), F.hasOptNone(), | |
| CodeGenOpts, LangOpts, | |
| /*AttrOnCallSite=*/false, FuncAttrs); | |
| if (!WillInternalize && F.isInterposable()) { | |
| // Do not promote "dynamic" denormal-fp-math to this translation unit's | |
| // setting for weak functions that won't be internalized. The user has no | |
| // real control for how builtin bitcode is linked, so we shouldn't assume | |
| // later copies will use a consistent mode. | |
| F.addFnAttrs(FuncAttrs); | |
| return; | |
| } | |
| llvm::AttributeMask AttrsToRemove; | |
| llvm::DenormalFPEnv OptsFPEnv(CodeGenOpts.FPDenormalMode, | |
| CodeGenOpts.FP32DenormalMode); | |
| llvm::DenormalFPEnv MergedFPEnv = | |
| OptsFPEnv.mergeCalleeMode(F.getDenormalFPEnv()); | |
| if (MergedFPEnv == llvm::DenormalFPEnv::getDefault()) { | |
| AttrsToRemove.addAttribute(llvm::Attribute::DenormalFPEnv); | |
| } else { | |
| // Overwrite existing attribute | |
| FuncAttrs.addDenormalFPEnvAttr(MergedFPEnv); | |
| } | |
| F.removeFnAttrs(AttrsToRemove); | |
| overrideFunctionFeaturesWithTargetFeatures(FuncAttrs, F, TargetOpts); | |
| F.addFnAttrs(FuncAttrs); | |
| } | |
| void CodeGenModule::getTrivialDefaultFunctionAttributes( | |
| StringRef Name, bool HasOptnone, bool AttrOnCallSite, | |
| llvm::AttrBuilder &FuncAttrs) { | |
| ::getTrivialDefaultFunctionAttributes(Name, HasOptnone, getCodeGenOpts(), | |
| getLangOpts(), AttrOnCallSite, | |
| FuncAttrs); | |
| } | |
| void CodeGenModule::getDefaultFunctionAttributes(StringRef Name, | |
| bool HasOptnone, | |
| bool AttrOnCallSite, | |
| llvm::AttrBuilder &FuncAttrs) { | |
| getTrivialDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, | |
| FuncAttrs); | |
| if (!AttrOnCallSite) | |
| TargetCodeGenInfo::initPointerAuthFnAttributes(CodeGenOpts.PointerAuth, | |
| FuncAttrs); | |
| // If we're just getting the default, get the default values for mergeable | |
| // attributes. | |
| if (!AttrOnCallSite) | |
| addMergableDefaultFunctionAttributes(CodeGenOpts, FuncAttrs); | |
| } | |
| void CodeGenModule::addDefaultFunctionDefinitionAttributes( | |
| llvm::AttrBuilder &attrs) { | |
| getDefaultFunctionAttributes(/*function name*/ "", /*optnone*/ false, | |
| /*for call*/ false, attrs); | |
| GetCPUAndFeaturesAttributes(GlobalDecl(), attrs); | |
| } | |
| static void addNoBuiltinAttributes(llvm::AttrBuilder &FuncAttrs, | |
| const LangOptions &LangOpts, | |
| const NoBuiltinAttr *NBA = nullptr) { | |
| auto AddNoBuiltinAttr = [&FuncAttrs](StringRef BuiltinName) { | |
| SmallString<32> AttributeName; | |
| AttributeName += "no-builtin-"; | |
| AttributeName += BuiltinName; | |
| FuncAttrs.addAttribute(AttributeName); | |
| }; | |
| // First, handle the language options passed through -fno-builtin. | |
| if (LangOpts.NoBuiltin) { | |
| // -fno-builtin disables them all. | |
| FuncAttrs.addAttribute("no-builtins"); | |
| return; | |
| } | |
| // Then, add attributes for builtins specified through -fno-builtin-<name>. | |
| llvm::for_each(LangOpts.NoBuiltinFuncs, AddNoBuiltinAttr); | |
| // Now, let's check the __attribute__((no_builtin("...")) attribute added to | |
| // the source. | |
| if (!NBA) | |
| return; | |
| // If there is a wildcard in the builtin names specified through the | |
| // attribute, disable them all. | |
| if (llvm::is_contained(NBA->builtinNames(), "*")) { | |
| FuncAttrs.addAttribute("no-builtins"); | |
| return; | |
| } | |
| // And last, add the rest of the builtin names. | |
| llvm::for_each(NBA->builtinNames(), AddNoBuiltinAttr); | |
| } | |
| static bool DetermineNoUndef(QualType QTy, CodeGenTypes &Types, | |
| const llvm::DataLayout &DL, const ABIArgInfo &AI, | |
| bool CheckCoerce = true) { | |
| llvm::Type *Ty = Types.ConvertTypeForMem(QTy); | |
| if (AI.getKind() == ABIArgInfo::Indirect || | |
| AI.getKind() == ABIArgInfo::IndirectAliased) | |
| return true; | |
| if (AI.getKind() == ABIArgInfo::Extend && !AI.isNoExt()) | |
| return true; | |
| if (!DL.typeSizeEqualsStoreSize(Ty)) | |
| // TODO: This will result in a modest amount of values not marked noundef | |
| // when they could be. We care about values that *invisibly* contain undef | |
| // bits from the perspective of LLVM IR. | |
| return false; | |
| if (CheckCoerce && AI.canHaveCoerceToType()) { | |
| llvm::Type *CoerceTy = AI.getCoerceToType(); | |
| if (llvm::TypeSize::isKnownGT(DL.getTypeSizeInBits(CoerceTy), | |
| DL.getTypeSizeInBits(Ty))) | |
| // If we're coercing to a type with a greater size than the canonical one, | |
| // we're introducing new undef bits. | |
| // Coercing to a type of smaller or equal size is ok, as we know that | |
| // there's no internal padding (typeSizeEqualsStoreSize). | |
| return false; | |
| } | |
| if (QTy->isBitIntType()) | |
| return true; | |
| if (QTy->isReferenceType()) | |
| return true; | |
| if (QTy->isNullPtrType()) | |
| return false; | |
| if (QTy->isMemberPointerType()) | |
| // TODO: Some member pointers are `noundef`, but it depends on the ABI. For | |
| // now, never mark them. | |
| return false; | |
| if (QTy->isScalarType()) { | |
| if (const ComplexType *Complex = dyn_cast<ComplexType>(QTy)) | |
| return DetermineNoUndef(Complex->getElementType(), Types, DL, AI, false); | |
| return true; | |
| } | |
| if (const VectorType *Vector = dyn_cast<VectorType>(QTy)) | |
| return DetermineNoUndef(Vector->getElementType(), Types, DL, AI, false); | |
| if (const MatrixType *Matrix = dyn_cast<MatrixType>(QTy)) | |
| return DetermineNoUndef(Matrix->getElementType(), Types, DL, AI, false); | |
| if (const ArrayType *Array = dyn_cast<ArrayType>(QTy)) | |
| return DetermineNoUndef(Array->getElementType(), Types, DL, AI, false); | |
| // TODO: Some structs may be `noundef`, in specific situations. | |
| return false; | |
| } | |
| /// Check if the argument of a function has maybe_undef attribute. | |
| static bool IsArgumentMaybeUndef(const Decl *TargetDecl, | |
| unsigned NumRequiredArgs, unsigned ArgNo) { | |
| const auto *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl); | |
| if (!FD) | |
| return false; | |
| // Assume variadic arguments do not have maybe_undef attribute. | |
| if (ArgNo >= NumRequiredArgs) | |
| return false; | |
| // Check if argument has maybe_undef attribute. | |
| if (ArgNo < FD->getNumParams()) { | |
| const ParmVarDecl *Param = FD->getParamDecl(ArgNo); | |
| if (Param && Param->hasAttr<MaybeUndefAttr>()) | |
| return true; | |
| } | |
| return false; | |
| } | |
| /// Test if it's legal to apply nofpclass for the given parameter type and it's | |
| /// lowered IR type. | |
| static bool canApplyNoFPClass(const ABIArgInfo &AI, QualType ParamType, | |
| bool IsReturn) { | |
| // Should only apply to FP types in the source, not ABI promoted. | |
| if (!ParamType->hasFloatingRepresentation()) | |
| return false; | |
| // The promoted-to IR type also needs to support nofpclass. | |
| llvm::Type *IRTy = AI.getCoerceToType(); | |
| if (llvm::AttributeFuncs::isNoFPClassCompatibleType(IRTy)) | |
| return true; | |
| if (llvm::StructType *ST = dyn_cast<llvm::StructType>(IRTy)) { | |
| return !IsReturn && AI.getCanBeFlattened() && | |
| llvm::all_of(ST->elements(), | |
| llvm::AttributeFuncs::isNoFPClassCompatibleType); | |
| } | |
| return false; | |
| } | |
| void CodeGenModule::AdjustMemoryAttribute(StringRef Name, | |
| CGCalleeInfo CalleeInfo, | |
| llvm::AttributeList &Attrs) { | |
| if (Attrs.getMemoryEffects().getModRef() == llvm::ModRefInfo::NoModRef) { | |
| Attrs = Attrs.removeFnAttribute(getLLVMContext(), llvm::Attribute::Memory); | |
| llvm::Attribute MemoryAttr = llvm::Attribute::getWithMemoryEffects( | |
| getLLVMContext(), llvm::MemoryEffects::writeOnly()); | |
| Attrs = Attrs.addFnAttribute(getLLVMContext(), MemoryAttr); | |
| } | |
| } | |
| /// Construct the IR attribute list of a function or call. | |
| /// | |
| /// When adding an attribute, please consider where it should be handled: | |
| /// | |
| /// - getDefaultFunctionAttributes is for attributes that are essentially | |
| /// part of the global target configuration (but perhaps can be | |
| /// overridden on a per-function basis). Adding attributes there | |
| /// will cause them to also be set in frontends that build on Clang's | |
| /// target-configuration logic, as well as for code defined in library | |
| /// modules such as CUDA's libdevice. | |
| /// | |
| /// - ConstructAttributeList builds on top of getDefaultFunctionAttributes | |
| /// and adds declaration-specific, convention-specific, and | |
| /// frontend-specific logic. The last is of particular importance: | |
| /// attributes that restrict how the frontend generates code must be | |
| /// added here rather than getDefaultFunctionAttributes. | |
| /// | |
| void CodeGenModule::ConstructAttributeList(StringRef Name, | |
| const CGFunctionInfo &FI, | |
| CGCalleeInfo CalleeInfo, | |
| llvm::AttributeList &AttrList, | |
| unsigned &CallingConv, | |
| bool AttrOnCallSite, bool IsThunk) { | |
| llvm::AttrBuilder FuncAttrs(getLLVMContext()); | |
| llvm::AttrBuilder RetAttrs(getLLVMContext()); | |
| // Collect function IR attributes from the CC lowering. | |
| // We'll collect the paramete and result attributes later. | |
| CallingConv = FI.getEffectiveCallingConvention(); | |
| if (FI.isNoReturn()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoReturn); | |
| if (FI.isCmseNSCall()) | |
| FuncAttrs.addAttribute("cmse_nonsecure_call"); | |
| // Collect function IR attributes from the callee prototype if we have one. | |
| AddAttributesFromFunctionProtoType(getContext(), FuncAttrs, | |
| CalleeInfo.getCalleeFunctionProtoType()); | |
| const Decl *TargetDecl = CalleeInfo.getCalleeDecl().getDecl(); | |
| // Attach assumption attributes to the declaration. If this is a call | |
| // site, attach assumptions from the caller to the call as well. | |
| AddAttributesFromOMPAssumes(FuncAttrs, TargetDecl); | |
| bool HasOptnone = false; | |
| // The NoBuiltinAttr attached to the target FunctionDecl. | |
| const NoBuiltinAttr *NBA = nullptr; | |
| // Some ABIs may result in additional accesses to arguments that may | |
| // otherwise not be present. | |
| std::optional<llvm::Attribute::AttrKind> MemAttrForPtrArgs; | |
| bool AddedPotentialArgAccess = false; | |
| auto AddPotentialArgAccess = [&]() { | |
| AddedPotentialArgAccess = true; | |
| llvm::Attribute A = FuncAttrs.getAttribute(llvm::Attribute::Memory); | |
| if (A.isValid()) | |
| FuncAttrs.addMemoryAttr(A.getMemoryEffects() | | |
| llvm::MemoryEffects::argMemOnly()); | |
| }; | |
| // Collect function IR attributes based on declaration-specific | |
| // information. | |
| // FIXME: handle sseregparm someday... | |
| if (TargetDecl) { | |
| if (TargetDecl->hasAttr<ReturnsTwiceAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice); | |
| if (TargetDecl->hasAttr<NoThrowAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); | |
| if (TargetDecl->hasAttr<NoReturnAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoReturn); | |
| if (TargetDecl->hasAttr<ColdAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::Cold); | |
| if (TargetDecl->hasAttr<HotAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::Hot); | |
| if (TargetDecl->hasAttr<NoDuplicateAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); | |
| if (TargetDecl->hasAttr<ConvergentAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::Convergent); | |
| if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { | |
| AddAttributesFromFunctionProtoType( | |
| getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>()); | |
| if (AttrOnCallSite && Fn->isReplaceableGlobalAllocationFunction()) { | |
| // A sane operator new returns a non-aliasing pointer. | |
| if (getCodeGenOpts().AssumeSaneOperatorNew && | |
| Fn->getDeclName().isAnyOperatorNew()) | |
| RetAttrs.addAttribute(llvm::Attribute::NoAlias); | |
| } | |
| const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn); | |
| const bool IsVirtualCall = MD && MD->isVirtual(); | |
| // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a | |
| // virtual function. These attributes are not inherited by overloads. | |
| if (!(AttrOnCallSite && IsVirtualCall)) { | |
| if (Fn->isNoReturn()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoReturn); | |
| NBA = Fn->getAttr<NoBuiltinAttr>(); | |
| } | |
| } | |
| if (isa<FunctionDecl>(TargetDecl) || isa<VarDecl>(TargetDecl)) { | |
| // Only place nomerge attribute on call sites, never functions. This | |
| // allows it to work on indirect virtual function calls. | |
| if (AttrOnCallSite && TargetDecl->hasAttr<NoMergeAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoMerge); | |
| } | |
| // 'const', 'pure' and 'noalias' attributed functions are also nounwind. | |
| if (TargetDecl->hasAttr<ConstAttr>()) { | |
| FuncAttrs.addMemoryAttr(llvm::MemoryEffects::none()); | |
| FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); | |
| // gcc specifies that 'const' functions have greater restrictions than | |
| // 'pure' functions, so they also cannot have infinite loops. | |
| FuncAttrs.addAttribute(llvm::Attribute::WillReturn); | |
| MemAttrForPtrArgs = llvm::Attribute::ReadNone; | |
| } else if (TargetDecl->hasAttr<PureAttr>()) { | |
| FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly()); | |
| FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); | |
| // gcc specifies that 'pure' functions cannot have infinite loops. | |
| FuncAttrs.addAttribute(llvm::Attribute::WillReturn); | |
| MemAttrForPtrArgs = llvm::Attribute::ReadOnly; | |
| } else if (TargetDecl->hasAttr<NoAliasAttr>()) { | |
| FuncAttrs.addMemoryAttr(llvm::MemoryEffects::inaccessibleOrArgMemOnly()); | |
| FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); | |
| } | |
| if (const auto *RA = TargetDecl->getAttr<RestrictAttr>(); | |
| RA && RA->getDeallocator() == nullptr) | |
| RetAttrs.addAttribute(llvm::Attribute::NoAlias); | |
| if (TargetDecl->hasAttr<ReturnsNonNullAttr>() && | |
| !CodeGenOpts.NullPointerIsValid) | |
| RetAttrs.addAttribute(llvm::Attribute::NonNull); | |
| if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) | |
| FuncAttrs.addAttribute("no_caller_saved_registers"); | |
| if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck); | |
| if (TargetDecl->hasAttr<LeafAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::NoCallback); | |
| if (TargetDecl->hasAttr<BPFFastCallAttr>()) | |
| FuncAttrs.addAttribute("bpf_fastcall"); | |
| HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); | |
| if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) { | |
| std::optional<unsigned> NumElemsParam; | |
| if (AllocSize->getNumElemsParam().isValid()) | |
| NumElemsParam = AllocSize->getNumElemsParam().getLLVMIndex(); | |
| FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam().getLLVMIndex(), | |
| NumElemsParam); | |
| } | |
| // OpenCL v2.0 Work groups may be whether uniform or not. | |
| // '-cl-uniform-work-group-size' compile option gets a hint | |
| // to the compiler that the global work-size be a multiple of | |
| // the work-group size specified to clEnqueueNDRangeKernel | |
| // (i.e. work groups are uniform). | |
| if (getLangOpts().OffloadUniformBlock) | |
| FuncAttrs.addAttribute("uniform-work-group-size"); | |
| if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>()) | |
| FuncAttrs.addAttribute("aarch64_pstate_sm_body"); | |
| if (auto *ModularFormat = TargetDecl->getAttr<ModularFormatAttr>()) { | |
| FormatAttr *Format = TargetDecl->getAttr<FormatAttr>(); | |
| StringRef Type = Format->getType()->getName(); | |
| std::string FormatIdx = std::to_string(Format->getFormatIdx()); | |
| std::string FirstArg = std::to_string(Format->getFirstArg()); | |
| SmallVector<StringRef> Args = { | |
| Type, FormatIdx, FirstArg, | |
| ModularFormat->getModularImplFn()->getName(), | |
| ModularFormat->getImplName()}; | |
| llvm::append_range(Args, ModularFormat->aspects()); | |
| FuncAttrs.addAttribute("modular-format", llvm::join(Args, ",")); | |
| } | |
| } | |
| // Attach "no-builtins" attributes to: | |
| // * call sites: both `nobuiltin` and "no-builtins" or "no-builtin-<name>". | |
| // * definitions: "no-builtins" or "no-builtin-<name>" only. | |
| // The attributes can come from: | |
| // * LangOpts: -ffreestanding, -fno-builtin, -fno-builtin-<name> | |
| // * FunctionDecl attributes: __attribute__((no_builtin(...))) | |
| addNoBuiltinAttributes(FuncAttrs, getLangOpts(), NBA); | |
| // Collect function IR attributes based on global settiings. | |
| getDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, FuncAttrs); | |
| // Override some default IR attributes based on declaration-specific | |
| // information. | |
| if (TargetDecl) { | |
| if (TargetDecl->hasAttr<NoSpeculativeLoadHardeningAttr>()) | |
| FuncAttrs.removeAttribute(llvm::Attribute::SpeculativeLoadHardening); | |
| if (TargetDecl->hasAttr<SpeculativeLoadHardeningAttr>()) | |
| FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); | |
| if (TargetDecl->hasAttr<NoSplitStackAttr>()) | |
| FuncAttrs.removeAttribute("split-stack"); | |
| if (TargetDecl->hasAttr<ZeroCallUsedRegsAttr>()) { | |
| // A function "__attribute__((...))" overrides the command-line flag. | |
| auto Kind = | |
| TargetDecl->getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs(); | |
| FuncAttrs.removeAttribute("zero-call-used-regs"); | |
| FuncAttrs.addAttribute( | |
| "zero-call-used-regs", | |
| ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(Kind)); | |
| } | |
| // Add NonLazyBind attribute to function declarations when -fno-plt | |
| // is used. | |
| // FIXME: what if we just haven't processed the function definition | |
| // yet, or if it's an external definition like C99 inline? | |
| if (CodeGenOpts.NoPLT) { | |
| if (auto *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { | |
| if (!Fn->isDefined() && !AttrOnCallSite) { | |
| FuncAttrs.addAttribute(llvm::Attribute::NonLazyBind); | |
| } | |
| } | |
| } | |
| // Remove 'convergent' if requested. | |
| if (TargetDecl->hasAttr<NoConvergentAttr>()) | |
| FuncAttrs.removeAttribute(llvm::Attribute::Convergent); | |
| } | |
| // Add "sample-profile-suffix-elision-policy" attribute for internal linkage | |
| // functions with -funique-internal-linkage-names. | |
| if (TargetDecl && CodeGenOpts.UniqueInternalLinkageNames) { | |
| if (const auto *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) { | |
| if (!FD->isExternallyVisible()) | |
| FuncAttrs.addAttribute("sample-profile-suffix-elision-policy", | |
| "selected"); | |
| } | |
| } | |
| // Collect non-call-site function IR attributes from declaration-specific | |
| // information. | |
| if (!AttrOnCallSite) { | |
| if (TargetDecl && TargetDecl->hasAttr<CmseNSEntryAttr>()) | |
| FuncAttrs.addAttribute("cmse_nonsecure_entry"); | |
| // Whether tail calls are enabled. | |
| auto shouldDisableTailCalls = [&] { | |
| // Should this be honored in getDefaultFunctionAttributes? | |
| if (CodeGenOpts.DisableTailCalls) | |
| return true; | |
| if (!TargetDecl) | |
| return false; | |
| if (TargetDecl->hasAttr<DisableTailCallsAttr>() || | |
| TargetDecl->hasAttr<AnyX86InterruptAttr>()) | |
| return true; | |
| if (CodeGenOpts.NoEscapingBlockTailCalls) { | |
| if (const auto *BD = dyn_cast<BlockDecl>(TargetDecl)) | |
| if (!BD->doesNotEscape()) | |
| return true; | |
| } | |
| return false; | |
| }; | |
| if (shouldDisableTailCalls()) | |
| FuncAttrs.addAttribute("disable-tail-calls", "true"); | |
| // These functions require the returns_twice attribute for correct codegen, | |
| // but the attribute may not be added if -fno-builtin is specified. We | |
| // explicitly add that attribute here. | |
| static const llvm::StringSet<> ReturnsTwiceFn{ | |
| "_setjmpex", "setjmp", "_setjmp", "vfork", | |
| "sigsetjmp", "__sigsetjmp", "savectx", "getcontext"}; | |
| if (ReturnsTwiceFn.contains(Name)) | |
| FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice); | |
| // CPU/feature overrides. addDefaultFunctionDefinitionAttributes | |
| // handles these separately to set them based on the global defaults. | |
| GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs); | |
| // Windows hotpatching support | |
| if (!MSHotPatchFunctions.empty()) { | |
| bool IsHotPatched = llvm::binary_search(MSHotPatchFunctions, Name); | |
| if (IsHotPatched) | |
| FuncAttrs.addAttribute("marked_for_windows_hot_patching"); | |
| } | |
| } | |
| // Mark functions that are replaceable by the loader. | |
| if (CodeGenOpts.isLoaderReplaceableFunctionName(Name)) | |
| FuncAttrs.addAttribute("loader-replaceable"); | |
| // Collect attributes from arguments and return values. | |
| ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI); | |
| QualType RetTy = FI.getReturnType(); | |
| const ABIArgInfo &RetAI = FI.getReturnInfo(); | |
| const llvm::DataLayout &DL = getDataLayout(); | |
| // Determine if the return type could be partially undef | |
| if (CodeGenOpts.EnableNoundefAttrs && | |
| HasStrictReturn(*this, RetTy, TargetDecl)) { | |
| if (!RetTy->isVoidType() && RetAI.getKind() != ABIArgInfo::Indirect && | |
| DetermineNoUndef(RetTy, getTypes(), DL, RetAI)) | |
| RetAttrs.addAttribute(llvm::Attribute::NoUndef); | |
| } | |
| switch (RetAI.getKind()) { | |
| case ABIArgInfo::Extend: | |
| if (RetAI.isSignExt()) | |
| RetAttrs.addAttribute(llvm::Attribute::SExt); | |
| else if (RetAI.isZeroExt()) | |
| RetAttrs.addAttribute(llvm::Attribute::ZExt); | |
| else | |
| RetAttrs.addAttribute(llvm::Attribute::NoExt); | |
| [[fallthrough]]; | |
| case ABIArgInfo::TargetSpecific: | |
| case ABIArgInfo::Direct: | |
| if (RetAI.getInReg()) | |
| RetAttrs.addAttribute(llvm::Attribute::InReg); | |
| if (canApplyNoFPClass(RetAI, RetTy, true)) | |
| RetAttrs.addNoFPClassAttr( | |
| CodeGenUtils::getNoFPClassTestMask(getLangOpts())); | |
| break; | |
| case ABIArgInfo::Ignore: | |
| break; | |
| case ABIArgInfo::InAlloca: | |
| case ABIArgInfo::Indirect: { | |
| // inalloca and sret disable readnone and readonly | |
| AddPotentialArgAccess(); | |
| break; | |
| } | |
| case ABIArgInfo::CoerceAndExpand: | |
| break; | |
| case ABIArgInfo::Expand: | |
| case ABIArgInfo::IndirectAliased: | |
| llvm_unreachable("Invalid ABI kind for return argument"); | |
| } | |
| if (!IsThunk) { | |
| // FIXME: fix this properly, https://reviews.llvm.org/D100388 | |
| if (const auto *RefTy = RetTy->getAs<ReferenceType>()) { | |
| QualType PTy = RefTy->getPointeeType(); | |
| if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) | |
| RetAttrs.addDereferenceableAttr( | |
| getMinimumObjectSize(PTy).getQuantity()); | |
| if (getTypes().getTargetAddressSpace(PTy) == 0 && | |
| !CodeGenOpts.NullPointerIsValid) | |
| RetAttrs.addAttribute(llvm::Attribute::NonNull); | |
| if (PTy->isObjectType()) { | |
| llvm::Align Alignment = | |
| getNaturalPointeeTypeAlignment(RetTy).getAsAlign(); | |
| RetAttrs.addAlignmentAttr(Alignment); | |
| } | |
| } | |
| } | |
| bool hasUsedSRet = false; | |
| SmallVector<llvm::AttrBuilder, 4> ArgAttrs; | |
| for (unsigned I = 0; I < IRFunctionArgs.totalIRArgs(); ++I) | |
| ArgAttrs.emplace_back(getLLVMContext()); | |
| // Attach attributes to sret. | |
| if (IRFunctionArgs.hasSRetArg()) { | |
| llvm::AttrBuilder &SRETAttrs = ArgAttrs[IRFunctionArgs.getSRetArgNo()]; | |
| SRETAttrs.addStructRetAttr(getTypes().ConvertTypeForMem(RetTy)); | |
| SRETAttrs.addAttribute(llvm::Attribute::Writable); | |
| SRETAttrs.addAttribute(llvm::Attribute::DeadOnUnwind); | |
| hasUsedSRet = true; | |
| if (RetAI.getInReg()) | |
| SRETAttrs.addAttribute(llvm::Attribute::InReg); | |
| SRETAttrs.addAlignmentAttr(RetAI.getIndirectAlign().getQuantity()); | |
| } | |
| // Attach attributes to inalloca argument. | |
| if (IRFunctionArgs.hasInallocaArg()) { | |
| ArgAttrs[IRFunctionArgs.getInallocaArgNo()].addInAllocaAttr( | |
| FI.getArgStruct()); | |
| } | |
| // Apply `nonnull`, `dereferenceable(N)` and `align N` to the `this` argument, | |
| // unless this is a thunk function. Add dead_on_return to the `this` argument | |
| // in base class destructors to aid in DSE. | |
| // FIXME: fix this properly, https://reviews.llvm.org/D100388 | |
| if (FI.isInstanceMethod() && !IRFunctionArgs.hasInallocaArg() && | |
| !FI.arg_begin()->type->isVoidPointerType() && !IsThunk) { | |
| auto IRArgs = IRFunctionArgs.getIRArgs(0); | |
| assert(IRArgs.second == 1 && "Expected only a single `this` pointer."); | |
| llvm::AttrBuilder &Attrs = ArgAttrs[IRArgs.first]; | |
| QualType ThisTy = FI.arg_begin()->type.getTypePtr()->getPointeeType(); | |
| int64_t ThisSz = getMinimumObjectSize(ThisTy).getQuantity(); | |
| if (!CodeGenOpts.NullPointerIsValid && | |
| getTypes().getTargetAddressSpace(FI.arg_begin()->type) == 0) { | |
| Attrs.addAttribute(llvm::Attribute::NonNull); | |
| Attrs.addDereferenceableAttr(ThisSz); | |
| } else { | |
| // FIXME dereferenceable should be correct here, regardless of | |
| // NullPointerIsValid. However, dereferenceable currently does not always | |
| // respect NullPointerIsValid and may imply nonnull and break the program. | |
| // See https://reviews.llvm.org/D66618 for discussions. | |
| Attrs.addDereferenceableOrNullAttr(ThisSz); | |
| } | |
| llvm::Align Alignment = | |
| getNaturalTypeAlignment(ThisTy, /*BaseInfo=*/nullptr, | |
| /*TBAAInfo=*/nullptr, /*forPointeeType=*/true) | |
| .getAsAlign(); | |
| Attrs.addAlignmentAttr(Alignment); | |
| const auto *DD = dyn_cast_if_present<CXXDestructorDecl>( | |
| CalleeInfo.getCalleeDecl().getDecl()); | |
| // Do not annotate vector deleting destructors with dead_on_return as the | |
| // this pointer in that case points to an array which we cannot | |
| // statically know the size of. Also do not mark deleting destructors | |
| // dead_on_return as then we might delete stores inside of a user-defined | |
| // operator delete implementation if it gets inlined, which would be | |
| // incorrect as the object's lifetime has already ended and the operator | |
| // delete implementation is allowed to manipulate the underlying storage. | |
| if (DD && | |
| CalleeInfo.getCalleeDecl().getDtorType() != | |
| CXXDtorType::Dtor_VectorDeleting && | |
| CalleeInfo.getCalleeDecl().getDtorType() != | |
| CXXDtorType::Dtor_Deleting && | |
| CodeGenOpts.StrictLifetimes) { | |
| const CXXRecordDecl *ClassDecl = | |
| dyn_cast<CXXRecordDecl>(DD->getDeclContext()); | |
| // We cannot add dead_on_return if we have virtual base classes because | |
| // they will generally still be live after the base object destructor. | |
| if (ClassDecl->getNumVBases() == 0) | |
| Attrs.addDeadOnReturnAttr(llvm::DeadOnReturnInfo( | |
| Context.getASTRecordLayout(ClassDecl).getDataSize().getQuantity())); | |
| } | |
| } | |
| unsigned ArgNo = 0; | |
| for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(), E = FI.arg_end(); | |
| I != E; ++I, ++ArgNo) { | |
| QualType ParamType = I->type; | |
| const ABIArgInfo &AI = I->info; | |
| llvm::AttrBuilder Attrs(getLLVMContext()); | |
| // Add attribute for padding argument, if necessary. | |
| if (IRFunctionArgs.hasPaddingArg(ArgNo)) { | |
| if (AI.getPaddingInReg()) { | |
| ArgAttrs[IRFunctionArgs.getPaddingArgNo(ArgNo)].addAttribute( | |
| llvm::Attribute::InReg); | |
| } | |
| } | |
| // Decide whether the argument we're handling could be partially undef | |
| if (CodeGenOpts.EnableNoundefAttrs && | |
| DetermineNoUndef(ParamType, getTypes(), DL, AI)) { | |
| Attrs.addAttribute(llvm::Attribute::NoUndef); | |
| } | |
| // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we | |
| // have the corresponding parameter variable. It doesn't make | |
| // sense to do it here because parameters are so messed up. | |
| switch (AI.getKind()) { | |
| case ABIArgInfo::Extend: | |
| if (AI.isSignExt()) | |
| Attrs.addAttribute(llvm::Attribute::SExt); | |
| else if (AI.isZeroExt()) | |
| Attrs.addAttribute(llvm::Attribute::ZExt); | |
| else | |
| Attrs.addAttribute(llvm::Attribute::NoExt); | |
| [[fallthrough]]; | |
| case ABIArgInfo::TargetSpecific: | |
| case ABIArgInfo::Direct: | |
| if (ArgNo == 0 && FI.isChainCall()) | |
| Attrs.addAttribute(llvm::Attribute::Nest); | |
| else if (AI.getInReg()) | |
| Attrs.addAttribute(llvm::Attribute::InReg); | |
| Attrs.addStackAlignmentAttr(llvm::MaybeAlign(AI.getDirectAlign())); | |
| if (canApplyNoFPClass(AI, ParamType, false)) | |
| Attrs.addNoFPClassAttr( | |
| CodeGenUtils::getNoFPClassTestMask(getLangOpts())); | |
| break; | |
| case ABIArgInfo::Indirect: { | |
| assert(!ParamType->isIncompleteType() && | |
| "Pass-by-value parameter has incomplete definition?"); | |
| if (AI.getInReg()) | |
| Attrs.addAttribute(llvm::Attribute::InReg); | |
| // HLSL out and inout parameters must not be marked with ByVal or | |
| // DeadOnReturn attributes because stores to these parameters by the | |
| // callee are visible to the caller. | |
| if (auto ParamABI = FI.getExtParameterInfo(ArgNo).getABI(); | |
| ParamABI != ParameterABI::HLSLOut && | |
| ParamABI != ParameterABI::HLSLInOut) { | |
| // Depending on the ABI, this may be either a byval or a dead_on_return | |
| // argument. | |
| if (AI.getIndirectByVal()) { | |
| Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); | |
| } else { | |
| // Add dead_on_return when the object's lifetime ends in the callee. | |
| // This includes trivially-destructible objects, as well as objects | |
| // whose destruction / clean-up is carried out within the callee | |
| // (e.g., Obj-C ARC-managed structs, MSVC callee-destroyed objects). | |
| if (!ParamType.isDestructedType() || !ParamType->isRecordType() || | |
| ParamType->castAsRecordDecl()->isParamDestroyedInCallee()) | |
| Attrs.addDeadOnReturnAttr(llvm::DeadOnReturnInfo()); | |
| } | |
| } | |
| auto *Decl = ParamType->getAsRecordDecl(); | |
| if (CodeGenOpts.PassByValueIsNoAlias && Decl && | |
| Decl->getArgPassingRestrictions() == | |
| RecordArgPassingKind::CanPassInRegs) | |
| // When calling the function, the pointer passed in will be the only | |
| // reference to the underlying object. Mark it accordingly. | |
| Attrs.addAttribute(llvm::Attribute::NoAlias); | |
| // TODO: We could add the byref attribute if not byval, but it would | |
| // require updating many testcases. | |
| CharUnits Align = AI.getIndirectAlign(); | |
| // In a byval argument, it is important that the required | |
| // alignment of the type is honored, as LLVM might be creating a | |
| // *new* stack object, and needs to know what alignment to give | |
| // it. (Sometimes it can deduce a sensible alignment on its own, | |
| // but not if clang decides it must emit a packed struct, or the | |
| // user specifies increased alignment requirements.) | |
| // | |
| // This is different from indirect *not* byval, where an aligned copy is | |
| // already created by the caller, and the align attribute is purely | |
| // informative. However, this can still be useful information for | |
| // optimizations, such as giving us one necessary condition for checking | |
| // if a load to this pointer can be speculatively executed. | |
| assert(!Align.isZero()); | |
| Attrs.addAlignmentAttr(Align.getQuantity()); | |
| // The `nofree` and `dereferenceable` attributes can already be inferred | |
| // for `byval` arguments. We'll need to provide additional hints | |
| // otherwise. | |
| if (!AI.getIndirectByVal()) { | |
| // Both 6.9.1 of the C standard and [basic.stc.auto] of the C++ standard | |
| // require parameters to have automatic storage duration. Therefore, the | |
| // underlying object of this pointer will not be freed during the | |
| // function's execution. | |
| Attrs.addAttribute(llvm::Attribute::NoFreeObj); | |
| Attrs.addDereferenceableAttr( | |
| Context.getTypeSizeInChars(ParamType).getQuantity()); | |
| } | |
| // byval disables readnone and readonly. | |
| AddPotentialArgAccess(); | |
| break; | |
| } | |
| case ABIArgInfo::IndirectAliased: { | |
| CharUnits Align = AI.getIndirectAlign(); | |
| Attrs.addByRefAttr(getTypes().ConvertTypeForMem(ParamType)); | |
| Attrs.addAlignmentAttr(Align.getQuantity()); | |
| break; | |
| } | |
| case ABIArgInfo::Ignore: | |
| case ABIArgInfo::Expand: | |
| case ABIArgInfo::CoerceAndExpand: | |
| break; | |
| case ABIArgInfo::InAlloca: | |
| // inalloca disables readnone and readonly. | |
| AddPotentialArgAccess(); | |
| continue; | |
| } | |
| if (const auto *RefTy = ParamType->getAs<ReferenceType>()) { | |
| QualType PTy = RefTy->getPointeeType(); | |
| if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) | |
| Attrs.addDereferenceableAttr(getMinimumObjectSize(PTy).getQuantity()); | |
| if (getTypes().getTargetAddressSpace(PTy) == 0 && | |
| !CodeGenOpts.NullPointerIsValid) | |
| Attrs.addAttribute(llvm::Attribute::NonNull); | |
| if (PTy->isObjectType()) { | |
| llvm::Align Alignment = | |
| getNaturalPointeeTypeAlignment(ParamType).getAsAlign(); | |
| Attrs.addAlignmentAttr(Alignment); | |
| } | |
| } | |
| // From OpenCL spec v3.0.10 section 6.3.5 Alignment of Types: | |
| // > For arguments to a __kernel function declared to be a pointer to a | |
| // > data type, the OpenCL compiler can assume that the pointee is always | |
| // > appropriately aligned as required by the data type. | |
| if (TargetDecl && | |
| DeviceKernelAttr::isOpenCLSpelling( | |
| TargetDecl->getAttr<DeviceKernelAttr>()) && | |
| ParamType->isPointerType()) { | |
| QualType PTy = ParamType->getPointeeType(); | |
| if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) { | |
| llvm::Align Alignment = | |
| getNaturalPointeeTypeAlignment(ParamType).getAsAlign(); | |
| Attrs.addAlignmentAttr(Alignment); | |
| } | |
| } | |
| switch (FI.getExtParameterInfo(ArgNo).getABI()) { | |
| case ParameterABI::HLSLOut: | |
| case ParameterABI::HLSLInOut: | |
| Attrs.addAttribute(llvm::Attribute::NoAlias); | |
| break; | |
| case ParameterABI::Ordinary: | |
| break; | |
| case ParameterABI::SwiftIndirectResult: { | |
| // Add 'sret' if we haven't already used it for something, but | |
| // only if the result is void. | |
| if (!hasUsedSRet && RetTy->isVoidType()) { | |
| Attrs.addStructRetAttr(getTypes().ConvertTypeForMem(ParamType)); | |
| hasUsedSRet = true; | |
| } | |
| // Add 'noalias' in either case. | |
| Attrs.addAttribute(llvm::Attribute::NoAlias); | |
| // Add 'dereferenceable' and 'alignment'. | |
| auto PTy = ParamType->getPointeeType(); | |
| if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) { | |
| auto info = getContext().getTypeInfoInChars(PTy); | |
| Attrs.addDereferenceableAttr(info.Width.getQuantity()); | |
| Attrs.addAlignmentAttr(info.Align.getAsAlign()); | |
| } | |
| break; | |
| } | |
| case ParameterABI::SwiftErrorResult: | |
| Attrs.addAttribute(llvm::Attribute::SwiftError); | |
| break; | |
| case ParameterABI::SwiftContext: | |
| Attrs.addAttribute(llvm::Attribute::SwiftSelf); | |
| break; | |
| case ParameterABI::SwiftAsyncContext: | |
| Attrs.addAttribute(llvm::Attribute::SwiftAsync); | |
| break; | |
| } | |
| if (FI.getExtParameterInfo(ArgNo).isNoEscape()) | |
| Attrs.addCapturesAttr( | |
| llvm::CaptureInfo(llvm::CaptureComponents::Address)); | |
| if (Attrs.hasAttributes()) { | |
| unsigned FirstIRArg, NumIRArgs; | |
| std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); | |
| for (unsigned i = 0; i < NumIRArgs; i++) | |
| ArgAttrs[FirstIRArg + i].merge(Attrs); | |
| } | |
| } | |
| assert(ArgNo == FI.arg_size()); | |
| // We can't see all potential arguments in a varargs declaration; treat them | |
| // as if they can access memory. | |
| if (!AttrOnCallSite && FI.isVariadic()) | |
| AddPotentialArgAccess(); | |
| ArgNo = 0; | |
| if (AddedPotentialArgAccess && MemAttrForPtrArgs) { | |
| llvm::FunctionType *FunctionType = getTypes().GetFunctionType(FI); | |
| for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(), | |
| E = FI.arg_end(); | |
| I != E; ++I, ++ArgNo) { | |
| if (I->info.isDirect() || I->info.isExpand() || | |
| I->info.isCoerceAndExpand()) { | |
| unsigned FirstIRArg, NumIRArgs; | |
| std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); | |
| for (unsigned i = FirstIRArg; i < FirstIRArg + NumIRArgs; ++i) { | |
| // The index may be out-of-bounds if the callee is a varargs | |
| // function. | |
| // | |
| // FIXME: We can compute the types of varargs arguments without going | |
| // through the function type, but the relevant code isn't exposed | |
| // in a way that can be called from here. | |
| if (i < FunctionType->getNumParams() && | |
| FunctionType->getParamType(i)->isPointerTy()) { | |
| ArgAttrs[i].addAttribute(*MemAttrForPtrArgs); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| SmallVector<llvm::AttributeSet, 4> ArgAttrSets; | |
| for (const llvm::AttrBuilder &Attrs : ArgAttrs) | |
| ArgAttrSets.push_back(llvm::AttributeSet::get(getLLVMContext(), Attrs)); | |
| AttrList = llvm::AttributeList::get( | |
| getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), FuncAttrs), | |
| llvm::AttributeSet::get(getLLVMContext(), RetAttrs), ArgAttrSets); | |
| } | |
| /// An argument came in as a promoted argument; demote it back to its | |
| /// declared type. | |
| static llvm::Value *emitArgumentDemotion(CodeGenFunction &CGF, | |
| const VarDecl *var, | |
| llvm::Value *value) { | |
| llvm::Type *varType = CGF.ConvertType(var->getType()); | |
| // This can happen with promotions that actually don't change the | |
| // underlying type, like the enum promotions. | |
| if (value->getType() == varType) | |
| return value; | |
| assert((varType->isIntegerTy() || varType->isFloatingPointTy()) && | |
| "unexpected promotion type"); | |
| if (isa<llvm::IntegerType>(varType)) | |
| return CGF.Builder.CreateTrunc(value, varType, "arg.unpromote"); | |
| return CGF.Builder.CreateFPCast(value, varType, "arg.unpromote"); | |
| } | |
| /// Returns the attribute (either parameter attribute, or function | |
| /// attribute), which declares argument ArgNo to be non-null. | |
| static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD, | |
| QualType ArgType, unsigned ArgNo) { | |
| // FIXME: __attribute__((nonnull)) can also be applied to: | |
| // - references to pointers, where the pointee is known to be | |
| // nonnull (apparently a Clang extension) | |
| // - transparent unions containing pointers | |
| // In the former case, LLVM IR cannot represent the constraint. In | |
| // the latter case, we have no guarantee that the transparent union | |
| // is in fact passed as a pointer. | |
| if (!ArgType->isAnyPointerType() && !ArgType->isBlockPointerType()) | |
| return nullptr; | |
| // First, check attribute on parameter itself. | |
| if (PVD) { | |
| if (auto ParmNNAttr = PVD->getAttr<NonNullAttr>()) | |
| return ParmNNAttr; | |
| } | |
| // Check function attributes. | |
| if (!FD) | |
| return nullptr; | |
| for (const auto *NNAttr : FD->specific_attrs<NonNullAttr>()) { | |
| if (NNAttr->isNonNull(ArgNo)) | |
| return NNAttr; | |
| } | |
| return nullptr; | |
| } | |
| namespace { | |
| struct CopyBackSwiftError final : EHScopeStack::Cleanup { | |
| Address Temp; | |
| Address Arg; | |
| CopyBackSwiftError(Address temp, Address arg) : Temp(temp), Arg(arg) {} | |
| void Emit(CodeGenFunction &CGF, Flags flags) override { | |
| llvm::Value *errorValue = CGF.Builder.CreateLoad(Temp); | |
| CGF.Builder.CreateStore(errorValue, Arg); | |
| } | |
| }; | |
| } // namespace | |
| void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, | |
| llvm::Function *Fn, | |
| const FunctionArgList &Args) { | |
| if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) | |
| // Naked functions don't have prologues. | |
| return; | |
| // 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>(CurCodeDecl)) { | |
| if (FD->hasImplicitReturnZero()) { | |
| QualType RetTy = FD->getReturnType().getUnqualifiedType(); | |
| 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. | |
| ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), FI); | |
| assert(Fn->arg_size() == IRFunctionArgs.totalIRArgs()); | |
| // If we're using inalloca, all the memory arguments are GEPs off of the last | |
| // parameter, which is a pointer to the complete memory area. | |
| Address ArgStruct = Address::invalid(); | |
| if (IRFunctionArgs.hasInallocaArg()) | |
| ArgStruct = Address(Fn->getArg(IRFunctionArgs.getInallocaArgNo()), | |
| FI.getArgStruct(), FI.getArgStructAlignment()); | |
| // Name the struct return parameter. | |
| if (IRFunctionArgs.hasSRetArg()) { | |
| auto AI = Fn->getArg(IRFunctionArgs.getSRetArgNo()); | |
| AI->setName("agg.result"); | |
| AI->addAttr(llvm::Attribute::NoAlias); | |
| } | |
| // Track if we received the parameter as a pointer (indirect, byval, or | |
| // inalloca). If already have a pointer, EmitParmDecl doesn't need to copy it | |
| // into a local alloca for us. | |
| SmallVector<ParamValue, 16> ArgVals; | |
| ArgVals.reserve(Args.size()); | |
| // Create a pointer value for every parameter declaration. This usually | |
| // entails copying one or more LLVM IR arguments into an alloca. Don't push | |
| // any cleanups or do anything that might unwind. We do that separately, so | |
| // we can push the cleanups in the correct order for the ABI. | |
| assert(FI.arg_size() == Args.size() && | |
| "Mismatch between function signature & arguments."); | |
| unsigned ArgNo = 0; | |
| CGFunctionInfo::const_arg_iterator info_it = FI.arg_begin(); | |
| for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; | |
| ++i, ++info_it, ++ArgNo) { | |
| const VarDecl *Arg = *i; | |
| const ABIArgInfo &ArgI = info_it->info; | |
| bool isPromoted = | |
| isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted(); | |
| // We are converting from ABIArgInfo type to VarDecl type directly, unless | |
| // the parameter is promoted. In this case we convert to | |
| // CGFunctionInfo::ArgInfo type with subsequent argument demotion. | |
| QualType Ty = isPromoted ? info_it->type : Arg->getType(); | |
| assert(hasScalarEvaluationKind(Ty) == | |
| hasScalarEvaluationKind(Arg->getType())); | |
| unsigned FirstIRArg, NumIRArgs; | |
| std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); | |
| switch (ArgI.getKind()) { | |
| case ABIArgInfo::InAlloca: { | |
| assert(NumIRArgs == 0); | |
| auto FieldIndex = ArgI.getInAllocaFieldIndex(); | |
| Address V = | |
| Builder.CreateStructGEP(ArgStruct, FieldIndex, Arg->getName()); | |
| if (ArgI.getInAllocaIndirect()) | |
| V = Address(Builder.CreateLoad(V), ConvertTypeForMem(Ty), | |
| getContext().getTypeAlignInChars(Ty)); | |
| ArgVals.push_back(ParamValue::forIndirect(V)); | |
| break; | |
| } | |
| case ABIArgInfo::Indirect: | |
| case ABIArgInfo::IndirectAliased: { | |
| assert(NumIRArgs == 1); | |
| Address ParamAddr = makeNaturalAddressForPointer( | |
| Fn->getArg(FirstIRArg), Ty, ArgI.getIndirectAlign(), false, nullptr, | |
| nullptr, KnownNonNull); | |
| if (!hasScalarEvaluationKind(Ty)) { | |
| // Aggregates and complex variables are accessed by reference. All we | |
| // need to do is realign the value, if requested. Also, if the address | |
| // may be aliased, copy it to ensure that the parameter variable is | |
| // mutable and has a unique adress, as C requires. | |
| if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) { | |
| RawAddress AlignedTemp = CreateMemTempWithoutCast(Ty, "coerce"); | |
| // Copy from the incoming argument pointer to the temporary with the | |
| // appropriate alignment. | |
| // | |
| // FIXME: We should have a common utility for generating an aggregate | |
| // copy. | |
| CharUnits Size = getContext().getTypeSizeInChars(Ty); | |
| Builder.CreateMemCpy( | |
| AlignedTemp.getPointer(), AlignedTemp.getAlignment().getAsAlign(), | |
| ParamAddr.emitRawPointer(*this), | |
| ParamAddr.getAlignment().getAsAlign(), | |
| llvm::ConstantInt::get(IntPtrTy, Size.getQuantity())); | |
| ParamAddr = AlignedTemp; | |
| } | |
| ArgVals.push_back(ParamValue::forIndirect(ParamAddr)); | |
| } else { | |
| // Load scalar value from indirect argument. | |
| llvm::Value *V = | |
| EmitLoadOfScalar(ParamAddr, false, Ty, Arg->getBeginLoc()); | |
| if (isPromoted) | |
| V = emitArgumentDemotion(*this, Arg, V); | |
| ArgVals.push_back(ParamValue::forDirect(V)); | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::Extend: | |
| case ABIArgInfo::Direct: { | |
| auto AI = Fn->getArg(FirstIRArg); | |
| llvm::Type *LTy = ConvertType(Arg->getType()); | |
| // Prepare parameter attributes. So far, only attributes for pointer | |
| // parameters are prepared. See | |
| // http://llvm.org/docs/LangRef.html#paramattrs. | |
| if (ArgI.getDirectOffset() == 0 && LTy->isPointerTy() && | |
| ArgI.getCoerceToType()->isPointerTy()) { | |
| assert(NumIRArgs == 1); | |
| if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) { | |
| // Set `nonnull` attribute if any. | |
| if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(), | |
| PVD->getFunctionScopeIndex()) && | |
| !CGM.getCodeGenOpts().NullPointerIsValid) | |
| AI->addAttr(llvm::Attribute::NonNull); | |
| QualType OTy = PVD->getOriginalType(); | |
| if (const auto *ArrTy = getContext().getAsConstantArrayType(OTy)) { | |
| // A C99 array parameter declaration with the static keyword also | |
| // indicates dereferenceability, and if the size is constant we can | |
| // use the dereferenceable attribute (which requires the size in | |
| // bytes). | |
| if (ArrTy->getSizeModifier() == ArraySizeModifier::Static) { | |
| QualType ETy = ArrTy->getElementType(); | |
| llvm::Align Alignment = | |
| CGM.getNaturalTypeAlignment(ETy).getAsAlign(); | |
| AI->addAttrs(llvm::AttrBuilder(getLLVMContext()) | |
| .addAlignmentAttr(Alignment)); | |
| uint64_t ArrSize = ArrTy->getZExtSize(); | |
| if (!ETy->isIncompleteType() && ETy->isConstantSizeType() && | |
| ArrSize) { | |
| llvm::AttrBuilder Attrs(getLLVMContext()); | |
| Attrs.addDereferenceableAttr( | |
| getContext().getTypeSizeInChars(ETy).getQuantity() * | |
| ArrSize); | |
| AI->addAttrs(Attrs); | |
| } else if (getContext().getTargetInfo().getNullPointerValue( | |
| ETy.getAddressSpace()) == 0 && | |
| !CGM.getCodeGenOpts().NullPointerIsValid) { | |
| AI->addAttr(llvm::Attribute::NonNull); | |
| } | |
| } | |
| } else if (const auto *ArrTy = | |
| getContext().getAsVariableArrayType(OTy)) { | |
| // For C99 VLAs with the static keyword, we don't know the size so | |
| // we can't use the dereferenceable attribute, but in addrspace(0) | |
| // we know that it must be nonnull. | |
| if (ArrTy->getSizeModifier() == ArraySizeModifier::Static) { | |
| QualType ETy = ArrTy->getElementType(); | |
| llvm::Align Alignment = | |
| CGM.getNaturalTypeAlignment(ETy).getAsAlign(); | |
| AI->addAttrs(llvm::AttrBuilder(getLLVMContext()) | |
| .addAlignmentAttr(Alignment)); | |
| if (!getTypes().getTargetAddressSpace(ETy) && | |
| !CGM.getCodeGenOpts().NullPointerIsValid) | |
| AI->addAttr(llvm::Attribute::NonNull); | |
| } | |
| } | |
| // Set `align` attribute if any. | |
| const auto *AVAttr = PVD->getAttr<AlignValueAttr>(); | |
| if (!AVAttr) | |
| if (const auto *TOTy = OTy->getAs<TypedefType>()) | |
| AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>(); | |
| if (AVAttr && !SanOpts.has(SanitizerKind::Alignment)) { | |
| // If alignment-assumption sanitizer is enabled, we do *not* add | |
| // alignment attribute here, but emit normal alignment assumption, | |
| // so the UBSAN check could function. | |
| llvm::ConstantInt *AlignmentCI = | |
| cast<llvm::ConstantInt>(EmitScalarExpr(AVAttr->getAlignment())); | |
| uint64_t AlignmentInt = | |
| AlignmentCI->getLimitedValue(llvm::Value::MaximumAlignment); | |
| if (AI->getParamAlign().valueOrOne() < AlignmentInt) { | |
| AI->removeAttr(llvm::Attribute::AttrKind::Alignment); | |
| AI->addAttrs(llvm::AttrBuilder(getLLVMContext()) | |
| .addAlignmentAttr(llvm::Align(AlignmentInt))); | |
| } | |
| } | |
| } | |
| // Set 'noalias' if an argument type has the `restrict` qualifier. | |
| if (Arg->getType().isRestrictQualified()) | |
| AI->addAttr(llvm::Attribute::NoAlias); | |
| } | |
| // Prepare the argument value. If we have the trivial case, handle it | |
| // with no muss and fuss. | |
| if (!isa<llvm::StructType>(ArgI.getCoerceToType()) && | |
| ArgI.getCoerceToType() == ConvertType(Ty) && | |
| ArgI.getDirectOffset() == 0) { | |
| assert(NumIRArgs == 1); | |
| // LLVM expects swifterror parameters to be used in very restricted | |
| // ways. Copy the value into a less-restricted temporary. | |
| llvm::Value *V = AI; | |
| if (FI.getExtParameterInfo(ArgNo).getABI() == | |
| ParameterABI::SwiftErrorResult) { | |
| QualType pointeeTy = Ty->getPointeeType(); | |
| assert(pointeeTy->isPointerType()); | |
| RawAddress temp = CreateMemTempWithoutCast( | |
| pointeeTy, getPointerAlign(), "swifterror.temp"); | |
| Address arg = makeNaturalAddressForPointer( | |
| V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); | |
| llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); | |
| Builder.CreateStore(incomingErrorValue, temp); | |
| V = temp.getPointer(); | |
| // Push a cleanup to copy the value back at the end of the function. | |
| // The convention does not guarantee that the value will be written | |
| // back if the function exits with an unwind exception. | |
| EHStack.pushCleanup<CopyBackSwiftError>(NormalCleanup, temp, arg); | |
| } | |
| // Ensure the argument is the correct type. | |
| if (V->getType() != ArgI.getCoerceToType()) | |
| V = Builder.CreateBitCast(V, ArgI.getCoerceToType()); | |
| if (isPromoted) | |
| V = emitArgumentDemotion(*this, Arg, V); | |
| // Because of merging of function types from multiple decls it is | |
| // possible for the type of an argument to not match the corresponding | |
| // type in the function type. Since we are codegening the callee | |
| // in here, add a cast to the argument type. | |
| llvm::Type *LTy = ConvertType(Arg->getType()); | |
| if (V->getType() != LTy) | |
| V = Builder.CreateBitCast(V, LTy); | |
| ArgVals.push_back(ParamValue::forDirect(V)); | |
| break; | |
| } | |
| // VLST arguments are coerced to VLATs at the function boundary for | |
| // ABI consistency. If this is a VLST that was coerced to | |
| // a VLAT at the function boundary and the types match up, use | |
| // llvm.vector.extract to convert back to the original VLST. | |
| if (auto *VecTyTo = dyn_cast<llvm::FixedVectorType>(ConvertType(Ty))) { | |
| llvm::Value *ArgVal = Fn->getArg(FirstIRArg); | |
| if (auto *VecTyFrom = | |
| dyn_cast<llvm::ScalableVectorType>(ArgVal->getType())) { | |
| auto [Coerced, Extracted] = CoerceScalableToFixed( | |
| *this, VecTyTo, VecTyFrom, ArgVal, Arg->getName()); | |
| if (Extracted) { | |
| assert(NumIRArgs == 1); | |
| ArgVals.push_back(ParamValue::forDirect(Coerced)); | |
| break; | |
| } | |
| } | |
| } | |
| llvm::StructType *STy = | |
| dyn_cast<llvm::StructType>(ArgI.getCoerceToType()); | |
| Address Alloca = CreateMemTempWithoutCast( | |
| Ty, getContext().getDeclAlign(Arg), Arg->getName()); | |
| // Pointer to store into. | |
| Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI); | |
| // Fast-isel and the optimizer generally like scalar values better than | |
| // FCAs, so we flatten them if this is safe to do for this argument. | |
| if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy && | |
| STy->getNumElements() > 1) { | |
| llvm::TypeSize StructSize = CGM.getDataLayout().getTypeAllocSize(STy); | |
| llvm::TypeSize PtrElementSize = | |
| CGM.getDataLayout().getTypeAllocSize(Ptr.getElementType()); | |
| if (StructSize.isScalable()) { | |
| assert(STy->containsHomogeneousScalableVectorTypes() && | |
| "ABI only supports structure with homogeneous scalable vector " | |
| "type"); | |
| assert(StructSize == PtrElementSize && | |
| "Only allow non-fractional movement of structure with" | |
| "homogeneous scalable vector type"); | |
| assert(STy->getNumElements() == NumIRArgs); | |
| llvm::Value *LoadedStructValue = llvm::PoisonValue::get(STy); | |
| for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { | |
| auto *AI = Fn->getArg(FirstIRArg + i); | |
| AI->setName(Arg->getName() + ".coerce" + Twine(i)); | |
| LoadedStructValue = | |
| Builder.CreateInsertValue(LoadedStructValue, AI, i); | |
| } | |
| Builder.CreateStore(LoadedStructValue, Ptr); | |
| } else { | |
| uint64_t SrcSize = StructSize.getFixedValue(); | |
| uint64_t DstSize = PtrElementSize.getFixedValue(); | |
| Address AddrToStoreInto = Address::invalid(); | |
| if (SrcSize <= DstSize) { | |
| AddrToStoreInto = Ptr.withElementType(STy); | |
| } else { | |
| AddrToStoreInto = | |
| CreateTempAlloca(STy, Alloca.getAlignment(), "coerce"); | |
| } | |
| assert(STy->getNumElements() == NumIRArgs); | |
| for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { | |
| auto AI = Fn->getArg(FirstIRArg + i); | |
| AI->setName(Arg->getName() + ".coerce" + Twine(i)); | |
| Address EltPtr = Builder.CreateStructGEP(AddrToStoreInto, i); | |
| Builder.CreateStore(AI, EltPtr); | |
| } | |
| if (SrcSize > DstSize) { | |
| Builder.CreateMemCpy(Ptr, AddrToStoreInto, DstSize); | |
| } | |
| // Structures with PFP fields require a coerced store to add any | |
| // pointer signatures. | |
| if (getContext().hasPFPFields(Ty)) { | |
| llvm::Value *Struct = Builder.CreateLoad(Ptr); | |
| CreatePFPCoercedStore(Struct, Ty, Ptr, *this); | |
| } | |
| } | |
| } else { | |
| // Simple case, just do a coerced store of the argument into the alloca. | |
| assert(NumIRArgs == 1); | |
| auto AI = Fn->getArg(FirstIRArg); | |
| AI->setName(Arg->getName() + ".coerce"); | |
| CreateCoercedStore( | |
| AI, Ty, Ptr, | |
| llvm::TypeSize::getFixed( | |
| getContext().getTypeSizeInChars(Ty).getQuantity() - | |
| ArgI.getDirectOffset()), | |
| /*DstIsVolatile=*/false); | |
| } | |
| // Match to what EmitParmDecl is expecting for this type. | |
| if (CodeGenFunction::hasScalarEvaluationKind(Ty)) { | |
| llvm::Value *V = | |
| EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc()); | |
| if (isPromoted) | |
| V = emitArgumentDemotion(*this, Arg, V); | |
| ArgVals.push_back(ParamValue::forDirect(V)); | |
| } else { | |
| ArgVals.push_back(ParamValue::forIndirect(Alloca)); | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::CoerceAndExpand: { | |
| // Reconstruct into a temporary. | |
| Address alloca = | |
| CreateMemTempWithoutCast(Ty, getContext().getDeclAlign(Arg)); | |
| ArgVals.push_back(ParamValue::forIndirect(alloca)); | |
| auto coercionType = ArgI.getCoerceAndExpandType(); | |
| auto unpaddedCoercionType = ArgI.getUnpaddedCoerceAndExpandType(); | |
| auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType); | |
| alloca = alloca.withElementType(coercionType); | |
| unsigned argIndex = FirstIRArg; | |
| unsigned unpaddedIndex = 0; | |
| for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { | |
| llvm::Type *eltType = coercionType->getElementType(i); | |
| if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) | |
| continue; | |
| auto eltAddr = Builder.CreateStructGEP(alloca, i); | |
| llvm::Value *elt = Fn->getArg(argIndex++); | |
| auto paramType = unpaddedStruct | |
| ? unpaddedStruct->getElementType(unpaddedIndex++) | |
| : unpaddedCoercionType; | |
| if (auto *VecTyTo = dyn_cast<llvm::FixedVectorType>(eltType)) { | |
| if (auto *VecTyFrom = dyn_cast<llvm::ScalableVectorType>(paramType)) { | |
| bool Extracted; | |
| std::tie(elt, Extracted) = CoerceScalableToFixed( | |
| *this, VecTyTo, VecTyFrom, elt, elt->getName()); | |
| assert(Extracted && "Unexpected scalable to fixed vector coercion"); | |
| } | |
| } | |
| Builder.CreateStore(elt, eltAddr); | |
| } | |
| assert(argIndex == FirstIRArg + NumIRArgs); | |
| 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. | |
| Address Alloca = | |
| CreateMemTempWithoutCast(Ty, getContext().getDeclAlign(Arg)); | |
| LValue LV = MakeAddrLValue(Alloca, Ty); | |
| ArgVals.push_back(ParamValue::forIndirect(Alloca)); | |
| auto FnArgIter = Fn->arg_begin() + FirstIRArg; | |
| ExpandTypeFromArgs(Ty, LV, FnArgIter); | |
| assert(FnArgIter == Fn->arg_begin() + FirstIRArg + NumIRArgs); | |
| for (unsigned i = 0, e = NumIRArgs; i != e; ++i) { | |
| auto AI = Fn->getArg(FirstIRArg + i); | |
| AI->setName(Arg->getName() + "." + Twine(i)); | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::TargetSpecific: { | |
| auto *AI = Fn->getArg(FirstIRArg); | |
| AI->setName(Arg->getName() + ".target_coerce"); | |
| Address Alloca = CreateMemTempWithoutCast( | |
| Ty, getContext().getDeclAlign(Arg), Arg->getName()); | |
| Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI); | |
| CGM.getABIInfo().createCoercedStore(AI, Ptr, ArgI, false, *this); | |
| if (CodeGenFunction::hasScalarEvaluationKind(Ty)) { | |
| llvm::Value *V = | |
| EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc()); | |
| if (isPromoted) { | |
| V = emitArgumentDemotion(*this, Arg, V); | |
| } | |
| ArgVals.push_back(ParamValue::forDirect(V)); | |
| } else { | |
| ArgVals.push_back(ParamValue::forIndirect(Alloca)); | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::Ignore: | |
| assert(NumIRArgs == 0); | |
| // Initialize the local variable appropriately. | |
| if (!hasScalarEvaluationKind(Ty)) { | |
| ArgVals.push_back( | |
| ParamValue::forIndirect(CreateMemTempWithoutCast(Ty))); | |
| } else { | |
| llvm::Value *U = llvm::UndefValue::get(ConvertType(Arg->getType())); | |
| ArgVals.push_back(ParamValue::forDirect(U)); | |
| } | |
| break; | |
| } | |
| } | |
| if (getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { | |
| for (int I = Args.size() - 1; I >= 0; --I) | |
| EmitParmDecl(*Args[I], ArgVals[I], I + 1); | |
| } else { | |
| for (unsigned I = 0, E = Args.size(); I != E; ++I) | |
| EmitParmDecl(*Args[I], ArgVals[I], I + 1); | |
| } | |
| } | |
| static void eraseUnusedBitCasts(llvm::Instruction *insn) { | |
| while (insn->use_empty()) { | |
| llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(insn); | |
| if (!bitcast) | |
| return; | |
| // This is "safe" because we would have used a ConstantExpr otherwise. | |
| insn = cast<llvm::Instruction>(bitcast->getOperand(0)); | |
| bitcast->eraseFromParent(); | |
| } | |
| } | |
| /// Try to emit a fused autorelease of a return result. | |
| static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF, | |
| llvm::Value *result) { | |
| // We must be immediately followed the cast. | |
| llvm::BasicBlock *BB = CGF.Builder.GetInsertBlock(); | |
| if (BB->empty()) | |
| return nullptr; | |
| if (&BB->back() != result) | |
| return nullptr; | |
| llvm::Type *resultType = result->getType(); | |
| // result is in a BasicBlock and is therefore an Instruction. | |
| llvm::Instruction *generator = cast<llvm::Instruction>(result); | |
| SmallVector<llvm::Instruction *, 4> InstsToKill; | |
| // Look for: | |
| // %generator = bitcast %type1* %generator2 to %type2* | |
| while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(generator)) { | |
| // We would have emitted this as a constant if the operand weren't | |
| // an Instruction. | |
| generator = cast<llvm::Instruction>(bitcast->getOperand(0)); | |
| // Require the generator to be immediately followed by the cast. | |
| if (generator->getNextNode() != bitcast) | |
| return nullptr; | |
| InstsToKill.push_back(bitcast); | |
| } | |
| // Look for: | |
| // %generator = call i8* @objc_retain(i8* %originalResult) | |
| // or | |
| // %generator = call i8* @objc_retainAutoreleasedReturnValue(i8* %originalResult) | |
| llvm::CallInst *call = dyn_cast<llvm::CallInst>(generator); | |
| if (!call) | |
| return nullptr; | |
| bool doRetainAutorelease; | |
| if (call->getCalledOperand() == CGF.CGM.getObjCEntrypoints().objc_retain) { | |
| doRetainAutorelease = true; | |
| } else if (call->getCalledOperand() == | |
| CGF.CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue) { | |
| doRetainAutorelease = false; | |
| // If we emitted an assembly marker for this call (and the | |
| // ARCEntrypoints field should have been set if so), go looking | |
| // for that call. If we can't find it, we can't do this | |
| // optimization. But it should always be the immediately previous | |
| // instruction, unless we needed bitcasts around the call. | |
| if (CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker) { | |
| llvm::Instruction *prev = call->getPrevNode(); | |
| assert(prev); | |
| if (isa<llvm::BitCastInst>(prev)) { | |
| prev = prev->getPrevNode(); | |
| assert(prev); | |
| } | |
| assert(isa<llvm::CallInst>(prev)); | |
| assert(cast<llvm::CallInst>(prev)->getCalledOperand() == | |
| CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker); | |
| InstsToKill.push_back(prev); | |
| } | |
| } else { | |
| return nullptr; | |
| } | |
| result = call->getArgOperand(0); | |
| InstsToKill.push_back(call); | |
| // Keep killing bitcasts, for sanity. Note that we no longer care | |
| // about precise ordering as long as there's exactly one use. | |
| while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) { | |
| if (!bitcast->hasOneUse()) | |
| break; | |
| InstsToKill.push_back(bitcast); | |
| result = bitcast->getOperand(0); | |
| } | |
| // Delete all the unnecessary instructions, from latest to earliest. | |
| for (auto *I : InstsToKill) | |
| I->eraseFromParent(); | |
| // Do the fused retain/autorelease if we were asked to. | |
| if (doRetainAutorelease) | |
| result = CGF.EmitARCRetainAutoreleaseReturnValue(result); | |
| // Cast back to the result type. | |
| return CGF.Builder.CreateBitCast(result, resultType); | |
| } | |
| /// If this is a +1 of the value of an immutable 'self', remove it. | |
| static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, | |
| llvm::Value *result) { | |
| // This is only applicable to a method with an immutable 'self'. | |
| const ObjCMethodDecl *method = | |
| dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl); | |
| if (!method) | |
| return nullptr; | |
| const VarDecl *self = method->getSelfDecl(); | |
| if (!self->getType().isConstQualified()) | |
| return nullptr; | |
| // Look for a retain call. Note: stripPointerCasts looks through returned arg | |
| // functions, which would cause us to miss the retain. | |
| llvm::CallInst *retainCall = dyn_cast<llvm::CallInst>(result); | |
| if (!retainCall || retainCall->getCalledOperand() != | |
| CGF.CGM.getObjCEntrypoints().objc_retain) | |
| return nullptr; | |
| // Look for an ordinary load of 'self'. | |
| llvm::Value *retainedValue = retainCall->getArgOperand(0); | |
| llvm::LoadInst *load = | |
| dyn_cast<llvm::LoadInst>(retainedValue->stripPointerCasts()); | |
| if (!load || load->isAtomic() || load->isVolatile() || | |
| load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) | |
| return nullptr; | |
| // Okay! Burn it all down. This relies for correctness on the | |
| // assumption that the retain is emitted as part of the return and | |
| // that thereafter everything is used "linearly". | |
| llvm::Type *resultType = result->getType(); | |
| eraseUnusedBitCasts(cast<llvm::Instruction>(result)); | |
| assert(retainCall->use_empty()); | |
| retainCall->eraseFromParent(); | |
| eraseUnusedBitCasts(cast<llvm::Instruction>(retainedValue)); | |
| return CGF.Builder.CreateBitCast(load, resultType); | |
| } | |
| /// Emit an ARC autorelease of the result of a function. | |
| /// | |
| /// \return the value to actually return from the function | |
| static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, | |
| llvm::Value *result) { | |
| // If we're returning 'self', kill the initial retain. This is a | |
| // heuristic attempt to "encourage correctness" in the really unfortunate | |
| // case where we have a return of self during a dealloc and we desperately | |
| // need to avoid the possible autorelease. | |
| if (llvm::Value *self = tryRemoveRetainOfSelf(CGF, result)) | |
| return self; | |
| // At -O0, try to emit a fused retain/autorelease. | |
| if (CGF.shouldUseFusedARCCalls()) | |
| if (llvm::Value *fused = tryEmitFusedAutoreleaseOfResult(CGF, result)) | |
| return fused; | |
| return CGF.EmitARCAutoreleaseReturnValue(result); | |
| } | |
| /// Heuristically search for a dominating store to the return-value slot. | |
| static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { | |
| llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); | |
| // Check if a User is a store which pointerOperand is the ReturnValue. | |
| // We are looking for stores to the ReturnValue, not for stores of the | |
| // ReturnValue to some other location. | |
| auto GetStoreIfValid = [&CGF, | |
| ReturnValuePtr](llvm::User *U) -> llvm::StoreInst * { | |
| auto *SI = dyn_cast<llvm::StoreInst>(U); | |
| if (!SI || SI->getPointerOperand() != ReturnValuePtr || | |
| SI->getValueOperand()->getType() != CGF.ReturnValue.getElementType()) | |
| return nullptr; | |
| // These aren't actually possible for non-coerced returns, and we | |
| // only care about non-coerced returns on this code path. | |
| // All memory instructions inside __try block are volatile. | |
| assert(!SI->isAtomic() && | |
| (!SI->isVolatile() || CGF.currentFunctionUsesSEHTry())); | |
| return SI; | |
| }; | |
| // If there are multiple uses of the return-value slot, just check | |
| // for something immediately preceding the IP. Sometimes this can | |
| // happen with how we generate implicit-returns; it can also happen | |
| // with noreturn cleanups. | |
| if (!ReturnValuePtr->hasOneUse()) { | |
| llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); | |
| if (IP->empty()) | |
| return nullptr; | |
| // Look at directly preceding instruction, skipping bitcasts, lifetime | |
| // markers, and fake uses and their operands. | |
| const llvm::Instruction *LoadIntoFakeUse = nullptr; | |
| for (llvm::Instruction &I : llvm::reverse(*IP)) { | |
| // Ignore instructions that are just loads for fake uses; the load should | |
| // immediately precede the fake use, so we only need to remember the | |
| // operand for the last fake use seen. | |
| if (LoadIntoFakeUse == &I) | |
| continue; | |
| if (isa<llvm::BitCastInst>(&I)) | |
| continue; | |
| if (auto *II = dyn_cast<llvm::IntrinsicInst>(&I)) { | |
| if (II->getIntrinsicID() == llvm::Intrinsic::lifetime_end) | |
| continue; | |
| if (II->getIntrinsicID() == llvm::Intrinsic::fake_use) { | |
| LoadIntoFakeUse = dyn_cast<llvm::Instruction>(II->getArgOperand(0)); | |
| continue; | |
| } | |
| } | |
| return GetStoreIfValid(&I); | |
| } | |
| return nullptr; | |
| } | |
| llvm::StoreInst *store = GetStoreIfValid(ReturnValuePtr->user_back()); | |
| if (!store) | |
| return nullptr; | |
| // Now do a first-and-dirty dominance check: just walk up the | |
| // single-predecessors chain from the current insertion point. | |
| llvm::BasicBlock *StoreBB = store->getParent(); | |
| llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); | |
| llvm::SmallPtrSet<llvm::BasicBlock *, 4> SeenBBs; | |
| while (IP != StoreBB) { | |
| if (!SeenBBs.insert(IP).second || !(IP = IP->getSinglePredecessor())) | |
| return nullptr; | |
| } | |
| // Okay, the store's basic block dominates the insertion point; we | |
| // can do our thing. | |
| return store; | |
| } | |
| // Helper functions for EmitCMSEClearRecord | |
| // Set the bits corresponding to a field having width `BitWidth` and located at | |
| // offset `BitOffset` (from the least significant bit) within a storage unit of | |
| // `Bits.size()` bytes. Each element of `Bits` corresponds to one target byte. | |
| // Use little-endian layout, i.e.`Bits[0]` is the LSB. | |
| static void setBitRange(SmallVectorImpl<uint64_t> &Bits, int BitOffset, | |
| int BitWidth, int CharWidth) { | |
| assert(CharWidth <= 64); | |
| assert(static_cast<unsigned>(BitWidth) <= Bits.size() * CharWidth); | |
| int Pos = 0; | |
| if (BitOffset >= CharWidth) { | |
| Pos += BitOffset / CharWidth; | |
| BitOffset = BitOffset % CharWidth; | |
| } | |
| const uint64_t Used = (uint64_t(1) << CharWidth) - 1; | |
| if (BitOffset + BitWidth >= CharWidth) { | |
| Bits[Pos++] |= (Used << BitOffset) & Used; | |
| BitWidth -= CharWidth - BitOffset; | |
| BitOffset = 0; | |
| } | |
| while (BitWidth >= CharWidth) { | |
| Bits[Pos++] = Used; | |
| BitWidth -= CharWidth; | |
| } | |
| if (BitWidth > 0) | |
| Bits[Pos++] |= (Used >> (CharWidth - BitWidth)) << BitOffset; | |
| } | |
| // Set the bits corresponding to a field having width `BitWidth` and located at | |
| // offset `BitOffset` (from the least significant bit) within a storage unit of | |
| // `StorageSize` bytes, located at `StorageOffset` in `Bits`. Each element of | |
| // `Bits` corresponds to one target byte. Use target endian layout. | |
| static void setBitRange(SmallVectorImpl<uint64_t> &Bits, int StorageOffset, | |
| int StorageSize, int BitOffset, int BitWidth, | |
| int CharWidth, bool BigEndian) { | |
| SmallVector<uint64_t, 8> TmpBits(StorageSize); | |
| setBitRange(TmpBits, BitOffset, BitWidth, CharWidth); | |
| if (BigEndian) | |
| std::reverse(TmpBits.begin(), TmpBits.end()); | |
| for (uint64_t V : TmpBits) | |
| Bits[StorageOffset++] |= V; | |
| } | |
| static void setUsedBits(CodeGenModule &, QualType, int, | |
| SmallVectorImpl<uint64_t> &); | |
| // Set the bits in `Bits`, which correspond to the value representations of | |
| // the actual members of the record type `RTy`. Note that this function does | |
| // not handle base classes, virtual tables, etc, since they cannot happen in | |
| // CMSE function arguments or return. The bit mask corresponds to the target | |
| // memory layout, i.e. it's endian dependent. | |
| static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset, | |
| SmallVectorImpl<uint64_t> &Bits) { | |
| ASTContext &Context = CGM.getContext(); | |
| int CharWidth = Context.getCharWidth(); | |
| const RecordDecl *RD = RTy->getDecl()->getDefinition(); | |
| const ASTRecordLayout &ASTLayout = Context.getASTRecordLayout(RD); | |
| const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(RD); | |
| int Idx = 0; | |
| for (auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Idx) { | |
| const FieldDecl *F = *I; | |
| if (F->isUnnamedBitField() || F->isZeroLengthBitField() || | |
| F->getType()->isIncompleteArrayType()) | |
| continue; | |
| if (F->isBitField()) { | |
| const CGBitFieldInfo &BFI = Layout.getBitFieldInfo(F); | |
| setBitRange(Bits, Offset + BFI.StorageOffset.getQuantity(), | |
| BFI.StorageSize / CharWidth, BFI.Offset, BFI.Size, CharWidth, | |
| CGM.getDataLayout().isBigEndian()); | |
| continue; | |
| } | |
| setUsedBits(CGM, F->getType(), | |
| Offset + ASTLayout.getFieldOffset(Idx) / CharWidth, Bits); | |
| } | |
| } | |
| // Set the bits in `Bits`, which correspond to the value representations of | |
| // the elements of an array type `ATy`. | |
| static void setUsedBits(CodeGenModule &CGM, const ConstantArrayType *ATy, | |
| int Offset, SmallVectorImpl<uint64_t> &Bits) { | |
| const ASTContext &Context = CGM.getContext(); | |
| QualType ETy = Context.getBaseElementType(ATy); | |
| int Size = Context.getTypeSizeInChars(ETy).getQuantity(); | |
| SmallVector<uint64_t, 4> TmpBits(Size); | |
| setUsedBits(CGM, ETy, 0, TmpBits); | |
| for (int I = 0, N = Context.getConstantArrayElementCount(ATy); I < N; ++I) { | |
| auto Src = TmpBits.begin(); | |
| auto Dst = Bits.begin() + Offset + I * Size; | |
| for (int J = 0; J < Size; ++J) | |
| *Dst++ |= *Src++; | |
| } | |
| } | |
| // Set the bits in `Bits`, which correspond to the value representations of | |
| // the type `QTy`. | |
| static void setUsedBits(CodeGenModule &CGM, QualType QTy, int Offset, | |
| SmallVectorImpl<uint64_t> &Bits) { | |
| if (const auto *RTy = QTy->getAsCanonical<RecordType>()) | |
| return setUsedBits(CGM, RTy, Offset, Bits); | |
| ASTContext &Context = CGM.getContext(); | |
| if (const auto *ATy = Context.getAsConstantArrayType(QTy)) | |
| return setUsedBits(CGM, ATy, Offset, Bits); | |
| int Size = Context.getTypeSizeInChars(QTy).getQuantity(); | |
| if (Size <= 0) | |
| return; | |
| std::fill_n(Bits.begin() + Offset, Size, | |
| (uint64_t(1) << Context.getCharWidth()) - 1); | |
| } | |
| static uint64_t buildMultiCharMask(const SmallVectorImpl<uint64_t> &Bits, | |
| int Pos, int Size, int CharWidth, | |
| bool BigEndian) { | |
| assert(Size > 0); | |
| uint64_t Mask = 0; | |
| if (BigEndian) { | |
| for (auto P = Bits.begin() + Pos, E = Bits.begin() + Pos + Size; P != E; | |
| ++P) | |
| Mask = (Mask << CharWidth) | *P; | |
| } else { | |
| auto P = Bits.begin() + Pos + Size, End = Bits.begin() + Pos; | |
| do | |
| Mask = (Mask << CharWidth) | *--P; | |
| while (P != End); | |
| } | |
| return Mask; | |
| } | |
| // Emit code to clear the bits in a record, which aren't a part of any user | |
| // declared member, when the record is a function return. | |
| llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src, | |
| llvm::IntegerType *ITy, | |
| QualType QTy) { | |
| assert(Src->getType() == ITy); | |
| assert(ITy->getScalarSizeInBits() <= 64); | |
| const llvm::DataLayout &DataLayout = CGM.getDataLayout(); | |
| int Size = DataLayout.getTypeStoreSize(ITy); | |
| SmallVector<uint64_t, 4> Bits(Size); | |
| setUsedBits(CGM, QTy->castAsCanonical<RecordType>(), 0, Bits); | |
| int CharWidth = CGM.getContext().getCharWidth(); | |
| uint64_t Mask = | |
| buildMultiCharMask(Bits, 0, Size, CharWidth, DataLayout.isBigEndian()); | |
| return Builder.CreateAnd(Src, Mask, "cmse.clear"); | |
| } | |
| // Emit code to clear the bits in a record, which aren't a part of any user | |
| // declared member, when the record is a function argument. | |
| llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src, | |
| llvm::ArrayType *ATy, | |
| QualType QTy) { | |
| const llvm::DataLayout &DataLayout = CGM.getDataLayout(); | |
| int Size = DataLayout.getTypeStoreSize(ATy); | |
| SmallVector<uint64_t, 16> Bits(Size); | |
| setUsedBits(CGM, QTy->castAsCanonical<RecordType>(), 0, Bits); | |
| // Clear each element of the LLVM array. | |
| int CharWidth = CGM.getContext().getCharWidth(); | |
| int CharsPerElt = | |
| ATy->getArrayElementType()->getScalarSizeInBits() / CharWidth; | |
| int MaskIndex = 0; | |
| llvm::Value *R = llvm::PoisonValue::get(ATy); | |
| for (int I = 0, N = ATy->getArrayNumElements(); I != N; ++I) { | |
| uint64_t Mask = buildMultiCharMask(Bits, MaskIndex, CharsPerElt, CharWidth, | |
| DataLayout.isBigEndian()); | |
| MaskIndex += CharsPerElt; | |
| llvm::Value *T0 = Builder.CreateExtractValue(Src, I); | |
| llvm::Value *T1 = Builder.CreateAnd(T0, Mask, "cmse.clear"); | |
| R = Builder.CreateInsertValue(R, T1, I); | |
| } | |
| return R; | |
| } | |
| void CodeGenFunction::EmitFunctionEpilog( | |
| const CGFunctionInfo &FI, bool EmitRetDbgLoc, SourceLocation EndLoc, | |
| uint64_t RetKeyInstructionsSourceAtom) { | |
| if (FI.isNoReturn()) { | |
| // Noreturn functions don't return. | |
| EmitUnreachable(EndLoc); | |
| return; | |
| } | |
| if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) { | |
| // Naked functions don't have epilogues. | |
| Builder.CreateUnreachable(); | |
| return; | |
| } | |
| // Functions with no result always return void. | |
| if (!ReturnValue.isValid()) { | |
| auto *I = Builder.CreateRetVoid(); | |
| if (RetKeyInstructionsSourceAtom) | |
| addInstToSpecificSourceAtom(I, nullptr, RetKeyInstructionsSourceAtom); | |
| else | |
| addInstToNewSourceAtom(I, nullptr); | |
| return; | |
| } | |
| llvm::DebugLoc RetDbgLoc; | |
| llvm::Value *RV = nullptr; | |
| QualType RetTy = FI.getReturnType(); | |
| const ABIArgInfo &RetAI = FI.getReturnInfo(); | |
| switch (RetAI.getKind()) { | |
| case ABIArgInfo::InAlloca: | |
| // Aggregates get evaluated directly into the destination. Sometimes we | |
| // need to return the sret value in a register, though. | |
| assert(hasAggregateEvaluationKind(RetTy)); | |
| if (RetAI.getInAllocaSRet()) { | |
| llvm::Function::arg_iterator EI = CurFn->arg_end(); | |
| --EI; | |
| llvm::Value *ArgStruct = &*EI; | |
| llvm::Value *SRet = Builder.CreateStructGEP( | |
| FI.getArgStruct(), ArgStruct, RetAI.getInAllocaFieldIndex()); | |
| llvm::Type *Ty = | |
| cast<llvm::GetElementPtrInst>(SRet)->getResultElementType(); | |
| RV = Builder.CreateAlignedLoad(Ty, SRet, getPointerAlign(), "sret"); | |
| } | |
| break; | |
| case ABIArgInfo::Indirect: { | |
| auto AI = CurFn->arg_begin(); | |
| if (RetAI.isSRetAfterThis()) | |
| ++AI; | |
| switch (getEvaluationKind(RetTy)) { | |
| case TEK_Complex: { | |
| ComplexPairTy RT = | |
| EmitLoadOfComplex(MakeAddrLValue(ReturnValue, RetTy), EndLoc); | |
| EmitStoreOfComplex(RT, MakeNaturalAlignAddrLValue(&*AI, RetTy), | |
| /*isInit*/ true); | |
| break; | |
| } | |
| case TEK_Aggregate: | |
| // Do nothing; aggregates get evaluated directly into the destination. | |
| break; | |
| case TEK_Scalar: { | |
| LValueBaseInfo BaseInfo; | |
| TBAAAccessInfo TBAAInfo; | |
| CharUnits Alignment = | |
| CGM.getNaturalTypeAlignment(RetTy, &BaseInfo, &TBAAInfo); | |
| Address ArgAddr(&*AI, ConvertType(RetTy), Alignment); | |
| LValue ArgVal = | |
| LValue::MakeAddr(ArgAddr, RetTy, getContext(), BaseInfo, TBAAInfo); | |
| EmitStoreOfScalar( | |
| EmitLoadOfScalar(MakeAddrLValue(ReturnValue, RetTy), EndLoc), ArgVal, | |
| /*isInit*/ true); | |
| break; | |
| } | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::Extend: | |
| case ABIArgInfo::Direct: | |
| if (RetAI.getCoerceToType() == ConvertType(RetTy) && | |
| RetAI.getDirectOffset() == 0) { | |
| // The internal return value temp always will have pointer-to-return-type | |
| // type, just do a load. | |
| // If there is a dominating store to ReturnValue, we can elide | |
| // the load, zap the store, and usually zap the alloca. | |
| if (llvm::StoreInst *SI = findDominatingStoreToReturnValue(*this)) { | |
| // Reuse the debug location from the store unless there is | |
| // cleanup code to be emitted between the store and return | |
| // instruction. | |
| if (EmitRetDbgLoc && !AutoreleaseResult) | |
| RetDbgLoc = SI->getDebugLoc(); | |
| // Get the stored value and nuke the now-dead store. | |
| RV = SI->getValueOperand(); | |
| SI->eraseFromParent(); | |
| // Otherwise, we have to do a simple load. | |
| } else { | |
| RV = Builder.CreateLoad(ReturnValue); | |
| } | |
| } else { | |
| // If the value is offset in memory, apply the offset now. | |
| Address V = emitAddressAtOffset(*this, ReturnValue, RetAI); | |
| RV = CreateCoercedLoad(V, RetTy, RetAI.getCoerceToType(), *this); | |
| } | |
| // In ARC, end functions that return a retainable type with a call | |
| // to objc_autoreleaseReturnValue. | |
| if (AutoreleaseResult) { | |
| #ifndef NDEBUG | |
| // Type::isObjCRetainabletype has to be called on a QualType that hasn't | |
| // been stripped of the typedefs, so we cannot use RetTy here. Get the | |
| // original return type of FunctionDecl, CurCodeDecl, and BlockDecl from | |
| // CurCodeDecl or BlockInfo. | |
| QualType RT; | |
| if (auto *FD = dyn_cast<FunctionDecl>(CurCodeDecl)) | |
| RT = FD->getReturnType(); | |
| else if (auto *MD = dyn_cast<ObjCMethodDecl>(CurCodeDecl)) | |
| RT = MD->getReturnType(); | |
| else if (isa<BlockDecl>(CurCodeDecl)) | |
| RT = BlockInfo->BlockExpression->getFunctionType()->getReturnType(); | |
| else | |
| llvm_unreachable("Unexpected function/method type"); | |
| assert(getLangOpts().ObjCAutoRefCount && !FI.isReturnsRetained() && | |
| RT->isObjCRetainableType()); | |
| #endif | |
| RV = emitAutoreleaseOfResult(*this, RV); | |
| } | |
| break; | |
| case ABIArgInfo::Ignore: | |
| break; | |
| case ABIArgInfo::CoerceAndExpand: { | |
| auto coercionType = RetAI.getCoerceAndExpandType(); | |
| auto unpaddedCoercionType = RetAI.getUnpaddedCoerceAndExpandType(); | |
| auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType); | |
| // Load all of the coerced elements out into results. | |
| llvm::SmallVector<llvm::Value *, 4> results; | |
| Address addr = ReturnValue.withElementType(coercionType); | |
| unsigned unpaddedIndex = 0; | |
| for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { | |
| auto coercedEltType = coercionType->getElementType(i); | |
| if (ABIArgInfo::isPaddingForCoerceAndExpand(coercedEltType)) | |
| continue; | |
| auto eltAddr = Builder.CreateStructGEP(addr, i); | |
| llvm::Value *elt = CreateCoercedLoad( | |
| eltAddr, RetTy, | |
| unpaddedStruct ? unpaddedStruct->getElementType(unpaddedIndex++) | |
| : unpaddedCoercionType, | |
| *this); | |
| results.push_back(elt); | |
| } | |
| // If we have one result, it's the single direct result type. | |
| if (results.size() == 1) { | |
| RV = results[0]; | |
| // Otherwise, we need to make a first-class aggregate. | |
| } else { | |
| // Construct a return type that lacks padding elements. | |
| llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType(); | |
| RV = llvm::PoisonValue::get(returnType); | |
| for (unsigned i = 0, e = results.size(); i != e; ++i) { | |
| RV = Builder.CreateInsertValue(RV, results[i], i); | |
| } | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::TargetSpecific: { | |
| Address V = emitAddressAtOffset(*this, ReturnValue, RetAI); | |
| RV = CGM.getABIInfo().createCoercedLoad(V, RetAI, *this); | |
| break; | |
| } | |
| case ABIArgInfo::Expand: | |
| case ABIArgInfo::IndirectAliased: | |
| llvm_unreachable("Invalid ABI kind for return argument"); | |
| } | |
| llvm::Instruction *Ret; | |
| if (RV) { | |
| if (CurFuncDecl && CurFuncDecl->hasAttr<CmseNSEntryAttr>()) { | |
| // For certain return types, clear padding bits, as they may reveal | |
| // sensitive information. | |
| // Small struct/union types are passed as integers. | |
| auto *ITy = dyn_cast<llvm::IntegerType>(RV->getType()); | |
| if (ITy != nullptr && isa<RecordType>(RetTy.getCanonicalType())) | |
| RV = EmitCMSEClearRecord(RV, ITy, RetTy); | |
| } | |
| EmitReturnValueCheck(RV); | |
| Ret = Builder.CreateRet(RV); | |
| } else { | |
| Ret = Builder.CreateRetVoid(); | |
| } | |
| if (RetDbgLoc) | |
| Ret->setDebugLoc(std::move(RetDbgLoc)); | |
| llvm::Value *Backup = RV ? Ret->getOperand(0) : nullptr; | |
| if (RetKeyInstructionsSourceAtom) | |
| addInstToSpecificSourceAtom(Ret, Backup, RetKeyInstructionsSourceAtom); | |
| else | |
| addInstToNewSourceAtom(Ret, Backup); | |
| } | |
| void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) { | |
| // A current decl may not be available when emitting vtable thunks. | |
| if (!CurCodeDecl) | |
| return; | |
| // If the return block isn't reachable, neither is this check, so don't emit | |
| // it. | |
| if (ReturnBlock.isValid() && ReturnBlock.getBlock()->use_empty()) | |
| return; | |
| ReturnsNonNullAttr *RetNNAttr = nullptr; | |
| if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) | |
| RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>(); | |
| if (!RetNNAttr && !requiresReturnValueNullabilityCheck()) | |
| return; | |
| // Prefer the returns_nonnull attribute if it's present. | |
| SourceLocation AttrLoc; | |
| SanitizerKind::SanitizerOrdinal CheckKind; | |
| SanitizerHandler Handler; | |
| if (RetNNAttr) { | |
| assert(!requiresReturnValueNullabilityCheck() && | |
| "Cannot check nullability and the nonnull attribute"); | |
| AttrLoc = RetNNAttr->getLocation(); | |
| CheckKind = SanitizerKind::SO_ReturnsNonnullAttribute; | |
| Handler = SanitizerHandler::NonnullReturn; | |
| } else { | |
| if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl)) | |
| if (auto *TSI = DD->getTypeSourceInfo()) | |
| if (auto FTL = TSI->getTypeLoc().getAsAdjusted<FunctionTypeLoc>()) | |
| AttrLoc = FTL.getReturnLoc().findNullabilityLoc(); | |
| CheckKind = SanitizerKind::SO_NullabilityReturn; | |
| Handler = SanitizerHandler::NullabilityReturn; | |
| } | |
| SanitizerDebugLocation SanScope(this, {CheckKind}, Handler); | |
| // Make sure the "return" source location is valid. If we're checking a | |
| // nullability annotation, make sure the preconditions for the check are met. | |
| llvm::BasicBlock *Check = createBasicBlock("nullcheck"); | |
| llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck"); | |
| llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load"); | |
| llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr); | |
| if (requiresReturnValueNullabilityCheck()) | |
| CanNullCheck = | |
| Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition); | |
| Builder.CreateCondBr(CanNullCheck, Check, NoCheck); | |
| EmitBlock(Check); | |
| // Now do the null check. | |
| llvm::Value *Cond = Builder.CreateIsNotNull(RV); | |
| llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)}; | |
| llvm::Value *DynamicData[] = {SLocPtr}; | |
| EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData); | |
| EmitBlock(NoCheck); | |
| #ifndef NDEBUG | |
| // The return location should not be used after the check has been emitted. | |
| ReturnLocation = Address::invalid(); | |
| #endif | |
| } | |
| static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) { | |
| const CXXRecordDecl *RD = type->getAsCXXRecordDecl(); | |
| return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; | |
| } | |
| static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF, QualType Ty) { | |
| // FIXME: Generate IR in one pass, rather than going back and fixing up these | |
| // placeholders. | |
| llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty); | |
| llvm::Type *IRPtrTy = llvm::PointerType::getUnqual(CGF.getLLVMContext()); | |
| llvm::Value *Placeholder = llvm::PoisonValue::get(IRPtrTy); | |
| // FIXME: When we generate this IR in one pass, we shouldn't need | |
| // this win32-specific alignment hack. | |
| CharUnits Align = CharUnits::fromQuantity(4); | |
| Placeholder = CGF.Builder.CreateAlignedLoad(IRPtrTy, Placeholder, Align); | |
| return AggValueSlot::forAddr( | |
| Address(Placeholder, IRTy, Align), Ty.getQualifiers(), | |
| AggValueSlot::IsNotDestructed, AggValueSlot::DoesNotNeedGCBarriers, | |
| AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap); | |
| } | |
| void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, | |
| const VarDecl *param, | |
| SourceLocation loc) { | |
| // StartFunction converted the ABI-lowered parameter(s) into a | |
| // local alloca. We need to turn that into an r-value suitable | |
| // for EmitCall. | |
| Address local = GetAddrOfLocalVar(param); | |
| QualType type = param->getType(); | |
| // GetAddrOfLocalVar returns a pointer-to-pointer for references, | |
| // but the argument needs to be the original pointer. | |
| if (type->isReferenceType()) { | |
| args.add(RValue::get(Builder.CreateLoad(local)), type); | |
| // In ARC, move out of consumed arguments so that the release cleanup | |
| // entered by StartFunction doesn't cause an over-release. This isn't | |
| // optimal -O0 code generation, but it should get cleaned up when | |
| // optimization is enabled. This also assumes that delegate calls are | |
| // performed exactly once for a set of arguments, but that should be safe. | |
| } else if (getLangOpts().ObjCAutoRefCount && | |
| param->hasAttr<NSConsumedAttr>() && type->isObjCRetainableType()) { | |
| llvm::Value *ptr = Builder.CreateLoad(local); | |
| auto null = | |
| llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType())); | |
| Builder.CreateStore(null, local); | |
| args.add(RValue::get(ptr), type); | |
| // For the most part, we just need to load the alloca, except that | |
| // aggregate r-values are actually pointers to temporaries. | |
| } else { | |
| args.add(convertTempToRValue(local, type, loc), type); | |
| } | |
| // Deactivate the cleanup for the callee-destructed param that was pushed. | |
| if (type->isRecordType() && !CurFuncIsThunk && | |
| type->castAsRecordDecl()->isParamDestroyedInCallee() && | |
| param->needsDestruction(getContext())) { | |
| EHScopeStack::stable_iterator cleanup = | |
| CalleeDestructedParamCleanups.lookup(cast<ParmVarDecl>(param)); | |
| assert(cleanup.isValid() && | |
| "cleanup for callee-destructed param not recorded"); | |
| // This load is a temporary marker which will be removed later. | |
| llvm::Instruction *isActive = | |
| Builder.CreateFlagLoad(llvm::Constant::getNullValue(Int8PtrTy)); | |
| args.addArgCleanupDeactivation(cleanup, isActive); | |
| } | |
| } | |
| static bool isProvablyNull(llvm::Value *addr) { | |
| return llvm::isa_and_nonnull<llvm::ConstantPointerNull>(addr); | |
| } | |
| static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { | |
| return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); | |
| } | |
| /// Emit the actual writing-back of a writeback. | |
| static void emitWriteback(CodeGenFunction &CGF, | |
| const CallArgList::Writeback &writeback) { | |
| const LValue &srcLV = writeback.Source; | |
| Address srcAddr = srcLV.getAddress(); | |
| assert(!isProvablyNull(srcAddr.getBasePointer()) && | |
| "shouldn't have writeback for provably null argument"); | |
| if (writeback.WritebackExpr) { | |
| CGF.EmitIgnoredExpr(writeback.WritebackExpr); | |
| CGF.EmitLifetimeEnd(writeback.Temporary.getBasePointer()); | |
| return; | |
| } | |
| llvm::BasicBlock *contBB = nullptr; | |
| // If the argument wasn't provably non-null, we need to null check | |
| // before doing the store. | |
| bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); | |
| if (!provablyNonNull) { | |
| llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); | |
| contBB = CGF.createBasicBlock("icr.done"); | |
| llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); | |
| CGF.Builder.CreateCondBr(isNull, contBB, writebackBB); | |
| CGF.EmitBlock(writebackBB); | |
| } | |
| // Load the value to writeback. | |
| llvm::Value *value = CGF.Builder.CreateLoad(writeback.Temporary); | |
| // Cast it back, in case we're writing an id to a Foo* or something. | |
| value = CGF.Builder.CreateBitCast(value, srcAddr.getElementType(), | |
| "icr.writeback-cast"); | |
| // Perform the writeback. | |
| // If we have a "to use" value, it's something we need to emit a use | |
| // of. This has to be carefully threaded in: if it's done after the | |
| // release it's potentially undefined behavior (and the optimizer | |
| // will ignore it), and if it happens before the retain then the | |
| // optimizer could move the release there. | |
| if (writeback.ToUse) { | |
| assert(srcLV.getObjCLifetime() == Qualifiers::OCL_Strong); | |
| // Retain the new value. No need to block-copy here: the block's | |
| // being passed up the stack. | |
| value = CGF.EmitARCRetainNonBlock(value); | |
| // Emit the intrinsic use here. | |
| CGF.EmitARCIntrinsicUse(writeback.ToUse); | |
| // Load the old value (primitively). | |
| llvm::Value *oldValue = CGF.EmitLoadOfScalar(srcLV, SourceLocation()); | |
| // Put the new value in place (primitively). | |
| CGF.EmitStoreOfScalar(value, srcLV, /*init*/ false); | |
| // Release the old value. | |
| CGF.EmitARCRelease(oldValue, srcLV.isARCPreciseLifetime()); | |
| // Otherwise, we can just do a normal lvalue store. | |
| } else { | |
| CGF.EmitStoreThroughLValue(RValue::get(value), srcLV); | |
| } | |
| // Jump to the continuation block. | |
| if (!provablyNonNull) | |
| CGF.EmitBlock(contBB); | |
| } | |
| static void deactivateArgCleanupsBeforeCall(CodeGenFunction &CGF, | |
| const CallArgList &CallArgs) { | |
| ArrayRef<CallArgList::CallArgCleanup> Cleanups = | |
| CallArgs.getCleanupsToDeactivate(); | |
| // Iterate in reverse to increase the likelihood of popping the cleanup. | |
| for (const auto &I : llvm::reverse(Cleanups)) { | |
| CGF.DeactivateCleanupBlock(I.Cleanup, I.IsActiveIP); | |
| I.IsActiveIP->eraseFromParent(); | |
| } | |
| } | |
| static const Expr *maybeGetUnaryAddrOfOperand(const Expr *E) { | |
| if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E->IgnoreParens())) | |
| if (uop->getOpcode() == UO_AddrOf) | |
| return uop->getSubExpr(); | |
| return nullptr; | |
| } | |
| /// Emit an argument that's being passed call-by-writeback. That is, | |
| /// we are passing the address of an __autoreleased temporary; it | |
| /// might be copy-initialized with the current value of the given | |
| /// address, but it will definitely be copied out of after the call. | |
| static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, | |
| const ObjCIndirectCopyRestoreExpr *CRE) { | |
| LValue srcLV; | |
| // Make an optimistic effort to emit the address as an l-value. | |
| // This can fail if the argument expression is more complicated. | |
| if (const Expr *lvExpr = maybeGetUnaryAddrOfOperand(CRE->getSubExpr())) { | |
| srcLV = CGF.EmitLValue(lvExpr); | |
| // Otherwise, just emit it as a scalar. | |
| } else { | |
| Address srcAddr = CGF.EmitPointerWithAlignment(CRE->getSubExpr()); | |
| QualType srcAddrType = | |
| CRE->getSubExpr()->getType()->castAs<PointerType>()->getPointeeType(); | |
| srcLV = CGF.MakeAddrLValue(srcAddr, srcAddrType); | |
| } | |
| Address srcAddr = srcLV.getAddress(); | |
| // The dest and src types don't necessarily match in LLVM terms | |
| // because of the crazy ObjC compatibility rules. | |
| llvm::PointerType *destType = | |
| cast<llvm::PointerType>(CGF.ConvertType(CRE->getType())); | |
| llvm::Type *destElemType = | |
| CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); | |
| // If the address is a constant null, just pass the appropriate null. | |
| if (isProvablyNull(srcAddr.getBasePointer())) { | |
| args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), | |
| CRE->getType()); | |
| return; | |
| } | |
| // Create the temporary. | |
| Address temp = | |
| CGF.CreateTempAlloca(destElemType, CGF.getPointerAlign(), "icr.temp"); | |
| // Loading an l-value can introduce a cleanup if the l-value is __weak, | |
| // and that cleanup will be conditional if we can't prove that the l-value | |
| // isn't null, so we need to register a dominating point so that the cleanups | |
| // system will make valid IR. | |
| CodeGenFunction::ConditionalEvaluation condEval(CGF); | |
| // Zero-initialize it if we're not doing a copy-initialization. | |
| bool shouldCopy = CRE->shouldCopy(); | |
| if (!shouldCopy) { | |
| llvm::Value *null = | |
| llvm::ConstantPointerNull::get(cast<llvm::PointerType>(destElemType)); | |
| CGF.Builder.CreateStore(null, temp); | |
| } | |
| llvm::BasicBlock *contBB = nullptr; | |
| llvm::BasicBlock *originBB = nullptr; | |
| // If the address is *not* known to be non-null, we need to switch. | |
| llvm::Value *finalArgument; | |
| bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); | |
| if (provablyNonNull) { | |
| finalArgument = temp.emitRawPointer(CGF); | |
| } else { | |
| llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); | |
| finalArgument = CGF.Builder.CreateSelect( | |
| isNull, llvm::ConstantPointerNull::get(destType), | |
| temp.emitRawPointer(CGF), "icr.argument"); | |
| // If we need to copy, then the load has to be conditional, which | |
| // means we need control flow. | |
| if (shouldCopy) { | |
| originBB = CGF.Builder.GetInsertBlock(); | |
| contBB = CGF.createBasicBlock("icr.cont"); | |
| llvm::BasicBlock *copyBB = CGF.createBasicBlock("icr.copy"); | |
| CGF.Builder.CreateCondBr(isNull, contBB, copyBB); | |
| CGF.EmitBlock(copyBB); | |
| condEval.begin(CGF); | |
| } | |
| } | |
| llvm::Value *valueToUse = nullptr; | |
| // Perform a copy if necessary. | |
| if (shouldCopy) { | |
| RValue srcRV = CGF.EmitLoadOfLValue(srcLV, SourceLocation()); | |
| assert(srcRV.isScalar()); | |
| llvm::Value *src = srcRV.getScalarVal(); | |
| src = CGF.Builder.CreateBitCast(src, destElemType, "icr.cast"); | |
| // Use an ordinary store, not a store-to-lvalue. | |
| CGF.Builder.CreateStore(src, temp); | |
| // If optimization is enabled, and the value was held in a | |
| // __strong variable, we need to tell the optimizer that this | |
| // value has to stay alive until we're doing the store back. | |
| // This is because the temporary is effectively unretained, | |
| // and so otherwise we can violate the high-level semantics. | |
| if (CGF.CGM.getCodeGenOpts().OptimizationLevel != 0 && | |
| srcLV.getObjCLifetime() == Qualifiers::OCL_Strong) { | |
| valueToUse = src; | |
| } | |
| } | |
| // Finish the control flow if we needed it. | |
| if (shouldCopy && !provablyNonNull) { | |
| llvm::BasicBlock *copyBB = CGF.Builder.GetInsertBlock(); | |
| CGF.EmitBlock(contBB); | |
| // Make a phi for the value to intrinsically use. | |
| if (valueToUse) { | |
| llvm::PHINode *phiToUse = | |
| CGF.Builder.CreatePHI(valueToUse->getType(), 2, "icr.to-use"); | |
| phiToUse->addIncoming(valueToUse, copyBB); | |
| phiToUse->addIncoming(llvm::PoisonValue::get(valueToUse->getType()), | |
| originBB); | |
| valueToUse = phiToUse; | |
| } | |
| condEval.end(CGF); | |
| } | |
| args.addWriteback(srcLV, temp, valueToUse); | |
| args.add(RValue::get(finalArgument), CRE->getType()); | |
| } | |
| void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) { | |
| assert(!StackBase); | |
| // Save the stack. | |
| StackBase = CGF.Builder.CreateStackSave("inalloca.save"); | |
| } | |
| void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const { | |
| if (StackBase) { | |
| // Restore the stack after the call. | |
| CGF.Builder.CreateStackRestore(StackBase); | |
| } | |
| } | |
| void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, | |
| SourceLocation ArgLoc, | |
| AbstractCallee AC, unsigned ParmNum) { | |
| if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || | |
| SanOpts.has(SanitizerKind::NullabilityArg))) | |
| return; | |
| // The param decl may be missing in a variadic function. | |
| auto PVD = ParmNum < AC.getNumParams() ? AC.getParamDecl(ParmNum) : nullptr; | |
| unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum; | |
| // Prefer the nonnull attribute if it's present. | |
| const NonNullAttr *NNAttr = nullptr; | |
| if (SanOpts.has(SanitizerKind::NonnullAttribute)) | |
| NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo); | |
| bool CanCheckNullability = false; | |
| if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD && | |
| !PVD->getType()->isRecordType()) { | |
| auto Nullability = PVD->getType()->getNullability(); | |
| CanCheckNullability = Nullability && | |
| *Nullability == NullabilityKind::NonNull && | |
| PVD->getTypeSourceInfo(); | |
| } | |
| if (!NNAttr && !CanCheckNullability) | |
| return; | |
| SourceLocation AttrLoc; | |
| SanitizerKind::SanitizerOrdinal CheckKind; | |
| SanitizerHandler Handler; | |
| if (NNAttr) { | |
| AttrLoc = NNAttr->getLocation(); | |
| CheckKind = SanitizerKind::SO_NonnullAttribute; | |
| Handler = SanitizerHandler::NonnullArg; | |
| } else { | |
| AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc(); | |
| CheckKind = SanitizerKind::SO_NullabilityArg; | |
| Handler = SanitizerHandler::NullabilityArg; | |
| } | |
| SanitizerDebugLocation SanScope(this, {CheckKind}, Handler); | |
| llvm::Value *Cond = EmitNonNullRValueCheck(RV, ArgType); | |
| llvm::Constant *StaticData[] = { | |
| EmitCheckSourceLocation(ArgLoc), | |
| EmitCheckSourceLocation(AttrLoc), | |
| llvm::ConstantInt::get(Int32Ty, ArgNo + 1), | |
| }; | |
| EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, {}); | |
| } | |
| void CodeGenFunction::EmitNonNullArgCheck(Address Addr, QualType ArgType, | |
| SourceLocation ArgLoc, | |
| AbstractCallee AC, unsigned ParmNum) { | |
| if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || | |
| SanOpts.has(SanitizerKind::NullabilityArg))) | |
| return; | |
| EmitNonNullArgCheck(RValue::get(Addr, *this), ArgType, ArgLoc, AC, ParmNum); | |
| } | |
| // Check if the call is going to use the inalloca convention. This needs to | |
| // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged | |
| // later, so we can't check it directly. | |
| static bool hasInAllocaArgs(CodeGenModule &CGM, CallingConv ExplicitCC, | |
| ArrayRef<QualType> ArgTypes) { | |
| // The Swift calling conventions don't go through the target-specific | |
| // argument classification, they never use inalloca. | |
| // TODO: Consider limiting inalloca use to only calling conventions supported | |
| // by MSVC. | |
| if (ExplicitCC == CC_Swift || ExplicitCC == CC_SwiftAsync) | |
| return false; | |
| if (!CGM.getTarget().getCXXABI().isMicrosoft()) | |
| return false; | |
| return llvm::any_of(ArgTypes, [&](QualType Ty) { | |
| return isInAllocaArgument(CGM.getCXXABI(), Ty); | |
| }); | |
| } | |
| #ifndef NDEBUG | |
| // Determine whether the given argument is an Objective-C method | |
| // that may have type parameters in its signature. | |
| static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) { | |
| const DeclContext *dc = method->getDeclContext(); | |
| if (const ObjCInterfaceDecl *classDecl = dyn_cast<ObjCInterfaceDecl>(dc)) { | |
| return classDecl->getTypeParamListAsWritten(); | |
| } | |
| if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) { | |
| return catDecl->getTypeParamList(); | |
| } | |
| return false; | |
| } | |
| #endif | |
| /// EmitCallArgs - Emit call arguments for a function. | |
| void CodeGenFunction::EmitCallArgs( | |
| CallArgList &Args, PrototypeWrapper Prototype, | |
| llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, | |
| AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) { | |
| SmallVector<QualType, 16> ArgTypes; | |
| assert((ParamsToSkip == 0 || Prototype.P) && | |
| "Can't skip parameters if type info is not provided"); | |
| // This variable only captures *explicitly* written conventions, not those | |
| // applied by default via command line flags or target defaults, such as | |
| // thiscall, aapcs, stdcall via -mrtd, etc. Computing that correctly would | |
| // require knowing if this is a C++ instance method or being able to see | |
| // unprototyped FunctionTypes. | |
| CallingConv ExplicitCC = CC_C; | |
| // First, if a prototype was provided, use those argument types. | |
| bool IsVariadic = false; | |
| if (Prototype.P) { | |
| const auto *MD = dyn_cast<const ObjCMethodDecl *>(Prototype.P); | |
| if (MD) { | |
| IsVariadic = MD->isVariadic(); | |
| ExplicitCC = getCallingConventionForDecl( | |
| MD, CGM.getTarget().getTriple().isOSWindows()); | |
| ArgTypes.assign(MD->param_type_begin() + ParamsToSkip, | |
| MD->param_type_end()); | |
| } else { | |
| const auto *FPT = cast<const FunctionProtoType *>(Prototype.P); | |
| IsVariadic = FPT->isVariadic(); | |
| ExplicitCC = FPT->getExtInfo().getCC(); | |
| ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip, | |
| FPT->param_type_end()); | |
| } | |
| #ifndef NDEBUG | |
| // Check that the prototyped types match the argument expression types. | |
| bool isGenericMethod = MD && isObjCMethodWithTypeParams(MD); | |
| CallExpr::const_arg_iterator Arg = ArgRange.begin(); | |
| for (QualType Ty : ArgTypes) { | |
| assert(Arg != ArgRange.end() && "Running over edge of argument list!"); | |
| QualType ParamTy = Ty.getNonReferenceType(); | |
| QualType ArgTy = (*Arg)->getType(); | |
| if (const auto *OBT = ParamTy->getAs<OverflowBehaviorType>()) | |
| ParamTy = OBT->getUnderlyingType(); | |
| if (const auto *OBT = ArgTy->getAs<OverflowBehaviorType>()) | |
| ArgTy = OBT->getUnderlyingType(); | |
| assert((isGenericMethod || Ty->isVariablyModifiedType() || | |
| ParamTy->isObjCRetainableType() || | |
| getContext().getCanonicalType(ParamTy).getTypePtr() == | |
| getContext().getCanonicalType(ArgTy).getTypePtr()) && | |
| "type mismatch in call argument!"); | |
| ++Arg; | |
| } | |
| // Either we've emitted all the call args, or we have a call to variadic | |
| // function. | |
| assert((Arg == ArgRange.end() || IsVariadic) && | |
| "Extra arguments in non-variadic function!"); | |
| #endif | |
| } | |
| // If we still have any arguments, emit them using the type of the argument. | |
| for (auto *A : llvm::drop_begin(ArgRange, ArgTypes.size())) | |
| ArgTypes.push_back(IsVariadic ? getVarArgType(A) : A->getType()); | |
| assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin())); | |
| // We must evaluate arguments from right to left in the MS C++ ABI, | |
| // because arguments are destroyed left to right in the callee. As a special | |
| // case, there are certain language constructs that require left-to-right | |
| // evaluation, and in those cases we consider the evaluation order requirement | |
| // to trump the "destruction order is reverse construction order" guarantee. | |
| bool LeftToRight = CodeGenUtils::shouldEvaluateArgsLeftToRight( | |
| Order, CGM.getTarget().getCXXABI()); | |
| auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg, | |
| RValue EmittedArg) { | |
| if (!AC.hasFunctionDecl() || I >= AC.getNumParams()) | |
| return; | |
| auto *PS = AC.getParamDecl(I)->getAttr<PassObjectSizeAttr>(); | |
| if (PS == nullptr) | |
| return; | |
| const auto &Context = getContext(); | |
| auto SizeTy = Context.getSizeType(); | |
| auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); | |
| assert(EmittedArg.getScalarVal() && "We emitted nothing for the arg?"); | |
| llvm::Value *V = evaluateOrEmitBuiltinObjectSize( | |
| Arg, PS->getType(), T, EmittedArg.getScalarVal(), PS->isDynamic()); | |
| Args.add(RValue::get(V), SizeTy); | |
| // If we're emitting args in reverse, be sure to do so with | |
| // pass_object_size, as well. | |
| if (!LeftToRight) | |
| std::swap(Args.back(), *(&Args.back() - 1)); | |
| }; | |
| // Insert a stack save if we're going to need any inalloca args. | |
| if (hasInAllocaArgs(CGM, ExplicitCC, ArgTypes)) { | |
| assert(getTarget().getTriple().getArch() == llvm::Triple::x86 && | |
| "inalloca only supported on x86"); | |
| Args.allocateArgumentMemory(*this); | |
| } | |
| // Evaluate each argument in the appropriate order. | |
| size_t CallArgsStart = Args.size(); | |
| for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) { | |
| unsigned Idx = LeftToRight ? I : E - I - 1; | |
| CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx; | |
| unsigned InitialArgSize = Args.size(); | |
| // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of | |
| // the argument and parameter match or the objc method is parameterized. | |
| assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) || | |
| getContext().hasSameUnqualifiedType((*Arg)->getType(), | |
| ArgTypes[Idx]) || | |
| (isa<ObjCMethodDecl>(AC.getDecl()) && | |
| isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) && | |
| "Argument and parameter types don't match"); | |
| EmitCallArg(Args, *Arg, ArgTypes[Idx]); | |
| // In particular, we depend on it being the last arg in Args, and the | |
| // objectsize bits depend on there only being one arg if !LeftToRight. | |
| assert(InitialArgSize + 1 == Args.size() && | |
| "The code below depends on only adding one arg per EmitCallArg"); | |
| (void)InitialArgSize; | |
| // Since pointer argument are never emitted as LValue, it is safe to emit | |
| // non-null argument check for r-value only. | |
| if (!Args.back().hasLValue()) { | |
| RValue RVArg = Args.back().getKnownRValue(); | |
| EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC, | |
| ParamsToSkip + Idx); | |
| // @llvm.objectsize should never have side-effects and shouldn't need | |
| // destruction/cleanups, so we can safely "emit" it after its arg, | |
| // regardless of right-to-leftness | |
| MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg); | |
| } | |
| } | |
| if (!LeftToRight) { | |
| // Un-reverse the arguments we just evaluated so they match up with the LLVM | |
| // IR function. | |
| std::reverse(Args.begin() + CallArgsStart, Args.end()); | |
| // Reverse the writebacks to match the MSVC ABI. | |
| Args.reverseWritebacks(); | |
| } | |
| } | |
| namespace { | |
| struct DestroyUnpassedArg final : EHScopeStack::Cleanup { | |
| DestroyUnpassedArg(Address Addr, QualType Ty) : Addr(Addr), Ty(Ty) {} | |
| Address Addr; | |
| QualType Ty; | |
| void Emit(CodeGenFunction &CGF, Flags flags) override { | |
| QualType::DestructionKind DtorKind = Ty.isDestructedType(); | |
| if (DtorKind == QualType::DK_cxx_destructor) { | |
| const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); | |
| assert(!Dtor->isTrivial()); | |
| CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false, | |
| /*Delegating=*/false, Addr, Ty); | |
| } else { | |
| CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty)); | |
| } | |
| } | |
| }; | |
| } // end anonymous namespace | |
| RValue CallArg::getRValue(CodeGenFunction &CGF) const { | |
| if (!HasLV) | |
| return RV; | |
| LValue Copy = CGF.MakeAddrLValue(CGF.CreateMemTempWithoutCast(Ty), Ty); | |
| CGF.EmitAggregateCopy(Copy, LV, Ty, AggValueSlot::DoesNotOverlap, | |
| LV.isVolatile()); | |
| IsUsed = true; | |
| return RValue::getAggregate(Copy.getAddress()); | |
| } | |
| void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const { | |
| LValue Dst = CGF.MakeAddrLValue(Addr, Ty); | |
| if (!HasLV && RV.isScalar()) | |
| CGF.EmitStoreOfScalar(RV.getScalarVal(), Dst, /*isInit=*/true); | |
| else if (!HasLV && RV.isComplex()) | |
| CGF.EmitStoreOfComplex(RV.getComplexVal(), Dst, /*init=*/true); | |
| else { | |
| auto Addr = HasLV ? LV.getAddress() : RV.getAggregateAddress(); | |
| LValue SrcLV = CGF.MakeAddrLValue(Addr, Ty); | |
| // We assume that call args are never copied into subobjects. | |
| CGF.EmitAggregateCopy(Dst, SrcLV, Ty, AggValueSlot::DoesNotOverlap, | |
| HasLV ? LV.isVolatileQualified() | |
| : RV.isVolatileQualified()); | |
| } | |
| IsUsed = true; | |
| } | |
| void CodeGenFunction::EmitWritebacks(const CallArgList &args) { | |
| for (const auto &I : args.writebacks()) | |
| emitWriteback(*this, I); | |
| } | |
| void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, | |
| QualType type) { | |
| std::optional<DisableDebugLocationUpdates> Dis; | |
| if (isa<CXXDefaultArgExpr>(E)) | |
| Dis.emplace(*this); | |
| if (const ObjCIndirectCopyRestoreExpr *CRE = | |
| dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) { | |
| assert(getLangOpts().ObjCAutoRefCount); | |
| return emitWritebackArg(*this, args, CRE); | |
| } | |
| // Add writeback for HLSLOutParamExpr. | |
| // Needs to be before the assert below because HLSLOutArgExpr is an LValue | |
| // and is not a reference. | |
| if (const HLSLOutArgExpr *OE = dyn_cast<HLSLOutArgExpr>(E)) { | |
| EmitHLSLOutArgExpr(OE, args, type); | |
| return; | |
| } | |
| assert(type->isReferenceType() == E->isGLValue() && | |
| "reference binding to unmaterialized r-value!"); | |
| if (E->isGLValue()) { | |
| assert(E->getObjectKind() == OK_Ordinary); | |
| return args.add(EmitReferenceBindingToExpr(E), type); | |
| } | |
| bool HasAggregateEvalKind = hasAggregateEvaluationKind(type); | |
| // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee. | |
| // However, we still have to push an EH-only cleanup in case we unwind before | |
| // we make it to the call. | |
| if (type->isRecordType() && | |
| type->castAsRecordDecl()->isParamDestroyedInCallee()) { | |
| // If we're using inalloca, use the argument memory. Otherwise, use a | |
| // temporary. | |
| AggValueSlot Slot = args.isUsingInAlloca() | |
| ? createPlaceholderSlot(*this, type) | |
| : CreateAggTemp(type, "agg.tmp"); | |
| bool DestroyedInCallee = true, NeedsCleanup = true; | |
| if (const auto *RD = type->getAsCXXRecordDecl()) | |
| DestroyedInCallee = RD->hasNonTrivialDestructor(); | |
| else | |
| NeedsCleanup = type.isDestructedType(); | |
| if (DestroyedInCallee) | |
| Slot.setExternallyDestructed(); | |
| EmitAggExpr(E, Slot); | |
| RValue RV = Slot.asRValue(); | |
| args.add(RV, type); | |
| if (DestroyedInCallee && NeedsCleanup) { | |
| // Create a no-op GEP between the placeholder and the cleanup so we can | |
| // RAUW it successfully. It also serves as a marker of the first | |
| // instruction where the cleanup is active. | |
| pushFullExprCleanup<DestroyUnpassedArg>(NormalAndEHCleanup, | |
| Slot.getAddress(), type); | |
| // This unreachable is a temporary marker which will be removed later. | |
| llvm::Instruction *IsActive = | |
| Builder.CreateFlagLoad(llvm::Constant::getNullValue(Int8PtrTy)); | |
| args.addArgCleanupDeactivation(EHStack.stable_begin(), IsActive); | |
| } | |
| return; | |
| } | |
| if (HasAggregateEvalKind) { | |
| auto *ICE = dyn_cast<ImplicitCastExpr>(E); | |
| if (ICE && ICE->getCastKind() == CK_LValueToRValue && | |
| ICE->getSubExpr()->getType().getAddressSpace() != | |
| LangAS::hlsl_constant && | |
| !type->isArrayParameterType() && !type.isNonTrivialToPrimitiveCopy()) { | |
| LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr()); | |
| assert(L.isSimple()); | |
| args.addUncopiedAggregate(L, type); | |
| return; | |
| } | |
| } | |
| args.add(EmitAnyExprToTemp(E), type); | |
| } | |
| QualType CodeGenFunction::getVarArgType(const Expr *Arg) { | |
| // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC | |
| // implicitly widens null pointer constants that are arguments to varargs | |
| // functions to pointer-sized ints. | |
| if (!getTarget().getTriple().isOSWindows()) | |
| return Arg->getType(); | |
| if (Arg->getType()->isIntegerType() && | |
| getContext().getTypeSize(Arg->getType()) < | |
| getContext().getTargetInfo().getPointerWidth(LangAS::Default) && | |
| Arg->isNullPointerConstant(getContext(), | |
| Expr::NPC_ValueDependentIsNotNull)) { | |
| return getContext().getIntPtrType(); | |
| } | |
| return Arg->getType(); | |
| } | |
| // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC | |
| // optimizer it can aggressively ignore unwind edges. | |
| void CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) { | |
| if (CGM.getCodeGenOpts().OptimizationLevel != 0 && | |
| !CGM.getCodeGenOpts().ObjCAutoRefCountExceptions) | |
| Inst->setMetadata("clang.arc.no_objc_arc_exceptions", | |
| CGM.getNoObjCARCExceptionsMetadata()); | |
| } | |
| /// Emits a call to the given no-arguments nounwind runtime function. | |
| llvm::CallInst * | |
| CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, | |
| const llvm::Twine &name) { | |
| return EmitNounwindRuntimeCall(callee, ArrayRef<llvm::Value *>(), name); | |
| } | |
| /// Emits a call to the given nounwind runtime function. | |
| llvm::CallInst * | |
| CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, | |
| ArrayRef<Address> args, | |
| const llvm::Twine &name) { | |
| SmallVector<llvm::Value *, 3> values; | |
| for (auto arg : args) | |
| values.push_back(arg.emitRawPointer(*this)); | |
| return EmitNounwindRuntimeCall(callee, values, name); | |
| } | |
| llvm::CallInst * | |
| CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, | |
| ArrayRef<llvm::Value *> args, | |
| const llvm::Twine &name) { | |
| llvm::CallInst *call = EmitRuntimeCall(callee, args, name); | |
| call->setDoesNotThrow(); | |
| return call; | |
| } | |
| /// Emits a simple call (never an invoke) to the given no-arguments | |
| /// runtime function. | |
| llvm::CallInst *CodeGenFunction::EmitRuntimeCall(llvm::FunctionCallee callee, | |
| const llvm::Twine &name) { | |
| return EmitRuntimeCall(callee, {}, name); | |
| } | |
| // Calls which may throw must have operand bundles indicating which funclet | |
| // they are nested within. | |
| SmallVector<llvm::OperandBundleDef, 1> | |
| CodeGenFunction::getBundlesForFunclet(llvm::Value *Callee) { | |
| // There is no need for a funclet operand bundle if we aren't inside a | |
| // funclet. | |
| if (!CurrentFuncletPad) | |
| return (SmallVector<llvm::OperandBundleDef, 1>()); | |
| // Skip intrinsics which cannot throw (as long as they don't lower into | |
| // regular function calls in the course of IR transformations). | |
| if (auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts())) { | |
| if (CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) { | |
| auto IID = CalleeFn->getIntrinsicID(); | |
| if (!llvm::IntrinsicInst::mayLowerToFunctionCall(IID)) | |
| return (SmallVector<llvm::OperandBundleDef, 1>()); | |
| } | |
| } | |
| SmallVector<llvm::OperandBundleDef, 1> BundleList; | |
| BundleList.emplace_back("funclet", CurrentFuncletPad); | |
| return BundleList; | |
| } | |
| static bool isConvergentIntrinsic(const llvm::Function *F) { | |
| assert(F->isIntrinsic() && "expected an intrinsic declaration"); | |
| return F->isConvergent(); | |
| } | |
| /// Emits a simple call (never an invoke) to the given runtime function. | |
| llvm::CallInst *CodeGenFunction::EmitRuntimeCall(llvm::FunctionCallee callee, | |
| ArrayRef<llvm::Value *> args, | |
| const llvm::Twine &name, | |
| bool IsConvergent) { | |
| SmallVector<llvm::OperandBundleDef> BundleList = | |
| getBundlesForFunclet(callee.getCallee()); | |
| if (IsConvergent) | |
| addConvergenceControlBundle(BundleList); | |
| llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList, name); | |
| call->setCallingConv(getRuntimeCC()); | |
| assert((IsConvergent == call->isConvergent() || | |
| (!IsConvergent && !CGM.shouldEmitConvergenceTokens())) && | |
| "runtime call convergence doesn't match its declaration"); | |
| return call; | |
| } | |
| llvm::CallInst *CodeGenFunction::EmitIntrinsicCall(llvm::Intrinsic::ID ID, | |
| const llvm::Twine &Name) { | |
| return EmitIntrinsicCall(ID, {}, {}, Name); | |
| } | |
| llvm::CallInst *CodeGenFunction::EmitIntrinsicCall(llvm::Intrinsic::ID ID, | |
| ArrayRef<llvm::Value *> Args, | |
| const llvm::Twine &Name) { | |
| return EmitIntrinsicCall(ID, {}, Args, Name); | |
| } | |
| llvm::CallInst *CodeGenFunction::EmitIntrinsicCall(llvm::Intrinsic::ID ID, | |
| ArrayRef<llvm::Type *> Types, | |
| ArrayRef<llvm::Value *> Args, | |
| const llvm::Twine &Name) { | |
| llvm::Function *F = | |
| llvm::Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID, Types); | |
| SmallVector<llvm::OperandBundleDef> BundleList = getBundlesForFunclet(F); | |
| if (isConvergentIntrinsic(F)) | |
| addConvergenceControlBundle(BundleList); | |
| return Builder.CreateCall(F, Args, BundleList, Name); | |
| } | |
| llvm::CallInst *CodeGenFunction::EmitIntrinsicCall(llvm::Intrinsic::ID ID, | |
| ArrayRef<llvm::Value *> Args, | |
| llvm::Type *RetTy, | |
| const llvm::Twine &Name) { | |
| SmallVector<llvm::Type *> ArgTys; | |
| ArgTys.reserve(Args.size()); | |
| for (llvm::Value *Arg : Args) | |
| ArgTys.push_back(Arg->getType()); | |
| llvm::Function *F = llvm::Intrinsic::getOrInsertDeclaration( | |
| &CGM.getModule(), ID, RetTy, ArgTys); | |
| SmallVector<llvm::OperandBundleDef> BundleList = getBundlesForFunclet(F); | |
| if (isConvergentIntrinsic(F)) | |
| addConvergenceControlBundle(BundleList); | |
| return Builder.CreateCall(F, Args, BundleList, Name); | |
| } | |
| /// Emits a call or invoke to the given noreturn runtime function. | |
| void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke( | |
| llvm::FunctionCallee callee, ArrayRef<llvm::Value *> args) { | |
| SmallVector<llvm::OperandBundleDef, 1> BundleList = | |
| getBundlesForFunclet(callee.getCallee()); | |
| if (getInvokeDest()) { | |
| llvm::InvokeInst *invoke = Builder.CreateInvoke( | |
| callee, getUnreachableBlock(), getInvokeDest(), args, BundleList); | |
| invoke->setDoesNotReturn(); | |
| invoke->setCallingConv(getRuntimeCC()); | |
| } else { | |
| llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList); | |
| call->setDoesNotReturn(); | |
| call->setCallingConv(getRuntimeCC()); | |
| Builder.CreateUnreachable(); | |
| } | |
| } | |
| /// Emits a call or invoke instruction to the given nullary runtime function. | |
| llvm::CallBase * | |
| CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, | |
| const Twine &name) { | |
| return EmitRuntimeCallOrInvoke(callee, {}, name); | |
| } | |
| /// Emits a call or invoke instruction to the given runtime function. | |
| llvm::CallBase * | |
| CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, | |
| ArrayRef<llvm::Value *> args, | |
| const Twine &name) { | |
| llvm::CallBase *call = EmitCallOrInvoke(callee, args, name); | |
| call->setCallingConv(getRuntimeCC()); | |
| return call; | |
| } | |
| /// Emits a call or invoke instruction to the given function, depending | |
| /// on the current state of the EH stack. | |
| llvm::CallBase *CodeGenFunction::EmitCallOrInvoke(llvm::FunctionCallee Callee, | |
| ArrayRef<llvm::Value *> Args, | |
| const Twine &Name) { | |
| llvm::BasicBlock *InvokeDest = getInvokeDest(); | |
| SmallVector<llvm::OperandBundleDef, 1> BundleList = | |
| getBundlesForFunclet(Callee.getCallee()); | |
| llvm::CallBase *Inst; | |
| if (!InvokeDest) | |
| Inst = Builder.CreateCall(Callee, Args, BundleList, Name); | |
| else { | |
| llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont"); | |
| Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, BundleList, | |
| Name); | |
| EmitBlock(ContBB); | |
| } | |
| // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC | |
| // optimizer it can aggressively ignore unwind edges. | |
| if (CGM.getLangOpts().ObjCAutoRefCount) | |
| AddObjCARCExceptionMetadata(Inst); | |
| return Inst; | |
| } | |
| void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old, | |
| llvm::Value *New) { | |
| DeferredReplacements.push_back( | |
| std::make_pair(llvm::WeakTrackingVH(Old), New)); | |
| } | |
| namespace { | |
| /// Specify given \p NewAlign as the alignment of return value attribute. If | |
| /// such attribute already exists, re-set it to the maximal one of two options. | |
| [[nodiscard]] llvm::AttributeList | |
| maybeRaiseRetAlignmentAttribute(llvm::LLVMContext &Ctx, | |
| const llvm::AttributeList &Attrs, | |
| llvm::Align NewAlign) { | |
| llvm::Align CurAlign = Attrs.getRetAlignment().valueOrOne(); | |
| if (CurAlign >= NewAlign) | |
| return Attrs; | |
| llvm::Attribute AlignAttr = llvm::Attribute::getWithAlignment(Ctx, NewAlign); | |
| return Attrs.removeRetAttribute(Ctx, llvm::Attribute::AttrKind::Alignment) | |
| .addRetAttribute(Ctx, AlignAttr); | |
| } | |
| template <typename AlignedAttrTy> class AbstractAssumeAlignedAttrEmitter { | |
| protected: | |
| CodeGenFunction &CGF; | |
| /// We do nothing if this is, or becomes, nullptr. | |
| const AlignedAttrTy *AA = nullptr; | |
| llvm::Value *Alignment = nullptr; // May or may not be a constant. | |
| llvm::ConstantInt *OffsetCI = nullptr; // Constant, hopefully zero. | |
| AbstractAssumeAlignedAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl) | |
| : CGF(CGF_) { | |
| if (!FuncDecl) | |
| return; | |
| AA = FuncDecl->getAttr<AlignedAttrTy>(); | |
| } | |
| public: | |
| /// If we can, materialize the alignment as an attribute on return value. | |
| [[nodiscard]] llvm::AttributeList | |
| TryEmitAsCallSiteAttribute(const llvm::AttributeList &Attrs) { | |
| if (!AA || OffsetCI || CGF.SanOpts.has(SanitizerKind::Alignment)) | |
| return Attrs; | |
| const auto *AlignmentCI = dyn_cast<llvm::ConstantInt>(Alignment); | |
| if (!AlignmentCI) | |
| return Attrs; | |
| // We may legitimately have non-power-of-2 alignment here. | |
| // If so, this is UB land, emit it via `@llvm.assume` instead. | |
| if (!AlignmentCI->getValue().isPowerOf2()) | |
| return Attrs; | |
| llvm::AttributeList NewAttrs = maybeRaiseRetAlignmentAttribute( | |
| CGF.getLLVMContext(), Attrs, | |
| llvm::Align( | |
| AlignmentCI->getLimitedValue(llvm::Value::MaximumAlignment))); | |
| AA = nullptr; // We're done. Disallow doing anything else. | |
| return NewAttrs; | |
| } | |
| /// Emit alignment assumption. | |
| /// This is a general fallback that we take if either there is an offset, | |
| /// or the alignment is variable or we are sanitizing for alignment. | |
| void EmitAsAnAssumption(SourceLocation Loc, QualType RetTy, RValue &Ret) { | |
| if (!AA) | |
| return; | |
| CGF.emitAlignmentAssumption(Ret.getScalarVal(), RetTy, Loc, | |
| AA->getLocation(), Alignment, OffsetCI); | |
| AA = nullptr; // We're done. Disallow doing anything else. | |
| } | |
| }; | |
| /// Helper data structure to emit `AssumeAlignedAttr`. | |
| class AssumeAlignedAttrEmitter final | |
| : public AbstractAssumeAlignedAttrEmitter<AssumeAlignedAttr> { | |
| public: | |
| AssumeAlignedAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl) | |
| : AbstractAssumeAlignedAttrEmitter(CGF_, FuncDecl) { | |
| if (!AA) | |
| return; | |
| // It is guaranteed that the alignment/offset are constants. | |
| Alignment = cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AA->getAlignment())); | |
| if (Expr *Offset = AA->getOffset()) { | |
| OffsetCI = cast<llvm::ConstantInt>(CGF.EmitScalarExpr(Offset)); | |
| if (OffsetCI->isNullValue()) // Canonicalize zero offset to no offset. | |
| OffsetCI = nullptr; | |
| } | |
| } | |
| }; | |
| /// Helper data structure to emit `AllocAlignAttr`. | |
| class AllocAlignAttrEmitter final | |
| : public AbstractAssumeAlignedAttrEmitter<AllocAlignAttr> { | |
| public: | |
| AllocAlignAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl, | |
| const CallArgList &CallArgs) | |
| : AbstractAssumeAlignedAttrEmitter(CGF_, FuncDecl) { | |
| if (!AA) | |
| return; | |
| // Alignment may or may not be a constant, and that is okay. | |
| Alignment = CallArgs[AA->getParamIndex().getLLVMIndex()] | |
| .getRValue(CGF) | |
| .getScalarVal(); | |
| } | |
| }; | |
| } // namespace | |
| static unsigned getMaxVectorWidth(const llvm::Type *Ty) { | |
| if (auto *VT = dyn_cast<llvm::VectorType>(Ty)) | |
| return VT->getPrimitiveSizeInBits().getKnownMinValue(); | |
| if (auto *AT = dyn_cast<llvm::ArrayType>(Ty)) | |
| return getMaxVectorWidth(AT->getElementType()); | |
| unsigned MaxVectorWidth = 0; | |
| if (auto *ST = dyn_cast<llvm::StructType>(Ty)) | |
| for (auto *I : ST->elements()) | |
| MaxVectorWidth = std::max(MaxVectorWidth, getMaxVectorWidth(I)); | |
| return MaxVectorWidth; | |
| } | |
| RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, | |
| const CGCallee &Callee, | |
| ReturnValueSlot ReturnValue, | |
| const CallArgList &CallArgs, | |
| llvm::CallBase **callOrInvoke, bool IsMustTail, | |
| SourceLocation Loc, | |
| bool IsVirtualFunctionPointerThunk) { | |
| // FIXME: We no longer need the types from CallArgs; lift up and simplify. | |
| assert(Callee.isOrdinary() || Callee.isVirtual()); | |
| // Handle struct-return functions by passing a pointer to the | |
| // location that we would like to return into. | |
| QualType RetTy = CallInfo.getReturnType(); | |
| const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); | |
| llvm::FunctionType *IRFuncTy = getTypes().GetFunctionType(CallInfo); | |
| const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl(); | |
| if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) { | |
| // We can only guarantee that a function is called from the correct | |
| // context/function based on the appropriate target attributes, | |
| // so only check in the case where we have both always_inline and target | |
| // since otherwise we could be making a conditional call after a check for | |
| // the proper cpu features (and it won't cause code generation issues due to | |
| // function based code generation). | |
| if ((TargetDecl->hasAttr<AlwaysInlineAttr>() && | |
| (TargetDecl->hasAttr<TargetAttr>() || | |
| (CurFuncDecl && CurFuncDecl->hasAttr<TargetAttr>()))) || | |
| (CurFuncDecl && CurFuncDecl->hasAttr<FlattenAttr>() && | |
| (CurFuncDecl->hasAttr<TargetAttr>() || | |
| TargetDecl->hasAttr<TargetAttr>()))) | |
| checkTargetFeatures(Loc, FD); | |
| } | |
| // Some architectures (such as x86-64) have the ABI changed based on | |
| // attribute-target/features. Give them a chance to diagnose. | |
| const FunctionDecl *CallerDecl = dyn_cast_or_null<FunctionDecl>(CurCodeDecl); | |
| const FunctionDecl *CalleeDecl = dyn_cast_or_null<FunctionDecl>(TargetDecl); | |
| CGM.getTargetCodeGenInfo().checkFunctionCallABI(CGM, Loc, CallerDecl, | |
| CalleeDecl, CallArgs, RetTy); | |
| // 1. Set up the arguments. | |
| // If we're using inalloca, insert the allocation after the stack save. | |
| // FIXME: Do this earlier rather than hacking it in here! | |
| RawAddress ArgMemory = RawAddress::invalid(); | |
| if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { | |
| const llvm::DataLayout &DL = CGM.getDataLayout(); | |
| llvm::Instruction *IP = CallArgs.getStackBase(); | |
| llvm::AllocaInst *AI; | |
| if (IP) { | |
| IP = IP->getNextNode(); | |
| AI = new llvm::AllocaInst(ArgStruct, DL.getAllocaAddrSpace(), "argmem", | |
| IP->getIterator()); | |
| } else { | |
| AI = CreateTempAlloca(ArgStruct, "argmem"); | |
| } | |
| auto Align = CallInfo.getArgStructAlignment(); | |
| AI->setAlignment(Align.getAsAlign()); | |
| AI->setUsedWithInAlloca(true); | |
| assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); | |
| ArgMemory = RawAddress(AI, ArgStruct, Align); | |
| } | |
| ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo); | |
| SmallVector<llvm::Value *, 16> IRCallArgs(IRFunctionArgs.totalIRArgs()); | |
| // If the call returns a temporary with struct return, create a temporary | |
| // alloca to hold the result, unless one is given to us. | |
| Address SRetPtr = Address::invalid(); | |
| // Original alloca for lifetime markers | |
| Address SRetAlloca = Address::invalid(); | |
| bool NeedSRetLifetimeEnd = false; | |
| if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { | |
| // For virtual function pointer thunks and musttail calls, we must always | |
| // forward an incoming SRet pointer to the callee, because a local alloca | |
| // would be de-allocated before the call. These cases both guarantee that | |
| // there will be an incoming SRet argument of the correct type. | |
| if ((IsVirtualFunctionPointerThunk || IsMustTail) && RetAI.isIndirect()) { | |
| SRetPtr = makeNaturalAddressForPointer(CurFn->arg_begin() + | |
| IRFunctionArgs.getSRetArgNo(), | |
| RetTy, CharUnits::fromQuantity(1)); | |
| } else if (!ReturnValue.isNull()) { | |
| SRetPtr = ReturnValue.getAddress(); | |
| } else { | |
| SRetPtr = CreateMemTempWithoutCast(RetTy, "tmp"); | |
| if (HaveInsertPoint() && ReturnValue.isUnused()) { | |
| NeedSRetLifetimeEnd = EmitLifetimeStart(SRetPtr.getBasePointer()); | |
| if (NeedSRetLifetimeEnd) | |
| SRetAlloca = SRetPtr; | |
| } | |
| } | |
| if (IRFunctionArgs.hasSRetArg()) { | |
| // A mismatch between the allocated return value's AS and the target's | |
| // chosen IndirectAS can happen e.g. when passing the this pointer through | |
| // a chain involving stores to / loads from the DefaultAS; we address this | |
| // here, symmetrically with the handling we have for normal pointer args. | |
| if (SRetPtr.getAddressSpace() != RetAI.getIndirectAddrSpace()) { | |
| llvm::Value *V = SRetPtr.getBasePointer(); | |
| llvm::Type *Ty = llvm::PointerType::get(getLLVMContext(), | |
| RetAI.getIndirectAddrSpace()); | |
| SRetPtr = SRetPtr.withPointer(performAddrSpaceCast(V, Ty), | |
| SRetPtr.isKnownNonNull()); | |
| } | |
| IRCallArgs[IRFunctionArgs.getSRetArgNo()] = | |
| getAsNaturalPointerTo(SRetPtr, RetTy); | |
| } else if (RetAI.isInAlloca()) { | |
| Address Addr = | |
| Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex()); | |
| Builder.CreateStore(getAsNaturalPointerTo(SRetPtr, RetTy), Addr); | |
| } | |
| } | |
| RawAddress swiftErrorTemp = RawAddress::invalid(); | |
| Address swiftErrorArg = Address::invalid(); | |
| // When passing arguments using temporary allocas, we need to add the | |
| // appropriate lifetime markers. This vector keeps track of all the lifetime | |
| // markers that need to be ended right after the call. | |
| SmallVector<llvm::Value *, 2> CallLifetimeEndAfterCall; | |
| // Translate all of the arguments as necessary to match the IR lowering. | |
| assert(CallInfo.arg_size() == CallArgs.size() && | |
| "Mismatch between function signature & arguments."); | |
| unsigned ArgNo = 0; | |
| CGFunctionInfo::const_arg_iterator info_it = CallInfo.arg_begin(); | |
| for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end(); | |
| I != E; ++I, ++info_it, ++ArgNo) { | |
| const ABIArgInfo &ArgInfo = info_it->info; | |
| // Insert a padding argument to ensure proper alignment. | |
| if (IRFunctionArgs.hasPaddingArg(ArgNo)) | |
| IRCallArgs[IRFunctionArgs.getPaddingArgNo(ArgNo)] = | |
| llvm::UndefValue::get(ArgInfo.getPaddingType()); | |
| unsigned FirstIRArg, NumIRArgs; | |
| std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); | |
| bool ArgHasMaybeUndefAttr = | |
| IsArgumentMaybeUndef(TargetDecl, CallInfo.getNumRequiredArgs(), ArgNo); | |
| switch (ArgInfo.getKind()) { | |
| case ABIArgInfo::InAlloca: { | |
| assert(NumIRArgs == 0); | |
| assert(getTarget().getTriple().getArch() == llvm::Triple::x86); | |
| if (I->isAggregate()) { | |
| RawAddress Addr = I->hasLValue() | |
| ? I->getKnownLValue().getAddress() | |
| : I->getKnownRValue().getAggregateAddress(); | |
| llvm::Instruction *Placeholder = | |
| cast<llvm::Instruction>(Addr.getPointer()); | |
| if (!ArgInfo.getInAllocaIndirect()) { | |
| // Replace the placeholder with the appropriate argument slot GEP. | |
| CGBuilderTy::InsertPoint IP = Builder.saveIP(); | |
| Builder.SetInsertPoint(Placeholder); | |
| Addr = Builder.CreateStructGEP(ArgMemory, | |
| ArgInfo.getInAllocaFieldIndex()); | |
| Builder.restoreIP(IP); | |
| } else { | |
| // For indirect things such as overaligned structs, replace the | |
| // placeholder with a regular aggregate temporary alloca. Store the | |
| // address of this alloca into the struct. | |
| Addr = | |
| CreateMemTempWithoutCast(info_it->type, "inalloca.indirect.tmp"); | |
| Address ArgSlot = Builder.CreateStructGEP( | |
| ArgMemory, ArgInfo.getInAllocaFieldIndex()); | |
| Builder.CreateStore(Addr.getPointer(), ArgSlot); | |
| } | |
| deferPlaceholderReplacement(Placeholder, Addr.getPointer()); | |
| } else if (ArgInfo.getInAllocaIndirect()) { | |
| // Make a temporary alloca and store the address of it into the argument | |
| // struct. | |
| RawAddress Addr = CreateMemTempWithoutCast( | |
| I->Ty, getContext().getTypeAlignInChars(I->Ty), | |
| "indirect-arg-temp"); | |
| I->copyInto(*this, Addr); | |
| Address ArgSlot = | |
| Builder.CreateStructGEP(ArgMemory, ArgInfo.getInAllocaFieldIndex()); | |
| Builder.CreateStore(Addr.getPointer(), ArgSlot); | |
| } else { | |
| // Store the RValue into the argument struct. | |
| Address Addr = | |
| Builder.CreateStructGEP(ArgMemory, ArgInfo.getInAllocaFieldIndex()); | |
| Addr = Addr.withElementType(ConvertTypeForMem(I->Ty)); | |
| I->copyInto(*this, Addr); | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::Indirect: | |
| case ABIArgInfo::IndirectAliased: { | |
| assert(NumIRArgs == 1); | |
| if (I->isAggregate()) { | |
| // We want to avoid creating an unnecessary temporary+copy here; | |
| // however, we need one in three cases: | |
| // 1. If the argument is not byval, and we are required to copy the | |
| // source. (This case doesn't occur on any common architecture.) | |
| // 2. If the argument is byval, RV is not sufficiently aligned, and | |
| // we cannot force it to be sufficiently aligned. | |
| // 3. If the argument is byval, but RV is not located in default | |
| // or alloca address space. | |
| Address Addr = I->hasLValue() | |
| ? I->getKnownLValue().getAddress() | |
| : I->getKnownRValue().getAggregateAddress(); | |
| CharUnits Align = ArgInfo.getIndirectAlign(); | |
| const llvm::DataLayout *TD = &CGM.getDataLayout(); | |
| assert((FirstIRArg >= IRFuncTy->getNumParams() || | |
| IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace() == | |
| TD->getAllocaAddrSpace()) && | |
| "indirect argument must be in alloca address space"); | |
| bool NeedCopy = false; | |
| if (Addr.getAlignment() < Align && | |
| llvm::getOrEnforceKnownAlignment(Addr.emitRawPointer(*this), | |
| Align.getAsAlign(), | |
| *TD) < Align.getAsAlign()) { | |
| NeedCopy = true; | |
| } else if (I->hasLValue()) { | |
| auto LV = I->getKnownLValue(); | |
| bool isByValOrRef = | |
| ArgInfo.isIndirectAliased() || ArgInfo.getIndirectByVal(); | |
| if (!isByValOrRef || | |
| (LV.getAlignment() < getContext().getTypeAlignInChars(I->Ty))) { | |
| NeedCopy = true; | |
| } | |
| if (isByValOrRef && Addr.getType()->getAddressSpace() != | |
| ArgInfo.getIndirectAddrSpace()) { | |
| NeedCopy = true; | |
| } | |
| } | |
| if (!NeedCopy) { | |
| // Skip the extra memcpy call. | |
| llvm::Value *V = getAsNaturalPointerTo(Addr, I->Ty); | |
| auto *T = llvm::PointerType::get(CGM.getLLVMContext(), | |
| ArgInfo.getIndirectAddrSpace()); | |
| // FIXME: This should not depend on the language address spaces, and | |
| // only the contextual values. If the address space mismatches, see if | |
| // we can look through a cast to a compatible address space value, | |
| // otherwise emit a copy. | |
| llvm::Value *Val = performAddrSpaceCast(V, T); | |
| if (ArgHasMaybeUndefAttr) | |
| Val = Builder.CreateFreeze(Val); | |
| IRCallArgs[FirstIRArg] = Val; | |
| break; | |
| } | |
| } else if (I->getType()->isArrayParameterType()) { | |
| // Don't produce a temporary for ArrayParameterType arguments. | |
| // ArrayParameterType arguments are only created from | |
| // HLSL_ArrayRValue casts and HLSLOutArgExpr expressions, both | |
| // of which create temporaries already. This allows us to just use the | |
| // scalar for the decayed array pointer as the argument directly. | |
| IRCallArgs[FirstIRArg] = I->getKnownRValue().getScalarVal(); | |
| break; | |
| } | |
| // For non-aggregate args and aggregate args meeting conditions above | |
| // we need to create an aligned temporary, and copy to it. | |
| RawAddress AI = CreateMemTempWithoutCast( | |
| I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); | |
| llvm::Value *Val = getAsNaturalPointerTo(AI, I->Ty); | |
| if (ArgHasMaybeUndefAttr) | |
| Val = Builder.CreateFreeze(Val); | |
| IRCallArgs[FirstIRArg] = Val; | |
| // Emit lifetime markers for the temporary alloca and add cleanup code to | |
| // emit the end lifetime marker after the call. | |
| if (EmitLifetimeStart(AI.getPointer())) | |
| CallLifetimeEndAfterCall.push_back(AI.getPointer()); | |
| // Generate the copy. | |
| I->copyInto(*this, AI); | |
| break; | |
| } | |
| case ABIArgInfo::Ignore: | |
| assert(NumIRArgs == 0); | |
| break; | |
| case ABIArgInfo::Extend: | |
| case ABIArgInfo::Direct: { | |
| if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) && | |
| ArgInfo.getCoerceToType() == ConvertType(info_it->type) && | |
| ArgInfo.getDirectOffset() == 0) { | |
| assert(NumIRArgs == 1); | |
| llvm::Value *V; | |
| if (!I->isAggregate()) | |
| V = I->getKnownRValue().getScalarVal(); | |
| else | |
| V = Builder.CreateLoad( | |
| I->hasLValue() ? I->getKnownLValue().getAddress() | |
| : I->getKnownRValue().getAggregateAddress()); | |
| // Implement swifterror by copying into a new swifterror argument. | |
| // We'll write back in the normal path out of the call. | |
| if (CallInfo.getExtParameterInfo(ArgNo).getABI() == | |
| ParameterABI::SwiftErrorResult) { | |
| assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); | |
| QualType pointeeTy = I->Ty->getPointeeType(); | |
| swiftErrorArg = makeNaturalAddressForPointer( | |
| V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); | |
| swiftErrorTemp = CreateMemTempWithoutCast( | |
| pointeeTy, getPointerAlign(), "swifterror.temp"); | |
| V = swiftErrorTemp.getPointer(); | |
| cast<llvm::AllocaInst>(V)->setSwiftError(true); | |
| llvm::Value *errorValue = Builder.CreateLoad(swiftErrorArg); | |
| Builder.CreateStore(errorValue, swiftErrorTemp); | |
| } | |
| // We might have to widen integers, but we should never truncate. | |
| if (ArgInfo.getCoerceToType() != V->getType() && | |
| V->getType()->isIntegerTy()) | |
| V = Builder.CreateZExt(V, ArgInfo.getCoerceToType()); | |
| // The only plausible mismatch here would be for pointer address spaces. | |
| // We assume that the target has a reasonable mapping for the DefaultAS | |
| // (it can be casted to from incoming specific ASes), and insert an AS | |
| // cast to address the mismatch. | |
| if (FirstIRArg < IRFuncTy->getNumParams() && | |
| V->getType() != IRFuncTy->getParamType(FirstIRArg)) { | |
| assert(V->getType()->isPointerTy() && "Only pointers can mismatch!"); | |
| V = performAddrSpaceCast(V, IRFuncTy->getParamType(FirstIRArg)); | |
| } | |
| if (ArgHasMaybeUndefAttr) | |
| V = Builder.CreateFreeze(V); | |
| IRCallArgs[FirstIRArg] = V; | |
| break; | |
| } | |
| llvm::StructType *STy = | |
| dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType()); | |
| // FIXME: Avoid the conversion through memory if possible. | |
| Address Src = Address::invalid(); | |
| if (!I->isAggregate()) { | |
| Src = CreateMemTempWithoutCast(I->Ty, "coerce"); | |
| I->copyInto(*this, Src); | |
| } else { | |
| Src = I->hasLValue() ? I->getKnownLValue().getAddress() | |
| : I->getKnownRValue().getAggregateAddress(); | |
| } | |
| // If the value is offset in memory, apply the offset now. | |
| Src = emitAddressAtOffset(*this, Src, ArgInfo); | |
| // Fast-isel and the optimizer generally like scalar values better than | |
| // FCAs, so we flatten them if this is safe to do for this argument. | |
| if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) { | |
| llvm::Type *SrcTy = Src.getElementType(); | |
| llvm::TypeSize SrcTypeSize = | |
| CGM.getDataLayout().getTypeAllocSize(SrcTy); | |
| llvm::TypeSize DstTypeSize = CGM.getDataLayout().getTypeAllocSize(STy); | |
| if (SrcTypeSize.isScalable()) { | |
| assert(STy->containsHomogeneousScalableVectorTypes() && | |
| "ABI only supports structure with homogeneous scalable vector " | |
| "type"); | |
| assert(SrcTypeSize == DstTypeSize && | |
| "Only allow non-fractional movement of structure with " | |
| "homogeneous scalable vector type"); | |
| assert(NumIRArgs == STy->getNumElements()); | |
| llvm::Value *StoredStructValue = | |
| Builder.CreateLoad(Src, Src.getName() + ".tuple"); | |
| for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { | |
| llvm::Value *Extract = Builder.CreateExtractValue( | |
| StoredStructValue, i, Src.getName() + ".extract" + Twine(i)); | |
| IRCallArgs[FirstIRArg + i] = Extract; | |
| } | |
| } else { | |
| uint64_t SrcSize = SrcTypeSize.getFixedValue(); | |
| uint64_t DstSize = DstTypeSize.getFixedValue(); | |
| bool HasPFPFields = getContext().hasPFPFields(I->Ty); | |
| // If the source type is smaller than the destination type of the | |
| // coerce-to logic, copy the source value into a temp alloca the size | |
| // of the destination type to allow loading all of it. The bits past | |
| // the source value are left undef. | |
| if (HasPFPFields || SrcSize < DstSize) { | |
| Address TempAlloca = CreateTempAlloca(STy, Src.getAlignment(), | |
| Src.getName() + ".coerce"); | |
| if (HasPFPFields) { | |
| // Structures with PFP fields require a coerced load to remove any | |
| // pointer signatures. | |
| Builder.CreateStore( | |
| CreatePFPCoercedLoad(Src, I->Ty, ArgInfo.getCoerceToType(), | |
| *this), | |
| TempAlloca); | |
| } else | |
| Builder.CreateMemCpy(TempAlloca, Src, SrcSize); | |
| Src = TempAlloca; | |
| } else { | |
| Src = Src.withElementType(STy); | |
| } | |
| assert(NumIRArgs == STy->getNumElements()); | |
| for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { | |
| Address EltPtr = Builder.CreateStructGEP(Src, i); | |
| llvm::Value *LI = Builder.CreateLoad(EltPtr); | |
| if (ArgHasMaybeUndefAttr) | |
| LI = Builder.CreateFreeze(LI); | |
| IRCallArgs[FirstIRArg + i] = LI; | |
| } | |
| } | |
| } else { | |
| // In the simple case, just pass the coerced loaded value. | |
| assert(NumIRArgs == 1); | |
| llvm::Value *Load = | |
| CreateCoercedLoad(Src, I->Ty, ArgInfo.getCoerceToType(), *this); | |
| if (CallInfo.isCmseNSCall()) { | |
| // For certain parameter types, clear padding bits, as they may reveal | |
| // sensitive information. | |
| // Small struct/union types are passed as integer arrays. | |
| auto *ATy = dyn_cast<llvm::ArrayType>(Load->getType()); | |
| if (ATy != nullptr && isa<RecordType>(I->Ty.getCanonicalType())) | |
| Load = EmitCMSEClearRecord(Load, ATy, I->Ty); | |
| } | |
| if (ArgHasMaybeUndefAttr) | |
| Load = Builder.CreateFreeze(Load); | |
| IRCallArgs[FirstIRArg] = Load; | |
| } | |
| break; | |
| } | |
| case ABIArgInfo::CoerceAndExpand: { | |
| auto coercionType = ArgInfo.getCoerceAndExpandType(); | |
| auto layout = CGM.getDataLayout().getStructLayout(coercionType); | |
| auto unpaddedCoercionType = ArgInfo.getUnpaddedCoerceAndExpandType(); | |
| auto *unpaddedStruct = dyn_cast<llvm::StructType>(unpaddedCoercionType); | |
| Address addr = Address::invalid(); | |
| RawAddress AllocaAddr = RawAddress::invalid(); | |
| bool NeedLifetimeEnd = false; | |
| if (I->isAggregate()) { | |
| addr = I->hasLValue() ? I->getKnownLValue().getAddress() | |
| : I->getKnownRValue().getAggregateAddress(); | |
| } else { | |
| RValue RV = I->getKnownRValue(); | |
| assert(RV.isScalar()); // complex should always just be direct | |
| llvm::Type *scalarType = RV.getScalarVal()->getType(); | |
| auto scalarAlign = CGM.getDataLayout().getPrefTypeAlign(scalarType); | |
| // Materialize to a temporary. | |
| addr = CreateTempAlloca(RV.getScalarVal()->getType(), | |
| CharUnits::fromQuantity(std::max( | |
| layout->getAlignment(), scalarAlign)), | |
| "tmp", | |
| /*ArraySize=*/nullptr, &AllocaAddr); | |
| NeedLifetimeEnd = EmitLifetimeStart(AllocaAddr.getPointer()); | |
| Builder.CreateStore(RV.getScalarVal(), addr); | |
| } | |
| addr = addr.withElementType(coercionType); | |
| unsigned IRArgPos = FirstIRArg; | |
| unsigned unpaddedIndex = 0; | |
| for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { | |
| llvm::Type *eltType = coercionType->getElementType(i); | |
| if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) | |
| continue; | |
| Address eltAddr = Builder.CreateStructGEP(addr, i); | |
| llvm::Value *elt = CreateCoercedLoad( | |
| eltAddr, I->Ty, | |
| unpaddedStruct ? unpaddedStruct->getElementType(unpaddedIndex++) | |
| : unpaddedCoercionType, | |
| *this); | |
| if (ArgHasMaybeUndefAttr) | |
| elt = Builder.CreateFreeze(elt); | |
| IRCallArgs[IRArgPos++] = elt; | |
| } | |
| assert(IRArgPos == FirstIRArg + NumIRArgs); | |
| if (NeedLifetimeEnd) | |
| EmitLifetimeEnd(AllocaAddr.getPointer()); | |
| break; | |
| } | |
| case ABIArgInfo::Expand: { | |
| unsigned IRArgPos = FirstIRArg; | |
| ExpandTypeToArgs(I->Ty, *I, IRFuncTy, IRCallArgs, IRArgPos); | |
| assert(IRArgPos == FirstIRArg + NumIRArgs); | |
| break; | |
| } | |
| case ABIArgInfo::TargetSpecific: { | |
| Address Src = Address::invalid(); | |
| if (!I->isAggregate()) { | |
| Src = CreateMemTempWithoutCast(I->Ty, "target_coerce"); | |
| I->copyInto(*this, Src); | |
| } else { | |
| Src = I->hasLValue() ? I->getKnownLValue().getAddress() | |
| : I->getKnownRValue().getAggregateAddress(); | |
| } | |
| // If the value is offset in memory, apply the offset now. | |
| Src = emitAddressAtOffset(*this, Src, ArgInfo); | |
| llvm::Value *Load = | |
| CGM.getABIInfo().createCoercedLoad(Src, ArgInfo, *this); | |
| IRCallArgs[FirstIRArg] = Load; | |
| break; | |
| } | |
| } | |
| } | |
| const CGCallee &ConcreteCallee = Callee.prepareConcreteCallee(*this); | |
| llvm::Value *CalleePtr = ConcreteCallee.getFunctionPointer(); | |
| // If we're using inalloca, set up that argument. | |
| if (ArgMemory.isValid()) { | |
| llvm::Value *Arg = ArgMemory.getPointer(); | |
| assert(IRFunctionArgs.hasInallocaArg()); | |
| IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg; | |
| } | |
| // 2. Prepare the function pointer. | |
| // If the callee is a bitcast of a non-variadic function to have a | |
| // variadic function pointer type, check to see if we can remove the | |
| // bitcast. This comes up with unprototyped functions. | |
| // | |
| // This makes the IR nicer, but more importantly it ensures that we | |
| // can inline the function at -O0 if it is marked always_inline. | |
| auto simplifyVariadicCallee = [](llvm::FunctionType *CalleeFT, | |
| llvm::Value *Ptr) -> llvm::Function * { | |
| if (!CalleeFT->isVarArg()) | |
| return nullptr; | |
| // Get underlying value if it's a bitcast | |
| if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr)) { | |
| if (CE->getOpcode() == llvm::Instruction::BitCast) | |
| Ptr = CE->getOperand(0); | |
| } | |
| llvm::Function *OrigFn = dyn_cast<llvm::Function>(Ptr); | |
| if (!OrigFn) | |
| return nullptr; | |
| llvm::FunctionType *OrigFT = OrigFn->getFunctionType(); | |
| // If the original type is variadic, or if any of the component types | |
| // disagree, we cannot remove the cast. | |
| if (OrigFT->isVarArg() || | |
| OrigFT->getNumParams() != CalleeFT->getNumParams() || | |
| OrigFT->getReturnType() != CalleeFT->getReturnType()) | |
| return nullptr; | |
| for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i) | |
| if (OrigFT->getParamType(i) != CalleeFT->getParamType(i)) | |
| return nullptr; | |
| return OrigFn; | |
| }; | |
| if (llvm::Function *OrigFn = simplifyVariadicCallee(IRFuncTy, CalleePtr)) { | |
| CalleePtr = OrigFn; | |
| IRFuncTy = OrigFn->getFunctionType(); | |
| } | |
| // 3. Perform the actual call. | |
| // Deactivate any cleanups that we're supposed to do immediately before | |
| // the call. | |
| if (!CallArgs.getCleanupsToDeactivate().empty()) | |
| deactivateArgCleanupsBeforeCall(*this, CallArgs); | |
| // Update the largest vector width if any arguments have vector types. | |
| for (unsigned i = 0; i < IRCallArgs.size(); ++i) | |
| LargestVectorWidth = std::max(LargestVectorWidth, | |
| getMaxVectorWidth(IRCallArgs[i]->getType())); | |
| // Compute the calling convention and attributes. | |
| unsigned CallingConv; | |
| llvm::AttributeList Attrs; | |
| CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo, | |
| Callee.getAbstractInfo(), Attrs, CallingConv, | |
| /*AttrOnCallSite=*/true, | |
| /*IsThunk=*/false); | |
| if (CallingConv == llvm::CallingConv::X86_VectorCall && | |
| getTarget().getTriple().isWindowsArm64EC()) { | |
| CGM.Error(Loc, "__vectorcall calling convention is not currently " | |
| "supported"); | |
| } | |
| if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) { | |
| if (FD->hasAttr<StrictFPAttr>()) | |
| // All calls within a strictfp function are marked strictfp | |
| Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::StrictFP); | |
| // If -ffast-math is enabled and the function is guarded by an | |
| // '__attribute__((optnone)) adjust the memory attribute so the BE emits the | |
| // library call instead of the intrinsic. | |
| if (FD->hasAttr<OptimizeNoneAttr>() && getLangOpts().FastMath) | |
| CGM.AdjustMemoryAttribute(CalleePtr->getName(), Callee.getAbstractInfo(), | |
| Attrs); | |
| } | |
| // Add call-site nomerge attribute if exists. | |
| if (InNoMergeAttributedStmt) | |
| Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoMerge); | |
| // Add call-site noinline attribute if exists. | |
| if (InNoInlineAttributedStmt) | |
| Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoInline); | |
| // Add call-site always_inline attribute if exists. | |
| // Note: This corresponds to the [[clang::always_inline]] statement attribute. | |
| if (InAlwaysInlineAttributedStmt && | |
| !CGM.getTargetCodeGenInfo().wouldInliningViolateFunctionCallABI( | |
| CallerDecl, CalleeDecl)) | |
| Attrs = | |
| Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline); | |
| // Apply some call-site-specific attributes. | |
| // TODO: work this into building the attribute set. | |
| // Apply always_inline to all calls within flatten functions. | |
| // FIXME: should this really take priority over __try, below? | |
| if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() && | |
| !InNoInlineAttributedStmt && | |
| !(TargetDecl && TargetDecl->hasAttr<NoInlineAttr>()) && | |
| !CGM.getTargetCodeGenInfo().wouldInliningViolateFunctionCallABI( | |
| CallerDecl, CalleeDecl)) { | |
| Attrs = | |
| Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline); | |
| } | |
| // Disable inlining inside SEH __try blocks. | |
| if (isSEHTryScope()) { | |
| Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoInline); | |
| } | |
| // Decide whether to use a call or an invoke. | |
| bool CannotThrow; | |
| if (currentFunctionUsesSEHTry()) { | |
| // SEH cares about asynchronous exceptions, so everything can "throw." | |
| CannotThrow = false; | |
| } else if (isCleanupPadScope() && | |
| getEHPersonality(*this).isMSVCXXPersonality()) { | |
| // The MSVC++ personality will implicitly terminate the program if an | |
| // exception is thrown during a cleanup outside of a try/catch. | |
| // We don't need to model anything in IR to get this behavior. | |
| CannotThrow = true; | |
| } else { | |
| // Otherwise, nounwind call sites will never throw. | |
| CannotThrow = Attrs.hasFnAttr(llvm::Attribute::NoUnwind); | |
| if (auto *FPtr = dyn_cast<llvm::Function>(CalleePtr)) | |
| if (FPtr->hasFnAttribute(llvm::Attribute::NoUnwind)) | |
| CannotThrow = true; | |
| } | |
| // If we made a temporary, be sure to clean up after ourselves. Note that we | |
| // can't depend on being inside of an ExprWithCleanups, so we need to manually | |
| // pop this cleanup later on. Being eager about this is OK, since this | |
| // temporary is 'invisible' outside of the callee. | |
| // Use the original alloca pointer (before any addrspacecast) for the | |
| // lifetime end marker, since lifetime intrinsics must reference the alloca | |
| // address space. | |
| if (NeedSRetLifetimeEnd) | |
| pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca); | |
| llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); | |
| SmallVector<llvm::OperandBundleDef, 1> BundleList = | |
| getBundlesForFunclet(CalleePtr); | |
| if (SanOpts.has(SanitizerKind::KCFI) && | |
| !isa_and_nonnull<FunctionDecl>(TargetDecl)) | |
| EmitKCFIOperandBundle(ConcreteCallee, BundleList); | |
| // Add the pointer-authentication bundle. | |
| EmitPointerAuthOperandBundle(ConcreteCallee.getPointerAuthInfo(), BundleList); | |
| if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) | |
| if (FD->hasAttr<StrictFPAttr>()) | |
| // All calls within a strictfp function are marked strictfp | |
| Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::StrictFP); | |
| AssumeAlignedAttrEmitter AssumeAlignedAttrEmitter(*this, TargetDecl); | |
| Attrs = AssumeAlignedAttrEmitter.TryEmitAsCallSiteAttribute(Attrs); | |
| AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs); | |
| Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs); | |
| if (Attrs.hasFnAttr(llvm::Attribute::Convergent)) { | |
| addConvergenceControlBundle(BundleList); | |
| // Remove call-site convergent attribute if requested, unless the call must | |
| // stay convergent to match its convergence token and the callee doesn't | |
| // already make it convergent. | |
| // | |
| // FIXME: This means [[clang::noconvergent]] can't make an indirect call | |
| // non-convergent when using convergence tokens. A call without a token can | |
| // later be made direct to a convergent function, which mixes controlled | |
| // and uncontrolled convergence and fails the verifier. | |
| auto *CalleeFn = dyn_cast<llvm::Function>(CalleePtr); | |
| if (InNoConvergentAttributedStmt && | |
| (!CGM.shouldEmitConvergenceTokens() || | |
| (CalleeFn && CalleeFn->isConvergent()))) { | |
| Attrs = Attrs.removeFnAttribute(getLLVMContext(), | |
| llvm::Attribute::Convergent); | |
| } | |
| } | |
| // Emit the actual call/invoke instruction. | |
| llvm::CallBase *CI; | |
| if (!InvokeDest) { | |
| CI = Builder.CreateCall(IRFuncTy, CalleePtr, IRCallArgs, BundleList); | |
| } else { | |
| llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); | |
| CI = Builder.CreateInvoke(IRFuncTy, CalleePtr, Cont, InvokeDest, IRCallArgs, | |
| BundleList); | |
| EmitBlock(Cont); | |
| } | |
| if (CI->getCalledFunction() && CI->getCalledFunction()->hasName() && | |
| CI->getCalledFunction()->getName().starts_with("_Z4sqrt")) { | |
| SetSqrtFPAccuracy(CI); | |
| } | |
| if (callOrInvoke) { | |
| *callOrInvoke = CI; | |
| if (CGM.getCodeGenOpts().CallGraphSection) { | |
| QualType CST; | |
| if (TargetDecl && TargetDecl->getFunctionType()) | |
| CST = QualType(TargetDecl->getFunctionType(), 0); | |
| else if (const auto *FPT = | |
| Callee.getAbstractInfo().getCalleeFunctionProtoType()) | |
| CST = QualType(FPT, 0); | |
| else if (const auto *FT = | |
| Callee.getAbstractInfo().getCalleeFunctionType()) | |
| CST = QualType(FT, 0); | |
| else | |
| llvm_unreachable( | |
| "Cannot find the callee type to generate callee_type metadata."); | |
| // Set type identifier metadata of indirect calls for call graph section. | |
| if (!CST.isNull()) { | |
| if (!CST->isFunctionProtoType()) { | |
| // Reconstruct a prototype for unprototyped callees from the argument | |
| // types passed at the call site (after default argument promotion). | |
| // | |
| // Basic Rationale & K&R-Style Definitions: | |
| // The argument types in CallArgs have already undergone C default | |
| // argument promotion (e.g., char/short -> int, float -> double). | |
| // Furthermore, for a K&R-style | |
| // definition (e.g., void foo(x) short x; { ... }), canonical C ABI | |
| // semantics expect the promoted type (int) at the call boundary | |
| // and implicitly cast down to the declared type (short) inside the | |
| // function. Therefore, signature computation at K&R definition | |
| // sites must also apply default argument promotion (yielding | |
| // void(int), not void(short)) so definition and call sites match. | |
| // | |
| // Signature Strictness & Normalization: | |
| // Since type identifier matching relies on exact hash equality, any | |
| // tolerance for C compatibility rules must be done by normalizing | |
| // types before hashing. | |
| // - Standard C allows certain exceptions for unprototyped calls (and | |
| // variadic va_arg), such as differences in signedness (e.g., | |
| // passing an int to an unsigned int parameter) or | |
| // interchangeability of enum types with their underlying integer | |
| // types. | |
| // - Existing CFI normalization (e.g., | |
| // -fsanitize-cfi-icall-experimental-normalize-integers) normalizes | |
| // types by bit-width and signedness (e.g., int vs long on LP64, | |
| // which C does not treat as compatible), but does not normalize | |
| // away signedness or enum mismatches. | |
| // - In the future, whether to normalize away signedness, enums, or | |
| // integer bit-widths depends on whether call graph analysis should | |
| // err on the side of inclusion (admitting any C-valid call) or | |
| // strictness (like CFI). Any normalization applied here at the call | |
| // site must remain strictly matched with definition-site | |
| // type signature computation. | |
| if (const auto *FNPT = CST->getAs<FunctionNoProtoType>()) { | |
| SmallVector<QualType, 8> ParamTypes; | |
| // CallArgs already contains default-promoted argument types for | |
| // unprototyped calls. | |
| for (const CallArg &Arg : CallArgs) | |
| ParamTypes.push_back(Arg.getType()); | |
| CST = CGM.ReconstructCallGraphPrototype(FNPT, ParamTypes); | |
| } | |
| llvm::Metadata *MD = | |
| CGM.CreateMetadataIdentifierForCallGraphType(CST); | |
| StringRef TypeStr; | |
| if (auto *MDS = dyn_cast_or_null<llvm::MDString>(MD)) | |
| TypeStr = MDS->getString(); | |
| CGM.getDiags().Report(Loc, diag::warn_cgs_no_proto) << CST << TypeStr; | |
| } | |
| CGM.createCalleeTypeMetadataForIcall(CST, *callOrInvoke); | |
| } | |
| } | |
| } | |
| // If this is within a function that has the guard(nocf) attribute and is an | |
| // indirect call, add the "guard_nocf" attribute to this call to indicate that | |
| // Control Flow Guard checks should not be added, even if the call is inlined. | |
| if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) { | |
| if (const auto *A = FD->getAttr<CFGuardAttr>()) { | |
| if (A->getGuard() == CFGuardAttr::GuardArg::nocf && | |
| !CI->getCalledFunction()) | |
| Attrs = Attrs.addFnAttribute(getLLVMContext(), "guard_nocf"); | |
| } | |
| } | |
| // Apply the attributes and calling convention. | |
| CI->setAttributes(Attrs); | |
| CI->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); | |
| // Apply various metadata. | |
| if (!CI->getType()->isVoidTy()) | |
| CI->setName("call"); | |
| // Update largest vector width from the return type. | |
| LargestVectorWidth = | |
| std::max(LargestVectorWidth, getMaxVectorWidth(CI->getType())); | |
| // Insert instrumentation or attach profile metadata at indirect call sites. | |
| // For more details, see the comment before the definition of | |
| // IPVK_IndirectCallTarget in InstrProfData.inc. | |
| if (!CI->getCalledFunction()) | |
| PGO->valueProfile(Builder, llvm::IPVK_IndirectCallTarget, CI, CalleePtr); | |
| // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC | |
| // optimizer it can aggressively ignore unwind edges. | |
| if (CGM.getLangOpts().ObjCAutoRefCount) | |
| AddObjCARCExceptionMetadata(CI); | |
| // Set tail call kind if necessary. | |
| bool IsPPC = getTarget().getTriple().isPPC(); | |
| bool IsMIPS = getTarget().getTriple().isMIPS(); | |
| bool HasMips16 = false; | |
| if (IsMIPS) { | |
| const TargetOptions &TargetOpts = getTarget().getTargetOpts(); | |
| HasMips16 = TargetOpts.FeatureMap.lookup("mips16"); | |
| if (!HasMips16) | |
| HasMips16 = llvm::is_contained(TargetOpts.Features, "+mips16"); | |
| } | |
| if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { | |
| if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) | |
| Call->setTailCallKind(llvm::CallInst::TCK_NoTail); | |
| else if (IsMustTail) { | |
| if (IsPPC) { | |
| if (getTarget().getTriple().isOSAIX()) | |
| CGM.getDiags().Report(Loc, diag::err_aix_musttail_unsupported); | |
| else if (!getTarget().hasFeature("pcrelative-memops")) { | |
| if (getTarget().hasFeature("longcall")) | |
| CGM.getDiags().Report(Loc, diag::err_ppc_impossible_musttail) << 0; | |
| else if (Call->isIndirectCall()) | |
| CGM.getDiags().Report(Loc, diag::err_ppc_impossible_musttail) << 1; | |
| else if (isa_and_nonnull<FunctionDecl>(TargetDecl)) { | |
| if (!cast<FunctionDecl>(TargetDecl)->isDefined()) | |
| // The undefined callee may be a forward declaration. Without | |
| // knowning all symbols in the module, we won't know the symbol is | |
| // defined or not. Collect all these symbols for later diagnosing. | |
| CGM.addUndefinedGlobalForTailCall( | |
| {cast<FunctionDecl>(TargetDecl), Loc}); | |
| else { | |
| llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage( | |
| GlobalDecl(cast<FunctionDecl>(TargetDecl))); | |
| if (llvm::GlobalValue::isWeakForLinker(Linkage) || | |
| llvm::GlobalValue::isDiscardableIfUnused(Linkage)) | |
| CGM.getDiags().Report(Loc, diag::err_ppc_impossible_musttail) | |
| << 2; | |
| } | |
| } | |
| } | |
| } | |
| if (IsMIPS) { | |
| if (HasMips16) | |
| CGM.getDiags().Report(Loc, diag::err_mips_impossible_musttail) << 0; | |
| else if (const auto *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) | |
| CGM.addUndefinedGlobalForTailCall({FD, Loc}); | |
| } | |
| Call->setTailCallKind(llvm::CallInst::TCK_MustTail); | |
| } | |
| } | |
| // Add metadata for calls to MSAllocator functions | |
| if (getDebugInfo() && TargetDecl && TargetDecl->hasAttr<MSAllocatorAttr>()) | |
| getDebugInfo()->addHeapAllocSiteMetadata(CI, RetTy->getPointeeType(), Loc); | |
| // Add srcloc metadata for [[gnu::error/warning]] diagnostics. When | |
| // ShowInliningChain is enabled, also track inline/static calls for the | |
| // heuristic fallback when debug info is not available. This heuristic is | |
| // conservative and best-effort since static or inline-annotated functions | |
| // are still not guaranteed to be inlined. | |
| if (TargetDecl) { | |
| bool NeedSrcLoc = TargetDecl->hasAttr<ErrorAttr>(); | |
| if (!NeedSrcLoc && CGM.getCodeGenOpts().ShowInliningChain) { | |
| if (const auto *FD = dyn_cast<FunctionDecl>(TargetDecl)) | |
| NeedSrcLoc = FD->isInlined() || FD->hasAttr<AlwaysInlineAttr>() || | |
| FD->getStorageClass() == SC_Static || | |
| FD->isInAnonymousNamespace(); | |
| } | |
| if (NeedSrcLoc) { | |
| auto *Line = llvm::ConstantInt::get(Int64Ty, Loc.getRawEncoding()); | |
| auto *MD = llvm::ConstantAsMetadata::get(Line); | |
| CI->setMetadata("srcloc", llvm::MDNode::get(getLLVMContext(), {MD})); | |
| } | |
| } | |
| // 4. Finish the call. | |
| // If the call doesn't return, finish the basic block and clear the | |
| // insertion point; this allows the rest of IRGen to discard | |
| // unreachable code. | |
| if (CI->doesNotReturn()) { | |
| if (NeedSRetLifetimeEnd) | |
| PopCleanupBlock(); | |
| // Strip away the noreturn attribute to better diagnose unreachable UB. | |
| if (SanOpts.has(SanitizerKind::Unreachable)) { | |
| // Also remove from function since CallBase::hasFnAttr additionally checks | |
| // attributes of the called function. | |
| if (auto *F = CI->getCalledFunction()) | |
| F->removeFnAttr(llvm::Attribute::NoReturn); | |
| CI->removeFnAttr(llvm::Attribute::NoReturn); | |
| // Avoid incompatibility with ASan which relies on the `noreturn` | |
| // attribute to insert handler calls. | |
| if (SanOpts.hasOneOf(SanitizerKind::Address | | |
| SanitizerKind::KernelAddress)) { | |
| SanitizerScope SanScope(this); | |
| llvm::IRBuilder<>::InsertPointGuard IPGuard(Builder); | |
| Builder.SetInsertPoint(CI); | |
| auto *FnType = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); | |
| llvm::FunctionCallee Fn = | |
| CGM.CreateRuntimeFunction(FnType, "__asan_handle_no_return"); | |
| EmitNounwindRuntimeCall(Fn); | |
| } | |
| } | |
| EmitUnreachable(Loc); | |
| Builder.ClearInsertionPoint(); | |
| // FIXME: For now, emit a dummy basic block because expr emitters in | |
| // generally are not ready to handle emitting expressions at unreachable | |
| // points. | |
| EnsureInsertPoint(); | |
| // Return a reasonable RValue. | |
| return GetUndefRValue(RetTy); | |
| } | |
| // If this is a musttail call, return immediately. We do not branch to the | |
| // epilogue in this case. | |
| if (IsMustTail) { | |
| for (auto it = EHStack.find(CurrentCleanupScopeDepth); it != EHStack.end(); | |
| ++it) { | |
| // A noexcept caller pushes an EHTerminateScope to call std::terminate() | |
| // if an exception escapes. A musttail call replaces the caller's frame, | |
| // removing this handler. This is safe if the callee is also nounwind: | |
| // the callee's own noexcept handler prevents any exception from reaching | |
| // where the caller's handler would have been. | |
| if (isa<EHTerminateScope>(&*it)) { | |
| if (CI->doesNotThrow()) | |
| continue; | |
| CGM.getDiags().Report(MustTailCall->getBeginLoc(), | |
| diag::err_musttail_noexcept_mismatch); | |
| break; | |
| } | |
| if (auto *Cleanup = dyn_cast<EHCleanupScope>(&*it)) { | |
| // Fake uses can be safely emitted immediately prior to the tail call, | |
| // so we choose to emit them just before the call here. | |
| if (Cleanup->isFakeUse()) { | |
| CGBuilderTy::InsertPointGuard IPG(Builder); | |
| Builder.SetInsertPoint(CI); | |
| Cleanup->getCleanup()->Emit(*this, EHScopeStack::Cleanup::Flags()); | |
| continue; | |
| } | |
| if (Cleanup->isRedundantBeforeReturn()) | |
| continue; | |
| } | |
| CGM.ErrorUnsupported(MustTailCall, "tail call skipping over cleanups"); | |
| } | |
| if (CI->getType()->isVoidTy()) | |
| Builder.CreateRetVoid(); | |
| else | |
| Builder.CreateRet(CI); | |
| Builder.ClearInsertionPoint(); | |
| EnsureInsertPoint(); | |
| return GetUndefRValue(RetTy); | |
| } | |
| // Perform the swifterror writeback. | |
| if (swiftErrorTemp.isValid()) { | |
| llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp); | |
| Builder.CreateStore(errorResult, swiftErrorArg); | |
| } | |
| // Emit any call-associated writebacks immediately. Arguably this | |
| // should happen after any return-value munging. | |
| if (CallArgs.hasWritebacks()) | |
| EmitWritebacks(CallArgs); | |
| // The stack cleanup for inalloca arguments has to run out of the normal | |
| // lexical order, so deactivate it and run it manually here. | |
| CallArgs.freeArgumentMemory(*this); | |
| // Extract the return value. | |
| RValue Ret; | |
| // If the current function is a virtual function pointer thunk, avoid copying | |
| // the return value of the musttail call to a temporary. | |
| if (IsVirtualFunctionPointerThunk) { | |
| Ret = RValue::get(CI); | |
| } else { | |
| Ret = [&] { | |
| switch (RetAI.getKind()) { | |
| case ABIArgInfo::CoerceAndExpand: { | |
| auto coercionType = RetAI.getCoerceAndExpandType(); | |
| Address addr = SRetPtr.withElementType(coercionType); | |
| assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType()); | |
| bool requiresExtract = isa<llvm::StructType>(CI->getType()); | |
| unsigned unpaddedIndex = 0; | |
| for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { | |
| llvm::Type *eltType = coercionType->getElementType(i); | |
| if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) | |
| continue; | |
| Address eltAddr = Builder.CreateStructGEP(addr, i); | |
| llvm::Value *elt = CI; | |
| if (requiresExtract) | |
| elt = Builder.CreateExtractValue(elt, unpaddedIndex++); | |
| else | |
| assert(unpaddedIndex == 0); | |
| Builder.CreateStore(elt, eltAddr); | |
| } | |
| [[fallthrough]]; | |
| } | |
| case ABIArgInfo::InAlloca: | |
| case ABIArgInfo::Indirect: { | |
| RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation()); | |
| if (NeedSRetLifetimeEnd) | |
| PopCleanupBlock(); | |
| return ret; | |
| } | |
| case ABIArgInfo::Ignore: | |
| // If we are ignoring an argument that had a result, make sure to | |
| // construct the appropriate return value for our caller. | |
| return GetUndefRValue(RetTy); | |
| case ABIArgInfo::Extend: | |
| case ABIArgInfo::Direct: { | |
| llvm::Type *RetIRTy = ConvertType(RetTy); | |
| if (RetAI.getCoerceToType() == RetIRTy && | |
| RetAI.getDirectOffset() == 0) { | |
| switch (getEvaluationKind(RetTy)) { | |
| case TEK_Complex: { | |
| llvm::Value *Real = Builder.CreateExtractValue(CI, 0); | |
| llvm::Value *Imag = Builder.CreateExtractValue(CI, 1); | |
| return RValue::getComplex(std::make_pair(Real, Imag)); | |
| } | |
| case TEK_Aggregate: | |
| break; | |
| case TEK_Scalar: { | |
| // If the argument doesn't match, perform a bitcast to coerce it. | |
| // This can happen due to trivial type mismatches. | |
| llvm::Value *V = CI; | |
| if (V->getType() != RetIRTy) | |
| V = Builder.CreateBitCast(V, RetIRTy); | |
| return RValue::get(V); | |
| } | |
| } | |
| } | |
| // If coercing a fixed vector from a scalable vector for ABI | |
| // compatibility, and the types match, use the llvm.vector.extract | |
| // intrinsic to perform the conversion. | |
| if (auto *FixedDstTy = dyn_cast<llvm::FixedVectorType>(RetIRTy)) { | |
| llvm::Value *V = CI; | |
| if (auto *ScalableSrcTy = | |
| dyn_cast<llvm::ScalableVectorType>(V->getType())) { | |
| if (FixedDstTy->getElementType() == | |
| ScalableSrcTy->getElementType()) { | |
| V = Builder.CreateExtractVector(FixedDstTy, V, uint64_t(0), | |
| "cast.fixed"); | |
| return RValue::get(V); | |
| } | |
| } | |
| } | |
| Address DestPtr = ReturnValue.getValue(); | |
| bool DestIsVolatile = ReturnValue.isVolatile(); | |
| uint64_t DestSize = | |
| getContext().getTypeInfoDataSizeInChars(RetTy).Width.getQuantity(); | |
| if (!DestPtr.isValid()) { | |
| DestPtr = CreateMemTempWithoutCast(RetTy, "coerce"); | |
| DestIsVolatile = false; | |
| DestSize = getContext().getTypeSizeInChars(RetTy).getQuantity(); | |
| } | |
| // An empty record can overlap other data (if declared with | |
| // no_unique_address); omit the store for such types - as there is no | |
| // actual data to store. | |
| if (!isEmptyRecord(getContext(), RetTy, true)) { | |
| // If the value is offset in memory, apply the offset now. | |
| Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); | |
| CreateCoercedStore( | |
| CI, RetTy, StorePtr, | |
| llvm::TypeSize::getFixed(DestSize - RetAI.getDirectOffset()), | |
| DestIsVolatile); | |
| } | |
| return convertTempToRValue(DestPtr, RetTy, SourceLocation()); | |
| } | |
| case ABIArgInfo::TargetSpecific: { | |
| Address DestPtr = ReturnValue.getValue(); | |
| Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); | |
| bool DestIsVolatile = ReturnValue.isVolatile(); | |
| if (!DestPtr.isValid()) { | |
| DestPtr = CreateMemTempWithoutCast(RetTy, "target_coerce"); | |
| DestIsVolatile = false; | |
| } | |
| CGM.getABIInfo().createCoercedStore(CI, StorePtr, RetAI, DestIsVolatile, | |
| *this); | |
| return convertTempToRValue(DestPtr, RetTy, SourceLocation()); | |
| } | |
| case ABIArgInfo::Expand: | |
| case ABIArgInfo::IndirectAliased: | |
| llvm_unreachable("Invalid ABI kind for return argument"); | |
| } | |
| llvm_unreachable("Unhandled ABIArgInfo::Kind"); | |
| }(); | |
| } | |
| // Emit the assume_aligned check on the return value. | |
| if (Ret.isScalar() && TargetDecl) { | |
| AssumeAlignedAttrEmitter.EmitAsAnAssumption(Loc, RetTy, Ret); | |
| AllocAlignAttrEmitter.EmitAsAnAssumption(Loc, RetTy, Ret); | |
| } | |
| // Emit the end lifetime markers for any temporary allocas created for the | |
| // call arguments. | |
| for (llvm::Value *LifetimeEndAddr : CallLifetimeEndAfterCall) | |
| EmitLifetimeEnd(LifetimeEndAddr); | |
| if (!ReturnValue.isExternallyDestructed() && | |
| RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct) | |
| pushDestroy(QualType::DK_nontrivial_c_struct, Ret.getAggregateAddress(), | |
| RetTy); | |
| // Generate function declaration DISuprogram in order to be used | |
| // in debug info about call sites. | |
| if (CGDebugInfo *DI = getDebugInfo()) { | |
| // Ensure call site info would actually be emitted before collecting | |
| // further callee info. | |
| if (CalleeDecl && !CalleeDecl->hasAttr<NoDebugAttr>() && | |
| DI->getCallSiteRelatedAttrs() != llvm::DINode::FlagZero) { | |
| CodeGenFunction CalleeCGF(CGM); | |
| const GlobalDecl &CalleeGlobalDecl = | |
| Callee.getAbstractInfo().getCalleeDecl(); | |
| CalleeCGF.CurGD = CalleeGlobalDecl; | |
| FunctionArgList Args; | |
| QualType ResTy = CalleeCGF.BuildFunctionArgList(CalleeGlobalDecl, Args); | |
| DI->EmitFuncDeclForCallSite( | |
| CI, DI->getFunctionType(CalleeDecl, ResTy, Args), CalleeGlobalDecl); | |
| } | |
| // Generate call site target information. | |
| DI->addCallTargetIfVirtual(CalleeDecl, CI); | |
| } | |
| return Ret; | |
| } | |
| CGCallee CGCallee::prepareConcreteCallee(CodeGenFunction &CGF) const { | |
| if (isVirtual()) { | |
| const CallExpr *CE = getVirtualCallExpr(); | |
| return CGF.CGM.getCXXABI().getVirtualFunctionPointer( | |
| CGF, getVirtualMethodDecl(), getThisAddress(), getVirtualFunctionType(), | |
| CE ? CE->getBeginLoc() : SourceLocation()); | |
| } | |
| return *this; | |
| } | |
| /* VarArg handling */ | |
| RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr, | |
| AggValueSlot Slot) { | |
| VAListAddr = VE->isMicrosoftABI() | |
| ? EmitMSVAListRef(VE->getSubExpr()) | |
| : (VE->isZOSABI() ? EmitZOSVAListRef(VE->getSubExpr()) | |
| : EmitVAListRef(VE->getSubExpr())); | |
| QualType Ty = VE->getType(); | |
| if (Ty->isVariablyModifiedType()) | |
| EmitVariablyModifiedType(Ty); | |
| if (VE->isMicrosoftABI()) | |
| return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot); | |
| if (VE->isZOSABI()) | |
| return CGM.getABIInfo().EmitZOSVAArg(*this, VAListAddr, Ty, Slot); | |
| return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot); | |
| } | |
| DisableDebugLocationUpdates::DisableDebugLocationUpdates(CodeGenFunction &CGF) | |
| : CGF(CGF) { | |
| CGF.disableDebugInfo(); | |
| } | |
| DisableDebugLocationUpdates::~DisableDebugLocationUpdates() { | |
| CGF.enableDebugInfo(); | |
| } |