1bfef3995SDimitry Andric //===--- CGCall.cpp - Encapsulate calling convention details --------------===//
2ec2b103cSEd Schouten //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ec2b103cSEd Schouten //
7ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
8ec2b103cSEd Schouten //
9ec2b103cSEd Schouten // These classes wrap the information about a call or function
10ec2b103cSEd Schouten // definition used to handle ABI compliancy.
11ec2b103cSEd Schouten //
12ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
13ec2b103cSEd Schouten
14ec2b103cSEd Schouten #include "CGCall.h"
154ba67500SRoman Divacky #include "ABIInfo.h"
16b1c73532SDimitry Andric #include "ABIInfoImpl.h"
172b6b257fSDimitry Andric #include "CGBlocks.h"
18809500fcSDimitry Andric #include "CGCXXABI.h"
1945b53394SDimitry Andric #include "CGCleanup.h"
20cfca06d7SDimitry Andric #include "CGRecordLayout.h"
21ec2b103cSEd Schouten #include "CodeGenFunction.h"
22ec2b103cSEd Schouten #include "CodeGenModule.h"
23dbe13110SDimitry Andric #include "TargetInfo.h"
24706b4fc4SDimitry Andric #include "clang/AST/Attr.h"
25ec2b103cSEd Schouten #include "clang/AST/Decl.h"
26ec2b103cSEd Schouten #include "clang/AST/DeclCXX.h"
27ec2b103cSEd Schouten #include "clang/AST/DeclObjC.h"
28676fbe81SDimitry Andric #include "clang/Basic/CodeGenOptions.h"
29809500fcSDimitry Andric #include "clang/Basic/TargetInfo.h"
30bfef3995SDimitry Andric #include "clang/CodeGen/CGFunctionInfo.h"
312b6b257fSDimitry Andric #include "clang/CodeGen/SwiftCallingConv.h"
32809500fcSDimitry Andric #include "llvm/ADT/StringExtras.h"
33bab175ecSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
34b60736ecSDimitry Andric #include "llvm/IR/Assumptions.h"
357fa27ce4SDimitry Andric #include "llvm/IR/AttributeMask.h"
36809500fcSDimitry Andric #include "llvm/IR/Attributes.h"
3748675466SDimitry Andric #include "llvm/IR/CallingConv.h"
38809500fcSDimitry Andric #include "llvm/IR/DataLayout.h"
39809500fcSDimitry Andric #include "llvm/IR/InlineAsm.h"
405e20cdd8SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
4148675466SDimitry Andric #include "llvm/IR/Intrinsics.h"
42145449b1SDimitry Andric #include "llvm/IR/Type.h"
43706b4fc4SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
44e3b55780SDimitry Andric #include <optional>
45ec2b103cSEd Schouten using namespace clang;
46ec2b103cSEd Schouten using namespace CodeGen;
47ec2b103cSEd Schouten
48ec2b103cSEd Schouten /***/
49ec2b103cSEd Schouten
ClangCallConvToLLVMCallConv(CallingConv CC)502b6b257fSDimitry Andric unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
51ecb7e5c8SRoman Divacky switch (CC) {
52ecb7e5c8SRoman Divacky default: return llvm::CallingConv::C;
53ecb7e5c8SRoman Divacky case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
54ecb7e5c8SRoman Divacky case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
55bab175ecSDimitry Andric case CC_X86RegCall: return llvm::CallingConv::X86_RegCall;
56d7279c4cSRoman Divacky case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
57de51d671SDimitry Andric case CC_Win64: return llvm::CallingConv::Win64;
58bfef3995SDimitry Andric case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV;
5901af97d3SDimitry Andric case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS;
6001af97d3SDimitry Andric case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP;
61809500fcSDimitry Andric case CC_IntelOclBicc: return llvm::CallingConv::Intel_OCL_BI;
6206d4ba38SDimitry Andric // TODO: Add support for __pascal to LLVM.
6306d4ba38SDimitry Andric case CC_X86Pascal: return llvm::CallingConv::C;
6406d4ba38SDimitry Andric // TODO: Add support for __vectorcall to LLVM.
6506d4ba38SDimitry Andric case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall;
66676fbe81SDimitry Andric case CC_AArch64VectorCall: return llvm::CallingConv::AArch64_VectorCall;
67145449b1SDimitry Andric case CC_AArch64SVEPCS: return llvm::CallingConv::AArch64_SVE_VectorCall;
68145449b1SDimitry Andric case CC_AMDGPUKernelCall: return llvm::CallingConv::AMDGPU_KERNEL;
695e20cdd8SDimitry Andric case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC;
702b6b257fSDimitry Andric case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv();
712b6b257fSDimitry Andric case CC_PreserveMost: return llvm::CallingConv::PreserveMost;
722b6b257fSDimitry Andric case CC_PreserveAll: return llvm::CallingConv::PreserveAll;
732b6b257fSDimitry Andric case CC_Swift: return llvm::CallingConv::Swift;
74344a3780SDimitry Andric case CC_SwiftAsync: return llvm::CallingConv::SwiftTail;
75b1c73532SDimitry Andric case CC_M68kRTD: return llvm::CallingConv::M68k_RTD;
76ac9a064cSDimitry Andric case CC_PreserveNone: return llvm::CallingConv::PreserveNone;
77ac9a064cSDimitry Andric // clang-format off
78ac9a064cSDimitry Andric case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall;
79ac9a064cSDimitry Andric // clang-format on
80ecb7e5c8SRoman Divacky }
81ecb7e5c8SRoman Divacky }
82ecb7e5c8SRoman Divacky
83676fbe81SDimitry Andric /// Derives the 'this' type for codegen purposes, i.e. ignoring method CVR
8422989816SDimitry Andric /// qualification. Either or both of RD and MD may be null. A null RD indicates
8522989816SDimitry Andric /// that there is no meaningful 'this' type, and a null MD can occur when
8622989816SDimitry Andric /// calling a method pointer.
DeriveThisType(const CXXRecordDecl * RD,const CXXMethodDecl * MD)8722989816SDimitry Andric CanQualType CodeGenTypes::DeriveThisType(const CXXRecordDecl *RD,
88676fbe81SDimitry Andric const CXXMethodDecl *MD) {
8922989816SDimitry Andric QualType RecTy;
9022989816SDimitry Andric if (RD)
9122989816SDimitry Andric RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal();
9222989816SDimitry Andric else
9322989816SDimitry Andric RecTy = Context.VoidTy;
9422989816SDimitry Andric
95676fbe81SDimitry Andric if (MD)
9622989816SDimitry Andric RecTy = Context.getAddrSpaceQualType(RecTy, MD->getMethodQualifiers().getAddressSpace());
9779ade4e0SRoman Divacky return Context.getPointerType(CanQualType::CreateUnsafe(RecTy));
98ec2b103cSEd Schouten }
99ec2b103cSEd Schouten
10079ade4e0SRoman Divacky /// Returns the canonical formal type of the given C++ method.
GetFormalType(const CXXMethodDecl * MD)10179ade4e0SRoman Divacky static CanQual<FunctionProtoType> GetFormalType(const CXXMethodDecl *MD) {
10279ade4e0SRoman Divacky return MD->getType()->getCanonicalTypeUnqualified()
10379ade4e0SRoman Divacky .getAs<FunctionProtoType>();
10479ade4e0SRoman Divacky }
10579ade4e0SRoman Divacky
10679ade4e0SRoman Divacky /// Returns the "extra-canonicalized" return type, which discards
10779ade4e0SRoman Divacky /// qualifiers on the return type. Codegen doesn't care about them,
10879ade4e0SRoman Divacky /// and it makes ABI code a little easier to be able to assume that
10979ade4e0SRoman Divacky /// all parameter and return types are top-level unqualified.
GetReturnType(QualType RetTy)11079ade4e0SRoman Divacky static CanQualType GetReturnType(QualType RetTy) {
11179ade4e0SRoman Divacky return RetTy->getCanonicalTypeUnqualified().getUnqualifiedType();
11279ade4e0SRoman Divacky }
11379ade4e0SRoman Divacky
11456d91b49SDimitry Andric /// Arrange the argument and result information for a value of the given
11556d91b49SDimitry Andric /// unprototyped freestanding function type.
11679ade4e0SRoman Divacky const CGFunctionInfo &
arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP)11756d91b49SDimitry Andric CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) {
118dbe13110SDimitry Andric // When translating an unprototyped function type, always use a
119dbe13110SDimitry Andric // variadic type.
1209f4dbff6SDimitry Andric return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(),
121b1c73532SDimitry Andric FnInfoOpts::None, std::nullopt,
1222b6b257fSDimitry Andric FTNP->getExtInfo(), {}, RequiredArgs(0));
12379ade4e0SRoman Divacky }
12479ade4e0SRoman Divacky
addExtParameterInfosForCall(llvm::SmallVectorImpl<FunctionProtoType::ExtParameterInfo> & paramInfos,const FunctionProtoType * proto,unsigned prefixArgs,unsigned totalArgs)1257442d6faSDimitry Andric static void addExtParameterInfosForCall(
1267442d6faSDimitry Andric llvm::SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos,
1277442d6faSDimitry Andric const FunctionProtoType *proto,
1287442d6faSDimitry Andric unsigned prefixArgs,
1297442d6faSDimitry Andric unsigned totalArgs) {
1307442d6faSDimitry Andric assert(proto->hasExtParameterInfos());
1317442d6faSDimitry Andric assert(paramInfos.size() <= prefixArgs);
1327442d6faSDimitry Andric assert(proto->getNumParams() + prefixArgs <= totalArgs);
1337442d6faSDimitry Andric
1347442d6faSDimitry Andric paramInfos.reserve(totalArgs);
1357442d6faSDimitry Andric
1367442d6faSDimitry Andric // Add default infos for any prefix args that don't already have infos.
1377442d6faSDimitry Andric paramInfos.resize(prefixArgs);
1387442d6faSDimitry Andric
1397442d6faSDimitry Andric // Add infos for the prototype.
1407442d6faSDimitry Andric for (const auto &ParamInfo : proto->getExtParameterInfos()) {
1417442d6faSDimitry Andric paramInfos.push_back(ParamInfo);
1427442d6faSDimitry Andric // pass_object_size params have no parameter info.
1437442d6faSDimitry Andric if (ParamInfo.hasPassObjectSize())
1447442d6faSDimitry Andric paramInfos.emplace_back();
1457442d6faSDimitry Andric }
1467442d6faSDimitry Andric
1477442d6faSDimitry Andric assert(paramInfos.size() <= totalArgs &&
1487442d6faSDimitry Andric "Did we forget to insert pass_object_size args?");
1497442d6faSDimitry Andric // Add default infos for the variadic and/or suffix arguments.
1507442d6faSDimitry Andric paramInfos.resize(totalArgs);
1517442d6faSDimitry Andric }
1527442d6faSDimitry Andric
1538746d127SDimitry Andric /// Adds the formal parameters in FPT to the given prefix. If any parameter in
15445b53394SDimitry Andric /// FPT has pass_object_size attrs, then we'll add parameters for those, too.
appendParameterTypes(const CodeGenTypes & CGT,SmallVectorImpl<CanQualType> & prefix,SmallVectorImpl<FunctionProtoType::ExtParameterInfo> & paramInfos,CanQual<FunctionProtoType> FPT)15545b53394SDimitry Andric static void appendParameterTypes(const CodeGenTypes &CGT,
15645b53394SDimitry Andric SmallVectorImpl<CanQualType> &prefix,
1572b6b257fSDimitry Andric SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos,
1587442d6faSDimitry Andric CanQual<FunctionProtoType> FPT) {
1597442d6faSDimitry Andric // Fast path: don't touch param info if we don't need to.
1607442d6faSDimitry Andric if (!FPT->hasExtParameterInfos()) {
1617442d6faSDimitry Andric assert(paramInfos.empty() &&
1627442d6faSDimitry Andric "We have paramInfos, but the prototype doesn't?");
16345b53394SDimitry Andric prefix.append(FPT->param_type_begin(), FPT->param_type_end());
16445b53394SDimitry Andric return;
16545b53394SDimitry Andric }
16645b53394SDimitry Andric
1677442d6faSDimitry Andric unsigned PrefixSize = prefix.size();
1687442d6faSDimitry Andric // In the vast majority of cases, we'll have precisely FPT->getNumParams()
16945b53394SDimitry Andric // parameters; the only thing that can change this is the presence of
17045b53394SDimitry Andric // pass_object_size. So, we preallocate for the common case.
17145b53394SDimitry Andric prefix.reserve(prefix.size() + FPT->getNumParams());
17245b53394SDimitry Andric
1737442d6faSDimitry Andric auto ExtInfos = FPT->getExtParameterInfos();
1747442d6faSDimitry Andric assert(ExtInfos.size() == FPT->getNumParams());
17545b53394SDimitry Andric for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) {
17645b53394SDimitry Andric prefix.push_back(FPT->getParamType(I));
1777442d6faSDimitry Andric if (ExtInfos[I].hasPassObjectSize())
17845b53394SDimitry Andric prefix.push_back(CGT.getContext().getSizeType());
17945b53394SDimitry Andric }
1807442d6faSDimitry Andric
1817442d6faSDimitry Andric addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize,
1827442d6faSDimitry Andric prefix.size());
18345b53394SDimitry Andric }
18445b53394SDimitry Andric
18556d91b49SDimitry Andric /// Arrange the LLVM function layout for a value of the given function
18606d4ba38SDimitry Andric /// type, on top of any implicit parameters already stored.
18706d4ba38SDimitry Andric static const CGFunctionInfo &
arrangeLLVMFunctionInfo(CodeGenTypes & CGT,bool instanceMethod,SmallVectorImpl<CanQualType> & prefix,CanQual<FunctionProtoType> FTP)18806d4ba38SDimitry Andric arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod,
18956d91b49SDimitry Andric SmallVectorImpl<CanQualType> &prefix,
19022989816SDimitry Andric CanQual<FunctionProtoType> FTP) {
1912b6b257fSDimitry Andric SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
19222989816SDimitry Andric RequiredArgs Required = RequiredArgs::forPrototypePlus(FTP, prefix.size());
193ec2b103cSEd Schouten // FIXME: Kill copy.
1947442d6faSDimitry Andric appendParameterTypes(CGT, prefix, paramInfos, FTP);
1959f4dbff6SDimitry Andric CanQualType resultType = FTP->getReturnType().getUnqualifiedType();
1962b6b257fSDimitry Andric
197b1c73532SDimitry Andric FnInfoOpts opts =
198b1c73532SDimitry Andric instanceMethod ? FnInfoOpts::IsInstanceMethod : FnInfoOpts::None;
199b1c73532SDimitry Andric return CGT.arrangeLLVMFunctionInfo(resultType, opts, prefix,
200b1c73532SDimitry Andric FTP->getExtInfo(), paramInfos, Required);
20179ade4e0SRoman Divacky }
20279ade4e0SRoman Divacky
203dbe13110SDimitry Andric /// Arrange the argument and result information for a value of the
20456d91b49SDimitry Andric /// given freestanding function type.
20579ade4e0SRoman Divacky const CGFunctionInfo &
arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP)20622989816SDimitry Andric CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> FTP) {
207dbe13110SDimitry Andric SmallVector<CanQualType, 16> argTypes;
20806d4ba38SDimitry Andric return ::arrangeLLVMFunctionInfo(*this, /*instanceMethod=*/false, argTypes,
20922989816SDimitry Andric FTP);
2104c8b2481SRoman Divacky }
2114c8b2481SRoman Divacky
getCallingConventionForDecl(const ObjCMethodDecl * D,bool IsWindows)212b60736ecSDimitry Andric static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D,
213b60736ecSDimitry Andric bool IsWindows) {
2144c8b2481SRoman Divacky // Set the appropriate calling convention for the Function.
2154c8b2481SRoman Divacky if (D->hasAttr<StdCallAttr>())
216ecb7e5c8SRoman Divacky return CC_X86StdCall;
2174c8b2481SRoman Divacky
2184c8b2481SRoman Divacky if (D->hasAttr<FastCallAttr>())
219ecb7e5c8SRoman Divacky return CC_X86FastCall;
2204c8b2481SRoman Divacky
221bab175ecSDimitry Andric if (D->hasAttr<RegCallAttr>())
222bab175ecSDimitry Andric return CC_X86RegCall;
223bab175ecSDimitry Andric
224d7279c4cSRoman Divacky if (D->hasAttr<ThisCallAttr>())
225d7279c4cSRoman Divacky return CC_X86ThisCall;
226d7279c4cSRoman Divacky
22706d4ba38SDimitry Andric if (D->hasAttr<VectorCallAttr>())
22806d4ba38SDimitry Andric return CC_X86VectorCall;
22906d4ba38SDimitry Andric
2303d1dcd9bSDimitry Andric if (D->hasAttr<PascalAttr>())
2313d1dcd9bSDimitry Andric return CC_X86Pascal;
2323d1dcd9bSDimitry Andric
23301af97d3SDimitry Andric if (PcsAttr *PCS = D->getAttr<PcsAttr>())
23401af97d3SDimitry Andric return (PCS->getPCS() == PcsAttr::AAPCS ? CC_AAPCS : CC_AAPCS_VFP);
23501af97d3SDimitry Andric
236676fbe81SDimitry Andric if (D->hasAttr<AArch64VectorPcsAttr>())
237676fbe81SDimitry Andric return CC_AArch64VectorCall;
238676fbe81SDimitry Andric
239145449b1SDimitry Andric if (D->hasAttr<AArch64SVEPcsAttr>())
240145449b1SDimitry Andric return CC_AArch64SVEPCS;
241145449b1SDimitry Andric
242145449b1SDimitry Andric if (D->hasAttr<AMDGPUKernelCallAttr>())
243145449b1SDimitry Andric return CC_AMDGPUKernelCall;
244145449b1SDimitry Andric
245809500fcSDimitry Andric if (D->hasAttr<IntelOclBiccAttr>())
246809500fcSDimitry Andric return CC_IntelOclBicc;
247809500fcSDimitry Andric
2489f4dbff6SDimitry Andric if (D->hasAttr<MSABIAttr>())
249de51d671SDimitry Andric return IsWindows ? CC_C : CC_Win64;
2509f4dbff6SDimitry Andric
2519f4dbff6SDimitry Andric if (D->hasAttr<SysVABIAttr>())
2529f4dbff6SDimitry Andric return IsWindows ? CC_X86_64SysV : CC_C;
2539f4dbff6SDimitry Andric
2542b6b257fSDimitry Andric if (D->hasAttr<PreserveMostAttr>())
2552b6b257fSDimitry Andric return CC_PreserveMost;
2562b6b257fSDimitry Andric
2572b6b257fSDimitry Andric if (D->hasAttr<PreserveAllAttr>())
2582b6b257fSDimitry Andric return CC_PreserveAll;
2592b6b257fSDimitry Andric
260b1c73532SDimitry Andric if (D->hasAttr<M68kRTDAttr>())
261b1c73532SDimitry Andric return CC_M68kRTD;
262b1c73532SDimitry Andric
263ac9a064cSDimitry Andric if (D->hasAttr<PreserveNoneAttr>())
264ac9a064cSDimitry Andric return CC_PreserveNone;
265ac9a064cSDimitry Andric
266ac9a064cSDimitry Andric if (D->hasAttr<RISCVVectorCCAttr>())
267ac9a064cSDimitry Andric return CC_RISCVVectorCall;
268ac9a064cSDimitry Andric
269ecb7e5c8SRoman Divacky return CC_C;
2704c8b2481SRoman Divacky }
2714c8b2481SRoman Divacky
272dbe13110SDimitry Andric /// Arrange the argument and result information for a call to an
273dbe13110SDimitry Andric /// unknown C++ non-static member function of the given abstract type.
27422989816SDimitry Andric /// (A null RD means we don't have any meaningful "this" argument type,
275bfef3995SDimitry Andric /// so fall back to a generic pointer type).
276dbe13110SDimitry Andric /// The member function must be an ordinary function, i.e. not a
277dbe13110SDimitry Andric /// constructor or destructor.
278dbe13110SDimitry Andric const CGFunctionInfo &
arrangeCXXMethodType(const CXXRecordDecl * RD,const FunctionProtoType * FTP,const CXXMethodDecl * MD)279dbe13110SDimitry Andric CodeGenTypes::arrangeCXXMethodType(const CXXRecordDecl *RD,
28045b53394SDimitry Andric const FunctionProtoType *FTP,
28145b53394SDimitry Andric const CXXMethodDecl *MD) {
282dbe13110SDimitry Andric SmallVector<CanQualType, 16> argTypes;
2834c8b2481SRoman Divacky
2844c8b2481SRoman Divacky // Add the 'this' pointer.
28522989816SDimitry Andric argTypes.push_back(DeriveThisType(RD, MD));
2864c8b2481SRoman Divacky
28706d4ba38SDimitry Andric return ::arrangeLLVMFunctionInfo(
288b1c73532SDimitry Andric *this, /*instanceMethod=*/true, argTypes,
28922989816SDimitry Andric FTP->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
290ec2b103cSEd Schouten }
291ec2b103cSEd Schouten
29248675466SDimitry Andric /// Set calling convention for CUDA/HIP kernel.
setCUDAKernelCallingConvention(CanQualType & FTy,CodeGenModule & CGM,const FunctionDecl * FD)29348675466SDimitry Andric static void setCUDAKernelCallingConvention(CanQualType &FTy, CodeGenModule &CGM,
29448675466SDimitry Andric const FunctionDecl *FD) {
29548675466SDimitry Andric if (FD->hasAttr<CUDAGlobalAttr>()) {
29648675466SDimitry Andric const FunctionType *FT = FTy->getAs<FunctionType>();
29748675466SDimitry Andric CGM.getTargetCodeGenInfo().setCUDAKernelCallingConvention(FT);
29848675466SDimitry Andric FTy = FT->getCanonicalTypeUnqualified();
29948675466SDimitry Andric }
30048675466SDimitry Andric }
30148675466SDimitry Andric
302dbe13110SDimitry Andric /// Arrange the argument and result information for a declaration or
303dbe13110SDimitry Andric /// definition of the given C++ non-static member function. The
304dbe13110SDimitry Andric /// member function must be an ordinary function, i.e. not a
305dbe13110SDimitry Andric /// constructor or destructor.
306dbe13110SDimitry Andric const CGFunctionInfo &
arrangeCXXMethodDeclaration(const CXXMethodDecl * MD)307dbe13110SDimitry Andric CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
308bfef3995SDimitry Andric assert(!isa<CXXConstructorDecl>(MD) && "wrong method for constructors!");
3093d1dcd9bSDimitry Andric assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
3103d1dcd9bSDimitry Andric
31148675466SDimitry Andric CanQualType FT = GetFormalType(MD).getAs<Type>();
31248675466SDimitry Andric setCUDAKernelCallingConvention(FT, CGM, MD);
31348675466SDimitry Andric auto prototype = FT.getAs<FunctionProtoType>();
314ec2b103cSEd Schouten
315b1c73532SDimitry Andric if (MD->isImplicitObjectMemberFunction()) {
316dbe13110SDimitry Andric // The abstract case is perfectly fine.
317e6b73279SDimitry Andric const CXXRecordDecl *ThisType =
318e6b73279SDimitry Andric getCXXABI().getThisArgumentTypeForMethod(MD);
31945b53394SDimitry Andric return arrangeCXXMethodType(ThisType, prototype.getTypePtr(), MD);
320ec2b103cSEd Schouten }
321ec2b103cSEd Schouten
32222989816SDimitry Andric return arrangeFreeFunctionType(prototype);
323dbe13110SDimitry Andric }
3241569ce68SRoman Divacky
inheritingCtorHasParams(const InheritedConstructor & Inherited,CXXCtorType Type)3252b6b257fSDimitry Andric bool CodeGenTypes::inheritingCtorHasParams(
3262b6b257fSDimitry Andric const InheritedConstructor &Inherited, CXXCtorType Type) {
3272b6b257fSDimitry Andric // Parameters are unnecessary if we're constructing a base class subobject
3282b6b257fSDimitry Andric // and the inherited constructor lives in a virtual base.
3292b6b257fSDimitry Andric return Type == Ctor_Complete ||
3302b6b257fSDimitry Andric !Inherited.getShadowDecl()->constructsVirtualBase() ||
3312b6b257fSDimitry Andric !Target.getCXXABI().hasConstructorVariants();
3322b6b257fSDimitry Andric }
3332b6b257fSDimitry Andric
334dbe13110SDimitry Andric const CGFunctionInfo &
arrangeCXXStructorDeclaration(GlobalDecl GD)33522989816SDimitry Andric CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) {
33622989816SDimitry Andric auto *MD = cast<CXXMethodDecl>(GD.getDecl());
33706d4ba38SDimitry Andric
338dbe13110SDimitry Andric SmallVector<CanQualType, 16> argTypes;
3392b6b257fSDimitry Andric SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
3407fa27ce4SDimitry Andric
341e6b73279SDimitry Andric const CXXRecordDecl *ThisType = getCXXABI().getThisArgumentTypeForMethod(GD);
3427fa27ce4SDimitry Andric argTypes.push_back(DeriveThisType(ThisType, MD));
343bfef3995SDimitry Andric
3442b6b257fSDimitry Andric bool PassParams = true;
3452b6b257fSDimitry Andric
34606d4ba38SDimitry Andric if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
3472b6b257fSDimitry Andric // A base class inheriting constructor doesn't get forwarded arguments
3482b6b257fSDimitry Andric // needed to construct a virtual base (or base class thereof).
3492b6b257fSDimitry Andric if (auto Inherited = CD->getInheritedConstructor())
35022989816SDimitry Andric PassParams = inheritingCtorHasParams(Inherited, GD.getCtorType());
35106d4ba38SDimitry Andric }
352dbe13110SDimitry Andric
35306d4ba38SDimitry Andric CanQual<FunctionProtoType> FTP = GetFormalType(MD);
3543d1dcd9bSDimitry Andric
3553d1dcd9bSDimitry Andric // Add the formal parameters.
3562b6b257fSDimitry Andric if (PassParams)
3577442d6faSDimitry Andric appendParameterTypes(*this, argTypes, paramInfos, FTP);
3589f4dbff6SDimitry Andric
359cfca06d7SDimitry Andric CGCXXABI::AddedStructorArgCounts AddedArgs =
360e6b73279SDimitry Andric getCXXABI().buildStructorSignature(GD, argTypes);
3617442d6faSDimitry Andric if (!paramInfos.empty()) {
3627442d6faSDimitry Andric // Note: prefix implies after the first param.
3637442d6faSDimitry Andric if (AddedArgs.Prefix)
3647442d6faSDimitry Andric paramInfos.insert(paramInfos.begin() + 1, AddedArgs.Prefix,
3657442d6faSDimitry Andric FunctionProtoType::ExtParameterInfo{});
3667442d6faSDimitry Andric if (AddedArgs.Suffix)
3677442d6faSDimitry Andric paramInfos.append(AddedArgs.Suffix,
3687442d6faSDimitry Andric FunctionProtoType::ExtParameterInfo{});
3697442d6faSDimitry Andric }
3709f4dbff6SDimitry Andric
3719f4dbff6SDimitry Andric RequiredArgs required =
3722b6b257fSDimitry Andric (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size())
3732b6b257fSDimitry Andric : RequiredArgs::All);
3743d1dcd9bSDimitry Andric
37556d91b49SDimitry Andric FunctionType::ExtInfo extInfo = FTP->getExtInfo();
376e6b73279SDimitry Andric CanQualType resultType = getCXXABI().HasThisReturn(GD) ? argTypes.front()
377e6b73279SDimitry Andric : getCXXABI().hasMostDerivedReturn(GD)
37806d4ba38SDimitry Andric ? CGM.getContext().VoidPtrTy
37906d4ba38SDimitry Andric : Context.VoidTy;
380b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::IsInstanceMethod,
381b1c73532SDimitry Andric argTypes, extInfo, paramInfos, required);
3822b6b257fSDimitry Andric }
3832b6b257fSDimitry Andric
3842b6b257fSDimitry Andric static SmallVector<CanQualType, 16>
getArgTypesForCall(ASTContext & ctx,const CallArgList & args)3852b6b257fSDimitry Andric getArgTypesForCall(ASTContext &ctx, const CallArgList &args) {
3862b6b257fSDimitry Andric SmallVector<CanQualType, 16> argTypes;
3872b6b257fSDimitry Andric for (auto &arg : args)
3882b6b257fSDimitry Andric argTypes.push_back(ctx.getCanonicalParamType(arg.Ty));
3892b6b257fSDimitry Andric return argTypes;
3902b6b257fSDimitry Andric }
3912b6b257fSDimitry Andric
3922b6b257fSDimitry Andric static SmallVector<CanQualType, 16>
getArgTypesForDeclaration(ASTContext & ctx,const FunctionArgList & args)3932b6b257fSDimitry Andric getArgTypesForDeclaration(ASTContext &ctx, const FunctionArgList &args) {
3942b6b257fSDimitry Andric SmallVector<CanQualType, 16> argTypes;
3952b6b257fSDimitry Andric for (auto &arg : args)
3962b6b257fSDimitry Andric argTypes.push_back(ctx.getCanonicalParamType(arg->getType()));
3972b6b257fSDimitry Andric return argTypes;
3982b6b257fSDimitry Andric }
3992b6b257fSDimitry Andric
4002b6b257fSDimitry Andric static llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16>
getExtParameterInfosForCall(const FunctionProtoType * proto,unsigned prefixArgs,unsigned totalArgs)4012b6b257fSDimitry Andric getExtParameterInfosForCall(const FunctionProtoType *proto,
4022b6b257fSDimitry Andric unsigned prefixArgs, unsigned totalArgs) {
4032b6b257fSDimitry Andric llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> result;
4042b6b257fSDimitry Andric if (proto->hasExtParameterInfos()) {
4052b6b257fSDimitry Andric addExtParameterInfosForCall(result, proto, prefixArgs, totalArgs);
4062b6b257fSDimitry Andric }
4072b6b257fSDimitry Andric return result;
4089f4dbff6SDimitry Andric }
4099f4dbff6SDimitry Andric
4109f4dbff6SDimitry Andric /// Arrange a call to a C++ method, passing the given arguments.
4117442d6faSDimitry Andric ///
4127442d6faSDimitry Andric /// ExtraPrefixArgs is the number of ABI-specific args passed after the `this`
4137442d6faSDimitry Andric /// parameter.
4147442d6faSDimitry Andric /// ExtraSuffixArgs is the number of ABI-specific args passed at the end of
4157442d6faSDimitry Andric /// args.
4167442d6faSDimitry Andric /// PassProtoArgs indicates whether `args` has args for the parameters in the
4177442d6faSDimitry Andric /// given CXXConstructorDecl.
4189f4dbff6SDimitry Andric const CGFunctionInfo &
arrangeCXXConstructorCall(const CallArgList & args,const CXXConstructorDecl * D,CXXCtorType CtorKind,unsigned ExtraPrefixArgs,unsigned ExtraSuffixArgs,bool PassProtoArgs)4199f4dbff6SDimitry Andric CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args,
4209f4dbff6SDimitry Andric const CXXConstructorDecl *D,
4219f4dbff6SDimitry Andric CXXCtorType CtorKind,
4227442d6faSDimitry Andric unsigned ExtraPrefixArgs,
4237442d6faSDimitry Andric unsigned ExtraSuffixArgs,
4247442d6faSDimitry Andric bool PassProtoArgs) {
4259f4dbff6SDimitry Andric // FIXME: Kill copy.
4269f4dbff6SDimitry Andric SmallVector<CanQualType, 16> ArgTypes;
42706d4ba38SDimitry Andric for (const auto &Arg : args)
42806d4ba38SDimitry Andric ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
4299f4dbff6SDimitry Andric
4307442d6faSDimitry Andric // +1 for implicit this, which should always be args[0].
4317442d6faSDimitry Andric unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs;
4327442d6faSDimitry Andric
4339f4dbff6SDimitry Andric CanQual<FunctionProtoType> FPT = GetFormalType(D);
43422989816SDimitry Andric RequiredArgs Required = PassProtoArgs
43522989816SDimitry Andric ? RequiredArgs::forPrototypePlus(
43622989816SDimitry Andric FPT, TotalPrefixArgs + ExtraSuffixArgs)
43722989816SDimitry Andric : RequiredArgs::All;
43822989816SDimitry Andric
4399f4dbff6SDimitry Andric GlobalDecl GD(D, CtorKind);
440e6b73279SDimitry Andric CanQualType ResultType = getCXXABI().HasThisReturn(GD) ? ArgTypes.front()
441e6b73279SDimitry Andric : getCXXABI().hasMostDerivedReturn(GD)
44206d4ba38SDimitry Andric ? CGM.getContext().VoidPtrTy
44306d4ba38SDimitry Andric : Context.VoidTy;
4449f4dbff6SDimitry Andric
4459f4dbff6SDimitry Andric FunctionType::ExtInfo Info = FPT->getExtInfo();
4467442d6faSDimitry Andric llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> ParamInfos;
4477442d6faSDimitry Andric // If the prototype args are elided, we should only have ABI-specific args,
4487442d6faSDimitry Andric // which never have param info.
4497442d6faSDimitry Andric if (PassProtoArgs && FPT->hasExtParameterInfos()) {
4507442d6faSDimitry Andric // ABI-specific suffix arguments are treated the same as variadic arguments.
4517442d6faSDimitry Andric addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs,
4522b6b257fSDimitry Andric ArgTypes.size());
4537442d6faSDimitry Andric }
454b1c73532SDimitry Andric
455b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(ResultType, FnInfoOpts::IsInstanceMethod,
456b1c73532SDimitry Andric ArgTypes, Info, ParamInfos, Required);
4571569ce68SRoman Divacky }
4581569ce68SRoman Divacky
459dbe13110SDimitry Andric /// Arrange the argument and result information for the declaration or
460dbe13110SDimitry Andric /// definition of the given function.
461dbe13110SDimitry Andric const CGFunctionInfo &
arrangeFunctionDeclaration(const FunctionDecl * FD)462dbe13110SDimitry Andric CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) {
463ec2b103cSEd Schouten if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
464b1c73532SDimitry Andric if (MD->isImplicitObjectMemberFunction())
465dbe13110SDimitry Andric return arrangeCXXMethodDeclaration(MD);
466ec2b103cSEd Schouten
46779ade4e0SRoman Divacky CanQualType FTy = FD->getType()->getCanonicalTypeUnqualified();
468dbe13110SDimitry Andric
46979ade4e0SRoman Divacky assert(isa<FunctionType>(FTy));
47048675466SDimitry Andric setCUDAKernelCallingConvention(FTy, CGM, FD);
471dbe13110SDimitry Andric
472dbe13110SDimitry Andric // When declaring a function without a prototype, always use a
473dbe13110SDimitry Andric // non-variadic type.
4746694ed09SDimitry Andric if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) {
475b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(noProto->getReturnType(), FnInfoOpts::None,
476b1c73532SDimitry Andric std::nullopt, noProto->getExtInfo(), {},
477e3b55780SDimitry Andric RequiredArgs::All);
478ec2b103cSEd Schouten }
479ec2b103cSEd Schouten
48022989816SDimitry Andric return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>());
481dbe13110SDimitry Andric }
482dbe13110SDimitry Andric
483dbe13110SDimitry Andric /// Arrange the argument and result information for the declaration or
484dbe13110SDimitry Andric /// definition of an Objective-C method.
485dbe13110SDimitry Andric const CGFunctionInfo &
arrangeObjCMethodDeclaration(const ObjCMethodDecl * MD)486dbe13110SDimitry Andric CodeGenTypes::arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD) {
487dbe13110SDimitry Andric // It happens that this is the same as a call with no optional
488dbe13110SDimitry Andric // arguments, except also using the formal 'self' type.
489dbe13110SDimitry Andric return arrangeObjCMessageSendSignature(MD, MD->getSelfDecl()->getType());
490dbe13110SDimitry Andric }
491dbe13110SDimitry Andric
492dbe13110SDimitry Andric /// Arrange the argument and result information for the function type
493dbe13110SDimitry Andric /// through which to perform a send to the given Objective-C method,
494dbe13110SDimitry Andric /// using the given receiver type. The receiver type is not always
495dbe13110SDimitry Andric /// the 'self' type of the method or even an Objective-C pointer type.
496dbe13110SDimitry Andric /// This is *not* the right method for actually performing such a
497dbe13110SDimitry Andric /// message send, due to the possibility of optional arguments.
498dbe13110SDimitry Andric const CGFunctionInfo &
arrangeObjCMessageSendSignature(const ObjCMethodDecl * MD,QualType receiverType)499dbe13110SDimitry Andric CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
500dbe13110SDimitry Andric QualType receiverType) {
501dbe13110SDimitry Andric SmallVector<CanQualType, 16> argTys;
502e3b55780SDimitry Andric SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(
503e3b55780SDimitry Andric MD->isDirectMethod() ? 1 : 2);
504dbe13110SDimitry Andric argTys.push_back(Context.getCanonicalParamType(receiverType));
505e3b55780SDimitry Andric if (!MD->isDirectMethod())
506dbe13110SDimitry Andric argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
507ec2b103cSEd Schouten // FIXME: Kill copy?
5082b6b257fSDimitry Andric for (const auto *I : MD->parameters()) {
5099f4dbff6SDimitry Andric argTys.push_back(Context.getCanonicalParamType(I->getType()));
510461a67faSDimitry Andric auto extParamInfo = FunctionProtoType::ExtParameterInfo().withIsNoEscape(
511461a67faSDimitry Andric I->hasAttr<NoEscapeAttr>());
512461a67faSDimitry Andric extParamInfos.push_back(extParamInfo);
51379ade4e0SRoman Divacky }
514180abc3dSDimitry Andric
515180abc3dSDimitry Andric FunctionType::ExtInfo einfo;
5169f4dbff6SDimitry Andric bool IsWindows = getContext().getTargetInfo().getTriple().isOSWindows();
5179f4dbff6SDimitry Andric einfo = einfo.withCallingConv(getCallingConventionForDecl(MD, IsWindows));
518180abc3dSDimitry Andric
519dbe13110SDimitry Andric if (getContext().getLangOpts().ObjCAutoRefCount &&
520180abc3dSDimitry Andric MD->hasAttr<NSReturnsRetainedAttr>())
521180abc3dSDimitry Andric einfo = einfo.withProducesResult(true);
522180abc3dSDimitry Andric
523dbe13110SDimitry Andric RequiredArgs required =
524dbe13110SDimitry Andric (MD->isVariadic() ? RequiredArgs(argTys.size()) : RequiredArgs::All);
525dbe13110SDimitry Andric
526b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(GetReturnType(MD->getReturnType()),
527b1c73532SDimitry Andric FnInfoOpts::None, argTys, einfo, extParamInfos,
528b1c73532SDimitry Andric required);
5292b6b257fSDimitry Andric }
5302b6b257fSDimitry Andric
5312b6b257fSDimitry Andric const CGFunctionInfo &
arrangeUnprototypedObjCMessageSend(QualType returnType,const CallArgList & args)5322b6b257fSDimitry Andric CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType,
5332b6b257fSDimitry Andric const CallArgList &args) {
5342b6b257fSDimitry Andric auto argTypes = getArgTypesForCall(Context, args);
5352b6b257fSDimitry Andric FunctionType::ExtInfo einfo;
5362b6b257fSDimitry Andric
537b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(GetReturnType(returnType), FnInfoOpts::None,
538b1c73532SDimitry Andric argTypes, einfo, {}, RequiredArgs::All);
539ecb7e5c8SRoman Divacky }
540ecb7e5c8SRoman Divacky
541dbe13110SDimitry Andric const CGFunctionInfo &
arrangeGlobalDeclaration(GlobalDecl GD)542dbe13110SDimitry Andric CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
543ecb7e5c8SRoman Divacky // FIXME: Do we need to handle ObjCMethodDecl?
544ecb7e5c8SRoman Divacky const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
545ecb7e5c8SRoman Divacky
54622989816SDimitry Andric if (isa<CXXConstructorDecl>(GD.getDecl()) ||
54722989816SDimitry Andric isa<CXXDestructorDecl>(GD.getDecl()))
54822989816SDimitry Andric return arrangeCXXStructorDeclaration(GD);
549ecb7e5c8SRoman Divacky
550dbe13110SDimitry Andric return arrangeFunctionDeclaration(FD);
551ec2b103cSEd Schouten }
552ec2b103cSEd Schouten
55306d4ba38SDimitry Andric /// Arrange a thunk that takes 'this' as the first parameter followed by
55406d4ba38SDimitry Andric /// varargs. Return a void pointer, regardless of the actual return type.
55506d4ba38SDimitry Andric /// The body of the thunk will end in a musttail call to a function of the
55606d4ba38SDimitry Andric /// correct type, and the caller will bitcast the function to the correct
55706d4ba38SDimitry Andric /// prototype.
55806d4ba38SDimitry Andric const CGFunctionInfo &
arrangeUnprototypedMustTailThunk(const CXXMethodDecl * MD)55948675466SDimitry Andric CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
56048675466SDimitry Andric assert(MD->isVirtual() && "only methods have thunks");
56106d4ba38SDimitry Andric CanQual<FunctionProtoType> FTP = GetFormalType(MD);
56222989816SDimitry Andric CanQualType ArgTys[] = {DeriveThisType(MD->getParent(), MD)};
563b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::None, ArgTys,
5642b6b257fSDimitry Andric FTP->getExtInfo(), {}, RequiredArgs(1));
56506d4ba38SDimitry Andric }
56606d4ba38SDimitry Andric
5675e20cdd8SDimitry Andric const CGFunctionInfo &
arrangeMSCtorClosure(const CXXConstructorDecl * CD,CXXCtorType CT)5685e20cdd8SDimitry Andric CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
5695e20cdd8SDimitry Andric CXXCtorType CT) {
5705e20cdd8SDimitry Andric assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure);
5715e20cdd8SDimitry Andric
5725e20cdd8SDimitry Andric CanQual<FunctionProtoType> FTP = GetFormalType(CD);
5735e20cdd8SDimitry Andric SmallVector<CanQualType, 2> ArgTys;
5745e20cdd8SDimitry Andric const CXXRecordDecl *RD = CD->getParent();
57522989816SDimitry Andric ArgTys.push_back(DeriveThisType(RD, CD));
5765e20cdd8SDimitry Andric if (CT == Ctor_CopyingClosure)
5775e20cdd8SDimitry Andric ArgTys.push_back(*FTP->param_type_begin());
5785e20cdd8SDimitry Andric if (RD->getNumVBases() > 0)
5795e20cdd8SDimitry Andric ArgTys.push_back(Context.IntTy);
5805e20cdd8SDimitry Andric CallingConv CC = Context.getDefaultCallingConvention(
5815e20cdd8SDimitry Andric /*IsVariadic=*/false, /*IsCXXMethod=*/true);
582b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::IsInstanceMethod,
583b1c73532SDimitry Andric ArgTys, FunctionType::ExtInfo(CC), {},
5842b6b257fSDimitry Andric RequiredArgs::All);
5855e20cdd8SDimitry Andric }
5865e20cdd8SDimitry Andric
587809500fcSDimitry Andric /// Arrange a call as unto a free function, except possibly with an
588809500fcSDimitry Andric /// additional number of formal parameters considered required.
589809500fcSDimitry Andric static const CGFunctionInfo &
arrangeFreeFunctionLikeCall(CodeGenTypes & CGT,CodeGenModule & CGM,const CallArgList & args,const FunctionType * fnType,unsigned numExtraRequiredArgs,bool chainCall)590809500fcSDimitry Andric arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
591bfef3995SDimitry Andric CodeGenModule &CGM,
592809500fcSDimitry Andric const CallArgList &args,
593809500fcSDimitry Andric const FunctionType *fnType,
59406d4ba38SDimitry Andric unsigned numExtraRequiredArgs,
59506d4ba38SDimitry Andric bool chainCall) {
596809500fcSDimitry Andric assert(args.size() >= numExtraRequiredArgs);
597809500fcSDimitry Andric
5982b6b257fSDimitry Andric llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
5992b6b257fSDimitry Andric
600809500fcSDimitry Andric // In most cases, there are no optional arguments.
601809500fcSDimitry Andric RequiredArgs required = RequiredArgs::All;
602809500fcSDimitry Andric
603809500fcSDimitry Andric // If we have a variadic prototype, the required arguments are the
604809500fcSDimitry Andric // extra prefix plus the arguments in the prototype.
605809500fcSDimitry Andric if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) {
606809500fcSDimitry Andric if (proto->isVariadic())
60722989816SDimitry Andric required = RequiredArgs::forPrototypePlus(proto, numExtraRequiredArgs);
608809500fcSDimitry Andric
6092b6b257fSDimitry Andric if (proto->hasExtParameterInfos())
6102b6b257fSDimitry Andric addExtParameterInfosForCall(paramInfos, proto, numExtraRequiredArgs,
6112b6b257fSDimitry Andric args.size());
6122b6b257fSDimitry Andric
613809500fcSDimitry Andric // If we don't have a prototype at all, but we're supposed to
614809500fcSDimitry Andric // explicitly use the variadic convention for unprototyped calls,
615809500fcSDimitry Andric // treat all of the arguments as required but preserve the nominal
616809500fcSDimitry Andric // possibility of variadics.
617bfef3995SDimitry Andric } else if (CGM.getTargetCodeGenInfo()
618bfef3995SDimitry Andric .isNoProtoCallVariadic(args,
619bfef3995SDimitry Andric cast<FunctionNoProtoType>(fnType))) {
620809500fcSDimitry Andric required = RequiredArgs(args.size());
621809500fcSDimitry Andric }
622809500fcSDimitry Andric
62306d4ba38SDimitry Andric // FIXME: Kill copy.
62406d4ba38SDimitry Andric SmallVector<CanQualType, 16> argTypes;
62506d4ba38SDimitry Andric for (const auto &arg : args)
62606d4ba38SDimitry Andric argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty));
627b1c73532SDimitry Andric FnInfoOpts opts = chainCall ? FnInfoOpts::IsChainCall : FnInfoOpts::None;
62806d4ba38SDimitry Andric return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()),
629b1c73532SDimitry Andric opts, argTypes, fnType->getExtInfo(),
630b1c73532SDimitry Andric paramInfos, required);
631809500fcSDimitry Andric }
632809500fcSDimitry Andric
633dbe13110SDimitry Andric /// Figure out the rules for calling a function with the given formal
634dbe13110SDimitry Andric /// type using the given arguments. The arguments are necessary
635dbe13110SDimitry Andric /// because the function might be unprototyped, in which case it's
636dbe13110SDimitry Andric /// target-dependent in crazy ways.
637dbe13110SDimitry Andric const CGFunctionInfo &
arrangeFreeFunctionCall(const CallArgList & args,const FunctionType * fnType,bool chainCall)63856d91b49SDimitry Andric CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
63906d4ba38SDimitry Andric const FunctionType *fnType,
64006d4ba38SDimitry Andric bool chainCall) {
64106d4ba38SDimitry Andric return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType,
64206d4ba38SDimitry Andric chainCall ? 1 : 0, chainCall);
643dbe13110SDimitry Andric }
644dbe13110SDimitry Andric
6452b6b257fSDimitry Andric /// A block function is essentially a free function with an
646809500fcSDimitry Andric /// extra implicit argument.
647809500fcSDimitry Andric const CGFunctionInfo &
arrangeBlockFunctionCall(const CallArgList & args,const FunctionType * fnType)648809500fcSDimitry Andric CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args,
649809500fcSDimitry Andric const FunctionType *fnType) {
65006d4ba38SDimitry Andric return arrangeFreeFunctionLikeCall(*this, CGM, args, fnType, 1,
65106d4ba38SDimitry Andric /*chainCall=*/false);
652dbe13110SDimitry Andric }
653dbe13110SDimitry Andric
654dbe13110SDimitry Andric const CGFunctionInfo &
arrangeBlockFunctionDeclaration(const FunctionProtoType * proto,const FunctionArgList & params)6552b6b257fSDimitry Andric CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto,
6562b6b257fSDimitry Andric const FunctionArgList ¶ms) {
6572b6b257fSDimitry Andric auto paramInfos = getExtParameterInfosForCall(proto, 1, params.size());
6582b6b257fSDimitry Andric auto argTypes = getArgTypesForDeclaration(Context, params);
6592b6b257fSDimitry Andric
66022989816SDimitry Andric return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()),
661b1c73532SDimitry Andric FnInfoOpts::None, argTypes,
662b1c73532SDimitry Andric proto->getExtInfo(), paramInfos,
66322989816SDimitry Andric RequiredArgs::forPrototypePlus(proto, 1));
6642b6b257fSDimitry Andric }
6652b6b257fSDimitry Andric
6662b6b257fSDimitry Andric const CGFunctionInfo &
arrangeBuiltinFunctionCall(QualType resultType,const CallArgList & args)6672b6b257fSDimitry Andric CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType,
6682b6b257fSDimitry Andric const CallArgList &args) {
669ec2b103cSEd Schouten // FIXME: Kill copy.
670dbe13110SDimitry Andric SmallVector<CanQualType, 16> argTypes;
67106d4ba38SDimitry Andric for (const auto &Arg : args)
67206d4ba38SDimitry Andric argTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
673b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None,
674b1c73532SDimitry Andric argTypes, FunctionType::ExtInfo(),
6752b6b257fSDimitry Andric /*paramInfos=*/{}, RequiredArgs::All);
6762b6b257fSDimitry Andric }
6772b6b257fSDimitry Andric
6782b6b257fSDimitry Andric const CGFunctionInfo &
arrangeBuiltinFunctionDeclaration(QualType resultType,const FunctionArgList & args)6792b6b257fSDimitry Andric CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType,
6802b6b257fSDimitry Andric const FunctionArgList &args) {
6812b6b257fSDimitry Andric auto argTypes = getArgTypesForDeclaration(Context, args);
6822b6b257fSDimitry Andric
683b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(GetReturnType(resultType), FnInfoOpts::None,
684b1c73532SDimitry Andric argTypes, FunctionType::ExtInfo(), {},
685b1c73532SDimitry Andric RequiredArgs::All);
6862b6b257fSDimitry Andric }
6872b6b257fSDimitry Andric
6882b6b257fSDimitry Andric const CGFunctionInfo &
arrangeBuiltinFunctionDeclaration(CanQualType resultType,ArrayRef<CanQualType> argTypes)6892b6b257fSDimitry Andric CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType,
6902b6b257fSDimitry Andric ArrayRef<CanQualType> argTypes) {
691b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(resultType, FnInfoOpts::None, argTypes,
692b1c73532SDimitry Andric FunctionType::ExtInfo(), {},
693b1c73532SDimitry Andric RequiredArgs::All);
694ec2b103cSEd Schouten }
695ec2b103cSEd Schouten
69656d91b49SDimitry Andric /// Arrange a call to a C++ method, passing the given arguments.
6977442d6faSDimitry Andric ///
6987442d6faSDimitry Andric /// numPrefixArgs is the number of ABI-specific prefix arguments we have. It
6997442d6faSDimitry Andric /// does not count `this`.
70056d91b49SDimitry Andric const CGFunctionInfo &
arrangeCXXMethodCall(const CallArgList & args,const FunctionProtoType * proto,RequiredArgs required,unsigned numPrefixArgs)70156d91b49SDimitry Andric CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args,
7022b6b257fSDimitry Andric const FunctionProtoType *proto,
7037442d6faSDimitry Andric RequiredArgs required,
7047442d6faSDimitry Andric unsigned numPrefixArgs) {
7057442d6faSDimitry Andric assert(numPrefixArgs + 1 <= args.size() &&
7067442d6faSDimitry Andric "Emitting a call with less args than the required prefix?");
7077442d6faSDimitry Andric // Add one to account for `this`. It's a bit awkward here, but we don't count
7087442d6faSDimitry Andric // `this` in similar places elsewhere.
7092b6b257fSDimitry Andric auto paramInfos =
7107442d6faSDimitry Andric getExtParameterInfosForCall(proto, numPrefixArgs + 1, args.size());
7112b6b257fSDimitry Andric
71256d91b49SDimitry Andric // FIXME: Kill copy.
7132b6b257fSDimitry Andric auto argTypes = getArgTypesForCall(Context, args);
71456d91b49SDimitry Andric
7152b6b257fSDimitry Andric FunctionType::ExtInfo info = proto->getExtInfo();
716b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(GetReturnType(proto->getReturnType()),
717b1c73532SDimitry Andric FnInfoOpts::IsInstanceMethod, argTypes, info,
718b1c73532SDimitry Andric paramInfos, required);
719ec2b103cSEd Schouten }
720ec2b103cSEd Schouten
arrangeNullaryFunction()721dbe13110SDimitry Andric const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
722b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(getContext().VoidTy, FnInfoOpts::None,
723b1c73532SDimitry Andric std::nullopt, FunctionType::ExtInfo(), {},
724b1c73532SDimitry Andric RequiredArgs::All);
7252b6b257fSDimitry Andric }
7262b6b257fSDimitry Andric
7272b6b257fSDimitry Andric const CGFunctionInfo &
arrangeCall(const CGFunctionInfo & signature,const CallArgList & args)7282b6b257fSDimitry Andric CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
7292b6b257fSDimitry Andric const CallArgList &args) {
7302b6b257fSDimitry Andric assert(signature.arg_size() <= args.size());
7312b6b257fSDimitry Andric if (signature.arg_size() == args.size())
7322b6b257fSDimitry Andric return signature;
7332b6b257fSDimitry Andric
7342b6b257fSDimitry Andric SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
7352b6b257fSDimitry Andric auto sigParamInfos = signature.getExtParameterInfos();
7362b6b257fSDimitry Andric if (!sigParamInfos.empty()) {
7372b6b257fSDimitry Andric paramInfos.append(sigParamInfos.begin(), sigParamInfos.end());
7382b6b257fSDimitry Andric paramInfos.resize(args.size());
7392b6b257fSDimitry Andric }
7402b6b257fSDimitry Andric
7412b6b257fSDimitry Andric auto argTypes = getArgTypesForCall(Context, args);
7422b6b257fSDimitry Andric
7432b6b257fSDimitry Andric assert(signature.getRequiredArgs().allowsOptionalArgs());
744b1c73532SDimitry Andric FnInfoOpts opts = FnInfoOpts::None;
745b1c73532SDimitry Andric if (signature.isInstanceMethod())
746b1c73532SDimitry Andric opts |= FnInfoOpts::IsInstanceMethod;
747b1c73532SDimitry Andric if (signature.isChainCall())
748b1c73532SDimitry Andric opts |= FnInfoOpts::IsChainCall;
749b1c73532SDimitry Andric if (signature.isDelegateCall())
750b1c73532SDimitry Andric opts |= FnInfoOpts::IsDelegateCall;
751b1c73532SDimitry Andric return arrangeLLVMFunctionInfo(signature.getReturnType(), opts, argTypes,
752b1c73532SDimitry Andric signature.getExtInfo(), paramInfos,
7532b6b257fSDimitry Andric signature.getRequiredArgs());
75401af97d3SDimitry Andric }
75501af97d3SDimitry Andric
756416ada0fSDimitry Andric namespace clang {
757416ada0fSDimitry Andric namespace CodeGen {
758416ada0fSDimitry Andric void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
759416ada0fSDimitry Andric }
760416ada0fSDimitry Andric }
761416ada0fSDimitry Andric
762dbe13110SDimitry Andric /// Arrange the argument and result information for an abstract value
763dbe13110SDimitry Andric /// of a given function type. This is the method which all of the
764dbe13110SDimitry Andric /// above functions ultimately defer to.
arrangeLLVMFunctionInfo(CanQualType resultType,FnInfoOpts opts,ArrayRef<CanQualType> argTypes,FunctionType::ExtInfo info,ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,RequiredArgs required)765b1c73532SDimitry Andric const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
766b1c73532SDimitry Andric CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
76756d91b49SDimitry Andric FunctionType::ExtInfo info,
7682b6b257fSDimitry Andric ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
769dbe13110SDimitry Andric RequiredArgs required) {
770676fbe81SDimitry Andric assert(llvm::all_of(argTypes,
7717442d6faSDimitry Andric [](CanQualType T) { return T.isCanonicalAsParam(); }));
77279ade4e0SRoman Divacky
773ec2b103cSEd Schouten // Lookup or create unique function info.
774ec2b103cSEd Schouten llvm::FoldingSetNodeID ID;
775b1c73532SDimitry Andric bool isInstanceMethod =
776b1c73532SDimitry Andric (opts & FnInfoOpts::IsInstanceMethod) == FnInfoOpts::IsInstanceMethod;
777b1c73532SDimitry Andric bool isChainCall =
778b1c73532SDimitry Andric (opts & FnInfoOpts::IsChainCall) == FnInfoOpts::IsChainCall;
779b1c73532SDimitry Andric bool isDelegateCall =
780b1c73532SDimitry Andric (opts & FnInfoOpts::IsDelegateCall) == FnInfoOpts::IsDelegateCall;
781b1c73532SDimitry Andric CGFunctionInfo::Profile(ID, isInstanceMethod, isChainCall, isDelegateCall,
782b1c73532SDimitry Andric info, paramInfos, required, resultType, argTypes);
783ec2b103cSEd Schouten
7849f4dbff6SDimitry Andric void *insertPos = nullptr;
785dbe13110SDimitry Andric CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
786ec2b103cSEd Schouten if (FI)
787ec2b103cSEd Schouten return *FI;
788ec2b103cSEd Schouten
7892b6b257fSDimitry Andric unsigned CC = ClangCallConvToLLVMCallConv(info.getCC());
7902b6b257fSDimitry Andric
791dbe13110SDimitry Andric // Construct the function info. We co-allocate the ArgInfos.
792b1c73532SDimitry Andric FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall,
793b1c73532SDimitry Andric info, paramInfos, resultType, argTypes, required);
794dbe13110SDimitry Andric FunctionInfos.InsertNode(FI, insertPos);
795ec2b103cSEd Schouten
79606d4ba38SDimitry Andric bool inserted = FunctionsBeingProcessed.insert(FI).second;
79706d4ba38SDimitry Andric (void)inserted;
798dbe13110SDimitry Andric assert(inserted && "Recursively being processed?");
799180abc3dSDimitry Andric
800ec2b103cSEd Schouten // Compute ABI information.
801416ada0fSDimitry Andric if (CC == llvm::CallingConv::SPIR_KERNEL) {
802416ada0fSDimitry Andric // Force target independent argument handling for the host visible
803416ada0fSDimitry Andric // kernel functions.
804416ada0fSDimitry Andric computeSPIRKernelABIInfo(CGM, *FI);
805344a3780SDimitry Andric } else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) {
8062b6b257fSDimitry Andric swiftcall::computeABIInfo(CGM, *FI);
807416ada0fSDimitry Andric } else {
808e6b73279SDimitry Andric CGM.getABIInfo().computeInfo(*FI);
8092b6b257fSDimitry Andric }
8103d1dcd9bSDimitry Andric
8113d1dcd9bSDimitry Andric // Loop over all of the computed argument and return value info. If any of
8123d1dcd9bSDimitry Andric // them are direct or extend without a specified coerce type, specify the
8133d1dcd9bSDimitry Andric // default now.
814dbe13110SDimitry Andric ABIArgInfo &retInfo = FI->getReturnInfo();
8159f4dbff6SDimitry Andric if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr)
816dbe13110SDimitry Andric retInfo.setCoerceToType(ConvertType(FI->getReturnType()));
8173d1dcd9bSDimitry Andric
8189f4dbff6SDimitry Andric for (auto &I : FI->arguments())
8199f4dbff6SDimitry Andric if (I.info.canHaveCoerceToType() && I.info.getCoerceToType() == nullptr)
8209f4dbff6SDimitry Andric I.info.setCoerceToType(ConvertType(I.type));
8214ba67500SRoman Divacky
822dbe13110SDimitry Andric bool erased = FunctionsBeingProcessed.erase(FI); (void)erased;
823dbe13110SDimitry Andric assert(erased && "Not in set?");
824ec2b103cSEd Schouten
825ec2b103cSEd Schouten return *FI;
826ec2b103cSEd Schouten }
827ec2b103cSEd Schouten
create(unsigned llvmCC,bool instanceMethod,bool chainCall,bool delegateCall,const FunctionType::ExtInfo & info,ArrayRef<ExtParameterInfo> paramInfos,CanQualType resultType,ArrayRef<CanQualType> argTypes,RequiredArgs required)828b1c73532SDimitry Andric CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod,
829b1c73532SDimitry Andric bool chainCall, bool delegateCall,
830dbe13110SDimitry Andric const FunctionType::ExtInfo &info,
8312b6b257fSDimitry Andric ArrayRef<ExtParameterInfo> paramInfos,
832dbe13110SDimitry Andric CanQualType resultType,
833dbe13110SDimitry Andric ArrayRef<CanQualType> argTypes,
834dbe13110SDimitry Andric RequiredArgs required) {
8352b6b257fSDimitry Andric assert(paramInfos.empty() || paramInfos.size() == argTypes.size());
83622989816SDimitry Andric assert(!required.allowsOptionalArgs() ||
83722989816SDimitry Andric required.getNumRequiredArgs() <= argTypes.size());
8382b6b257fSDimitry Andric
8392b6b257fSDimitry Andric void *buffer =
8402b6b257fSDimitry Andric operator new(totalSizeToAlloc<ArgInfo, ExtParameterInfo>(
8412b6b257fSDimitry Andric argTypes.size() + 1, paramInfos.size()));
8422b6b257fSDimitry Andric
843dbe13110SDimitry Andric CGFunctionInfo *FI = new(buffer) CGFunctionInfo();
844dbe13110SDimitry Andric FI->CallingConvention = llvmCC;
845dbe13110SDimitry Andric FI->EffectiveCallingConvention = llvmCC;
846dbe13110SDimitry Andric FI->ASTCallingConvention = info.getCC();
84706d4ba38SDimitry Andric FI->InstanceMethod = instanceMethod;
84806d4ba38SDimitry Andric FI->ChainCall = chainCall;
849b1c73532SDimitry Andric FI->DelegateCall = delegateCall;
850cfca06d7SDimitry Andric FI->CmseNSCall = info.getCmseNSCall();
851dbe13110SDimitry Andric FI->NoReturn = info.getNoReturn();
852dbe13110SDimitry Andric FI->ReturnsRetained = info.getProducesResult();
85357091882SDimitry Andric FI->NoCallerSavedRegs = info.getNoCallerSavedRegs();
85448675466SDimitry Andric FI->NoCfCheck = info.getNoCfCheck();
855dbe13110SDimitry Andric FI->Required = required;
856dbe13110SDimitry Andric FI->HasRegParm = info.getHasRegParm();
857dbe13110SDimitry Andric FI->RegParm = info.getRegParm();
8589f4dbff6SDimitry Andric FI->ArgStruct = nullptr;
85945b53394SDimitry Andric FI->ArgStructAlign = 0;
860dbe13110SDimitry Andric FI->NumArgs = argTypes.size();
8612b6b257fSDimitry Andric FI->HasExtParameterInfos = !paramInfos.empty();
862dbe13110SDimitry Andric FI->getArgsBuffer()[0].type = resultType;
863145449b1SDimitry Andric FI->MaxVectorWidth = 0;
864dbe13110SDimitry Andric for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
865dbe13110SDimitry Andric FI->getArgsBuffer()[i + 1].type = argTypes[i];
8662b6b257fSDimitry Andric for (unsigned i = 0, e = paramInfos.size(); i != e; ++i)
8672b6b257fSDimitry Andric FI->getExtParameterInfosBuffer()[i] = paramInfos[i];
868dbe13110SDimitry Andric return FI;
869ec2b103cSEd Schouten }
870ec2b103cSEd Schouten
871ec2b103cSEd Schouten /***/
872ec2b103cSEd Schouten
87306d4ba38SDimitry Andric namespace {
87406d4ba38SDimitry Andric // ABIArgInfo::Expand implementation.
87506d4ba38SDimitry Andric
87606d4ba38SDimitry Andric // Specifies the way QualType passed as ABIArgInfo::Expand is expanded.
87706d4ba38SDimitry Andric struct TypeExpansion {
87806d4ba38SDimitry Andric enum TypeExpansionKind {
87906d4ba38SDimitry Andric // Elements of constant arrays are expanded recursively.
88006d4ba38SDimitry Andric TEK_ConstantArray,
88106d4ba38SDimitry Andric // Record fields are expanded recursively (but if record is a union, only
88206d4ba38SDimitry Andric // the field with the largest size is expanded).
88306d4ba38SDimitry Andric TEK_Record,
88406d4ba38SDimitry Andric // For complex types, real and imaginary parts are expanded recursively.
88506d4ba38SDimitry Andric TEK_Complex,
88606d4ba38SDimitry Andric // All other types are not expandable.
88706d4ba38SDimitry Andric TEK_None
88806d4ba38SDimitry Andric };
88906d4ba38SDimitry Andric
89006d4ba38SDimitry Andric const TypeExpansionKind Kind;
89106d4ba38SDimitry Andric
TypeExpansion__anon748148590211::TypeExpansion89206d4ba38SDimitry Andric TypeExpansion(TypeExpansionKind K) : Kind(K) {}
~TypeExpansion__anon748148590211::TypeExpansion89306d4ba38SDimitry Andric virtual ~TypeExpansion() {}
89406d4ba38SDimitry Andric };
89506d4ba38SDimitry Andric
89606d4ba38SDimitry Andric struct ConstantArrayExpansion : TypeExpansion {
89706d4ba38SDimitry Andric QualType EltTy;
89806d4ba38SDimitry Andric uint64_t NumElts;
89906d4ba38SDimitry Andric
ConstantArrayExpansion__anon748148590211::ConstantArrayExpansion90006d4ba38SDimitry Andric ConstantArrayExpansion(QualType EltTy, uint64_t NumElts)
90106d4ba38SDimitry Andric : TypeExpansion(TEK_ConstantArray), EltTy(EltTy), NumElts(NumElts) {}
classof__anon748148590211::ConstantArrayExpansion90206d4ba38SDimitry Andric static bool classof(const TypeExpansion *TE) {
90306d4ba38SDimitry Andric return TE->Kind == TEK_ConstantArray;
90406d4ba38SDimitry Andric }
90506d4ba38SDimitry Andric };
90606d4ba38SDimitry Andric
90706d4ba38SDimitry Andric struct RecordExpansion : TypeExpansion {
90806d4ba38SDimitry Andric SmallVector<const CXXBaseSpecifier *, 1> Bases;
90906d4ba38SDimitry Andric
91006d4ba38SDimitry Andric SmallVector<const FieldDecl *, 1> Fields;
91106d4ba38SDimitry Andric
RecordExpansion__anon748148590211::RecordExpansion91206d4ba38SDimitry Andric RecordExpansion(SmallVector<const CXXBaseSpecifier *, 1> &&Bases,
91306d4ba38SDimitry Andric SmallVector<const FieldDecl *, 1> &&Fields)
9142b6b257fSDimitry Andric : TypeExpansion(TEK_Record), Bases(std::move(Bases)),
9152b6b257fSDimitry Andric Fields(std::move(Fields)) {}
classof__anon748148590211::RecordExpansion91606d4ba38SDimitry Andric static bool classof(const TypeExpansion *TE) {
91706d4ba38SDimitry Andric return TE->Kind == TEK_Record;
91806d4ba38SDimitry Andric }
91906d4ba38SDimitry Andric };
92006d4ba38SDimitry Andric
92106d4ba38SDimitry Andric struct ComplexExpansion : TypeExpansion {
92206d4ba38SDimitry Andric QualType EltTy;
92306d4ba38SDimitry Andric
ComplexExpansion__anon748148590211::ComplexExpansion92406d4ba38SDimitry Andric ComplexExpansion(QualType EltTy) : TypeExpansion(TEK_Complex), EltTy(EltTy) {}
classof__anon748148590211::ComplexExpansion92506d4ba38SDimitry Andric static bool classof(const TypeExpansion *TE) {
92606d4ba38SDimitry Andric return TE->Kind == TEK_Complex;
92706d4ba38SDimitry Andric }
92806d4ba38SDimitry Andric };
92906d4ba38SDimitry Andric
93006d4ba38SDimitry Andric struct NoExpansion : TypeExpansion {
NoExpansion__anon748148590211::NoExpansion93106d4ba38SDimitry Andric NoExpansion() : TypeExpansion(TEK_None) {}
classof__anon748148590211::NoExpansion93206d4ba38SDimitry Andric static bool classof(const TypeExpansion *TE) {
93306d4ba38SDimitry Andric return TE->Kind == TEK_None;
93406d4ba38SDimitry Andric }
93506d4ba38SDimitry Andric };
93606d4ba38SDimitry Andric } // namespace
93706d4ba38SDimitry Andric
93806d4ba38SDimitry Andric static std::unique_ptr<TypeExpansion>
getTypeExpansion(QualType Ty,const ASTContext & Context)93906d4ba38SDimitry Andric getTypeExpansion(QualType Ty, const ASTContext &Context) {
94006d4ba38SDimitry Andric if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
941ac9a064cSDimitry Andric return std::make_unique<ConstantArrayExpansion>(AT->getElementType(),
942ac9a064cSDimitry Andric AT->getZExtSize());
94306d4ba38SDimitry Andric }
94406d4ba38SDimitry Andric if (const RecordType *RT = Ty->getAs<RecordType>()) {
94506d4ba38SDimitry Andric SmallVector<const CXXBaseSpecifier *, 1> Bases;
94606d4ba38SDimitry Andric SmallVector<const FieldDecl *, 1> Fields;
947ec2b103cSEd Schouten const RecordDecl *RD = RT->getDecl();
948ec2b103cSEd Schouten assert(!RD->hasFlexibleArrayMember() &&
949ec2b103cSEd Schouten "Cannot expand structure with flexible array.");
9506b9a6e39SDimitry Andric if (RD->isUnion()) {
9516b9a6e39SDimitry Andric // Unions can be here only in degenerative cases - all the fields are same
9526b9a6e39SDimitry Andric // after flattening. Thus we have to use the "largest" field.
9539f4dbff6SDimitry Andric const FieldDecl *LargestFD = nullptr;
9546b9a6e39SDimitry Andric CharUnits UnionSize = CharUnits::Zero();
9556b9a6e39SDimitry Andric
9569f4dbff6SDimitry Andric for (const auto *FD : RD->fields()) {
95748675466SDimitry Andric if (FD->isZeroLengthBitField(Context))
95806d4ba38SDimitry Andric continue;
9596b9a6e39SDimitry Andric assert(!FD->isBitField() &&
9606b9a6e39SDimitry Andric "Cannot expand structure with bit-field members.");
96106d4ba38SDimitry Andric CharUnits FieldSize = Context.getTypeSizeInChars(FD->getType());
9626b9a6e39SDimitry Andric if (UnionSize < FieldSize) {
9636b9a6e39SDimitry Andric UnionSize = FieldSize;
9646b9a6e39SDimitry Andric LargestFD = FD;
9656b9a6e39SDimitry Andric }
9666b9a6e39SDimitry Andric }
9676b9a6e39SDimitry Andric if (LargestFD)
96806d4ba38SDimitry Andric Fields.push_back(LargestFD);
9696b9a6e39SDimitry Andric } else {
97006d4ba38SDimitry Andric if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
97106d4ba38SDimitry Andric assert(!CXXRD->isDynamicClass() &&
97206d4ba38SDimitry Andric "cannot expand vtable pointers in dynamic classes");
973145449b1SDimitry Andric llvm::append_range(Bases, llvm::make_pointer_range(CXXRD->bases()));
974ec2b103cSEd Schouten }
975ec2b103cSEd Schouten
97606d4ba38SDimitry Andric for (const auto *FD : RD->fields()) {
97748675466SDimitry Andric if (FD->isZeroLengthBitField(Context))
97806d4ba38SDimitry Andric continue;
97906d4ba38SDimitry Andric assert(!FD->isBitField() &&
98006d4ba38SDimitry Andric "Cannot expand structure with bit-field members.");
98106d4ba38SDimitry Andric Fields.push_back(FD);
98206d4ba38SDimitry Andric }
98306d4ba38SDimitry Andric }
984519fc96cSDimitry Andric return std::make_unique<RecordExpansion>(std::move(Bases),
98506d4ba38SDimitry Andric std::move(Fields));
98606d4ba38SDimitry Andric }
98706d4ba38SDimitry Andric if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
988519fc96cSDimitry Andric return std::make_unique<ComplexExpansion>(CT->getElementType());
98906d4ba38SDimitry Andric }
990519fc96cSDimitry Andric return std::make_unique<NoExpansion>();
99106d4ba38SDimitry Andric }
99206d4ba38SDimitry Andric
getExpansionSize(QualType Ty,const ASTContext & Context)99306d4ba38SDimitry Andric static int getExpansionSize(QualType Ty, const ASTContext &Context) {
99406d4ba38SDimitry Andric auto Exp = getTypeExpansion(Ty, Context);
99506d4ba38SDimitry Andric if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
99606d4ba38SDimitry Andric return CAExp->NumElts * getExpansionSize(CAExp->EltTy, Context);
99706d4ba38SDimitry Andric }
99806d4ba38SDimitry Andric if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
99906d4ba38SDimitry Andric int Res = 0;
100006d4ba38SDimitry Andric for (auto BS : RExp->Bases)
100106d4ba38SDimitry Andric Res += getExpansionSize(BS->getType(), Context);
100206d4ba38SDimitry Andric for (auto FD : RExp->Fields)
100306d4ba38SDimitry Andric Res += getExpansionSize(FD->getType(), Context);
100406d4ba38SDimitry Andric return Res;
100506d4ba38SDimitry Andric }
100606d4ba38SDimitry Andric if (isa<ComplexExpansion>(Exp.get()))
100706d4ba38SDimitry Andric return 2;
100806d4ba38SDimitry Andric assert(isa<NoExpansion>(Exp.get()));
100906d4ba38SDimitry Andric return 1;
101006d4ba38SDimitry Andric }
101106d4ba38SDimitry Andric
101206d4ba38SDimitry Andric void
getExpandedTypes(QualType Ty,SmallVectorImpl<llvm::Type * >::iterator & TI)101306d4ba38SDimitry Andric CodeGenTypes::getExpandedTypes(QualType Ty,
101406d4ba38SDimitry Andric SmallVectorImpl<llvm::Type *>::iterator &TI) {
101506d4ba38SDimitry Andric auto Exp = getTypeExpansion(Ty, Context);
101606d4ba38SDimitry Andric if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
101706d4ba38SDimitry Andric for (int i = 0, n = CAExp->NumElts; i < n; i++) {
101806d4ba38SDimitry Andric getExpandedTypes(CAExp->EltTy, TI);
101906d4ba38SDimitry Andric }
102006d4ba38SDimitry Andric } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
102106d4ba38SDimitry Andric for (auto BS : RExp->Bases)
102206d4ba38SDimitry Andric getExpandedTypes(BS->getType(), TI);
102306d4ba38SDimitry Andric for (auto FD : RExp->Fields)
102406d4ba38SDimitry Andric getExpandedTypes(FD->getType(), TI);
102506d4ba38SDimitry Andric } else if (auto CExp = dyn_cast<ComplexExpansion>(Exp.get())) {
102606d4ba38SDimitry Andric llvm::Type *EltTy = ConvertType(CExp->EltTy);
102706d4ba38SDimitry Andric *TI++ = EltTy;
102806d4ba38SDimitry Andric *TI++ = EltTy;
102906d4ba38SDimitry Andric } else {
103006d4ba38SDimitry Andric assert(isa<NoExpansion>(Exp.get()));
103106d4ba38SDimitry Andric *TI++ = ConvertType(Ty);
103206d4ba38SDimitry Andric }
103306d4ba38SDimitry Andric }
103406d4ba38SDimitry Andric
forConstantArrayExpansion(CodeGenFunction & CGF,ConstantArrayExpansion * CAE,Address BaseAddr,llvm::function_ref<void (Address)> Fn)103545b53394SDimitry Andric static void forConstantArrayExpansion(CodeGenFunction &CGF,
103645b53394SDimitry Andric ConstantArrayExpansion *CAE,
103745b53394SDimitry Andric Address BaseAddr,
103845b53394SDimitry Andric llvm::function_ref<void(Address)> Fn) {
103945b53394SDimitry Andric for (int i = 0, n = CAE->NumElts; i < n; i++) {
1040ac9a064cSDimitry Andric Address EltAddr = CGF.Builder.CreateConstGEP2_32(BaseAddr, 0, i);
1041ac9a064cSDimitry Andric Fn(EltAddr);
104245b53394SDimitry Andric }
104345b53394SDimitry Andric }
104445b53394SDimitry Andric
ExpandTypeFromArgs(QualType Ty,LValue LV,llvm::Function::arg_iterator & AI)1045cfca06d7SDimitry Andric void CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
1046cfca06d7SDimitry Andric llvm::Function::arg_iterator &AI) {
1047ec2b103cSEd Schouten assert(LV.isSimple() &&
1048ec2b103cSEd Schouten "Unexpected non-simple lvalue during struct expansion.");
104936981b17SDimitry Andric
105006d4ba38SDimitry Andric auto Exp = getTypeExpansion(Ty, getContext());
105106d4ba38SDimitry Andric if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
1052706b4fc4SDimitry Andric forConstantArrayExpansion(
1053ac9a064cSDimitry Andric *this, CAExp, LV.getAddress(), [&](Address EltAddr) {
105406d4ba38SDimitry Andric LValue LV = MakeAddrLValue(EltAddr, CAExp->EltTy);
105506d4ba38SDimitry Andric ExpandTypeFromArgs(CAExp->EltTy, LV, AI);
105645b53394SDimitry Andric });
105706d4ba38SDimitry Andric } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
1058ac9a064cSDimitry Andric Address This = LV.getAddress();
105906d4ba38SDimitry Andric for (const CXXBaseSpecifier *BS : RExp->Bases) {
106006d4ba38SDimitry Andric // Perform a single step derived-to-base conversion.
106145b53394SDimitry Andric Address Base =
106206d4ba38SDimitry Andric GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
106306d4ba38SDimitry Andric /*NullCheckValue=*/false, SourceLocation());
106406d4ba38SDimitry Andric LValue SubLV = MakeAddrLValue(Base, BS->getType());
10656b9a6e39SDimitry Andric
106606d4ba38SDimitry Andric // Recurse onto bases.
106706d4ba38SDimitry Andric ExpandTypeFromArgs(BS->getType(), SubLV, AI);
10686b9a6e39SDimitry Andric }
106906d4ba38SDimitry Andric for (auto FD : RExp->Fields) {
1070ec2b103cSEd Schouten // FIXME: What are the right qualifiers here?
10712b6b257fSDimitry Andric LValue SubLV = EmitLValueForFieldInitialization(LV, FD);
107206d4ba38SDimitry Andric ExpandTypeFromArgs(FD->getType(), SubLV, AI);
10736b9a6e39SDimitry Andric }
107445b53394SDimitry Andric } else if (isa<ComplexExpansion>(Exp.get())) {
1075cfca06d7SDimitry Andric auto realValue = &*AI++;
1076cfca06d7SDimitry Andric auto imagValue = &*AI++;
107745b53394SDimitry Andric EmitStoreOfComplex(ComplexPairTy(realValue, imagValue), LV, /*init*/ true);
1078ec2b103cSEd Schouten } else {
1079706b4fc4SDimitry Andric // Call EmitStoreOfScalar except when the lvalue is a bitfield to emit a
1080706b4fc4SDimitry Andric // primitive store.
108106d4ba38SDimitry Andric assert(isa<NoExpansion>(Exp.get()));
1082145449b1SDimitry Andric llvm::Value *Arg = &*AI++;
1083145449b1SDimitry Andric if (LV.isBitField()) {
1084145449b1SDimitry Andric EmitStoreThroughLValue(RValue::get(Arg), LV);
1085145449b1SDimitry Andric } else {
1086145449b1SDimitry Andric // TODO: currently there are some places are inconsistent in what LLVM
1087145449b1SDimitry Andric // pointer type they use (see D118744). Once clang uses opaque pointers
1088145449b1SDimitry Andric // all LLVM pointer types will be the same and we can remove this check.
1089145449b1SDimitry Andric if (Arg->getType()->isPointerTy()) {
1090ac9a064cSDimitry Andric Address Addr = LV.getAddress();
1091145449b1SDimitry Andric Arg = Builder.CreateBitCast(Arg, Addr.getElementType());
1092145449b1SDimitry Andric }
1093145449b1SDimitry Andric EmitStoreOfScalar(Arg, LV);
1094145449b1SDimitry Andric }
109506d4ba38SDimitry Andric }
1096ec2b103cSEd Schouten }
1097ec2b103cSEd Schouten
ExpandTypeToArgs(QualType Ty,CallArg Arg,llvm::FunctionType * IRFuncTy,SmallVectorImpl<llvm::Value * > & IRCallArgs,unsigned & IRCallArgPos)109806d4ba38SDimitry Andric void CodeGenFunction::ExpandTypeToArgs(
109948675466SDimitry Andric QualType Ty, CallArg Arg, llvm::FunctionType *IRFuncTy,
110006d4ba38SDimitry Andric SmallVectorImpl<llvm::Value *> &IRCallArgs, unsigned &IRCallArgPos) {
110106d4ba38SDimitry Andric auto Exp = getTypeExpansion(Ty, getContext());
110206d4ba38SDimitry Andric if (auto CAExp = dyn_cast<ConstantArrayExpansion>(Exp.get())) {
1103ac9a064cSDimitry Andric Address Addr = Arg.hasLValue() ? Arg.getKnownLValue().getAddress()
110448675466SDimitry Andric : Arg.getKnownRValue().getAggregateAddress();
110548675466SDimitry Andric forConstantArrayExpansion(
110648675466SDimitry Andric *this, CAExp, Addr, [&](Address EltAddr) {
110748675466SDimitry Andric CallArg EltArg = CallArg(
110848675466SDimitry Andric convertTempToRValue(EltAddr, CAExp->EltTy, SourceLocation()),
110948675466SDimitry Andric CAExp->EltTy);
111048675466SDimitry Andric ExpandTypeToArgs(CAExp->EltTy, EltArg, IRFuncTy, IRCallArgs,
111148675466SDimitry Andric IRCallArgPos);
111245b53394SDimitry Andric });
111306d4ba38SDimitry Andric } else if (auto RExp = dyn_cast<RecordExpansion>(Exp.get())) {
1114ac9a064cSDimitry Andric Address This = Arg.hasLValue() ? Arg.getKnownLValue().getAddress()
111548675466SDimitry Andric : Arg.getKnownRValue().getAggregateAddress();
111606d4ba38SDimitry Andric for (const CXXBaseSpecifier *BS : RExp->Bases) {
111706d4ba38SDimitry Andric // Perform a single step derived-to-base conversion.
111845b53394SDimitry Andric Address Base =
111906d4ba38SDimitry Andric GetAddressOfBaseClass(This, Ty->getAsCXXRecordDecl(), &BS, &BS + 1,
112006d4ba38SDimitry Andric /*NullCheckValue=*/false, SourceLocation());
112148675466SDimitry Andric CallArg BaseArg = CallArg(RValue::getAggregate(Base), BS->getType());
112206d4ba38SDimitry Andric
112306d4ba38SDimitry Andric // Recurse onto bases.
112448675466SDimitry Andric ExpandTypeToArgs(BS->getType(), BaseArg, IRFuncTy, IRCallArgs,
112506d4ba38SDimitry Andric IRCallArgPos);
112606d4ba38SDimitry Andric }
112706d4ba38SDimitry Andric
112806d4ba38SDimitry Andric LValue LV = MakeAddrLValue(This, Ty);
112906d4ba38SDimitry Andric for (auto FD : RExp->Fields) {
113048675466SDimitry Andric CallArg FldArg =
113148675466SDimitry Andric CallArg(EmitRValueForField(LV, FD, SourceLocation()), FD->getType());
113248675466SDimitry Andric ExpandTypeToArgs(FD->getType(), FldArg, IRFuncTy, IRCallArgs,
113306d4ba38SDimitry Andric IRCallArgPos);
113406d4ba38SDimitry Andric }
113506d4ba38SDimitry Andric } else if (isa<ComplexExpansion>(Exp.get())) {
113648675466SDimitry Andric ComplexPairTy CV = Arg.getKnownRValue().getComplexVal();
113706d4ba38SDimitry Andric IRCallArgs[IRCallArgPos++] = CV.first;
113806d4ba38SDimitry Andric IRCallArgs[IRCallArgPos++] = CV.second;
113906d4ba38SDimitry Andric } else {
114006d4ba38SDimitry Andric assert(isa<NoExpansion>(Exp.get()));
114148675466SDimitry Andric auto RV = Arg.getKnownRValue();
114206d4ba38SDimitry Andric assert(RV.isScalar() &&
114306d4ba38SDimitry Andric "Unexpected non-scalar rvalue during struct expansion.");
114406d4ba38SDimitry Andric
114506d4ba38SDimitry Andric // Insert a bitcast as needed.
114606d4ba38SDimitry Andric llvm::Value *V = RV.getScalarVal();
114706d4ba38SDimitry Andric if (IRCallArgPos < IRFuncTy->getNumParams() &&
114806d4ba38SDimitry Andric V->getType() != IRFuncTy->getParamType(IRCallArgPos))
114906d4ba38SDimitry Andric V = Builder.CreateBitCast(V, IRFuncTy->getParamType(IRCallArgPos));
115006d4ba38SDimitry Andric
115106d4ba38SDimitry Andric IRCallArgs[IRCallArgPos++] = V;
115206d4ba38SDimitry Andric }
1153ec2b103cSEd Schouten }
1154ec2b103cSEd Schouten
115545b53394SDimitry Andric /// Create a temporary allocation for the purposes of coercion.
CreateTempAllocaForCoercion(CodeGenFunction & CGF,llvm::Type * Ty,CharUnits MinAlign,const Twine & Name="tmp")1156ac9a064cSDimitry Andric static RawAddress CreateTempAllocaForCoercion(CodeGenFunction &CGF,
1157ac9a064cSDimitry Andric llvm::Type *Ty,
1158b60736ecSDimitry Andric CharUnits MinAlign,
1159b60736ecSDimitry Andric const Twine &Name = "tmp") {
116045b53394SDimitry Andric // Don't use an alignment that's worse than what LLVM would prefer.
1161e3b55780SDimitry Andric auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlign(Ty);
116245b53394SDimitry Andric CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign));
116345b53394SDimitry Andric
1164b60736ecSDimitry Andric return CGF.CreateTempAlloca(Ty, Align, Name + ".coerce");
116545b53394SDimitry Andric }
116645b53394SDimitry Andric
11674ba67500SRoman Divacky /// EnterStructPointerForCoercedAccess - Given a struct pointer that we are
11684ba67500SRoman Divacky /// accessing some number of bytes out of it, try to gep into the struct to get
11694ba67500SRoman Divacky /// at its inner goodness. Dive as deep as possible without entering an element
11704ba67500SRoman Divacky /// with an in-memory size smaller than DstSize.
117145b53394SDimitry Andric static Address
EnterStructPointerForCoercedAccess(Address SrcPtr,llvm::StructType * SrcSTy,uint64_t DstSize,CodeGenFunction & CGF)117245b53394SDimitry Andric EnterStructPointerForCoercedAccess(Address SrcPtr,
117336981b17SDimitry Andric llvm::StructType *SrcSTy,
11744ba67500SRoman Divacky uint64_t DstSize, CodeGenFunction &CGF) {
11754ba67500SRoman Divacky // We can't dive into a zero-element struct.
11764ba67500SRoman Divacky if (SrcSTy->getNumElements() == 0) return SrcPtr;
11774ba67500SRoman Divacky
117836981b17SDimitry Andric llvm::Type *FirstElt = SrcSTy->getElementType(0);
11794ba67500SRoman Divacky
11804ba67500SRoman Divacky // If the first elt is at least as large as what we're looking for, or if the
118106d4ba38SDimitry Andric // first element is the same size as the whole struct, we can enter it. The
118206d4ba38SDimitry Andric // comparison must be made on the store size and not the alloca size. Using
118306d4ba38SDimitry Andric // the alloca size may overstate the size of the load.
11844ba67500SRoman Divacky uint64_t FirstEltSize =
118506d4ba38SDimitry Andric CGF.CGM.getDataLayout().getTypeStoreSize(FirstElt);
11864ba67500SRoman Divacky if (FirstEltSize < DstSize &&
118706d4ba38SDimitry Andric FirstEltSize < CGF.CGM.getDataLayout().getTypeStoreSize(SrcSTy))
11884ba67500SRoman Divacky return SrcPtr;
11894ba67500SRoman Divacky
11904ba67500SRoman Divacky // GEP into the first element.
119122989816SDimitry Andric SrcPtr = CGF.Builder.CreateStructGEP(SrcPtr, 0, "coerce.dive");
11924ba67500SRoman Divacky
11934ba67500SRoman Divacky // If the first element is a struct, recurse.
119445b53394SDimitry Andric llvm::Type *SrcTy = SrcPtr.getElementType();
119536981b17SDimitry Andric if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy))
11964ba67500SRoman Divacky return EnterStructPointerForCoercedAccess(SrcPtr, SrcSTy, DstSize, CGF);
11974ba67500SRoman Divacky
11984ba67500SRoman Divacky return SrcPtr;
11994ba67500SRoman Divacky }
12004ba67500SRoman Divacky
12014ba67500SRoman Divacky /// CoerceIntOrPtrToIntOrPtr - Convert a value Val to the specific Ty where both
12024ba67500SRoman Divacky /// are either integers or pointers. This does a truncation of the value if it
12034ba67500SRoman Divacky /// is too large or a zero extension if it is too small.
1204bfef3995SDimitry Andric ///
1205bfef3995SDimitry Andric /// This behaves as if the value were coerced through memory, so on big-endian
1206bfef3995SDimitry Andric /// targets the high bits are preserved in a truncation, while little-endian
1207bfef3995SDimitry Andric /// targets preserve the low bits.
CoerceIntOrPtrToIntOrPtr(llvm::Value * Val,llvm::Type * Ty,CodeGenFunction & CGF)12084ba67500SRoman Divacky static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
120936981b17SDimitry Andric llvm::Type *Ty,
12104ba67500SRoman Divacky CodeGenFunction &CGF) {
12114ba67500SRoman Divacky if (Val->getType() == Ty)
12124ba67500SRoman Divacky return Val;
12134ba67500SRoman Divacky
12144ba67500SRoman Divacky if (isa<llvm::PointerType>(Val->getType())) {
12154ba67500SRoman Divacky // If this is Pointer->Pointer avoid conversion to and from int.
12164ba67500SRoman Divacky if (isa<llvm::PointerType>(Ty))
12174ba67500SRoman Divacky return CGF.Builder.CreateBitCast(Val, Ty, "coerce.val");
12184ba67500SRoman Divacky
12194ba67500SRoman Divacky // Convert the pointer to an integer so we can play with its width.
12204ba67500SRoman Divacky Val = CGF.Builder.CreatePtrToInt(Val, CGF.IntPtrTy, "coerce.val.pi");
12214ba67500SRoman Divacky }
12224ba67500SRoman Divacky
122336981b17SDimitry Andric llvm::Type *DestIntTy = Ty;
12244ba67500SRoman Divacky if (isa<llvm::PointerType>(DestIntTy))
12254ba67500SRoman Divacky DestIntTy = CGF.IntPtrTy;
12264ba67500SRoman Divacky
1227bfef3995SDimitry Andric if (Val->getType() != DestIntTy) {
1228bfef3995SDimitry Andric const llvm::DataLayout &DL = CGF.CGM.getDataLayout();
1229bfef3995SDimitry Andric if (DL.isBigEndian()) {
1230bfef3995SDimitry Andric // Preserve the high bits on big-endian targets.
1231bfef3995SDimitry Andric // That is what memory coercion does.
12329f4dbff6SDimitry Andric uint64_t SrcSize = DL.getTypeSizeInBits(Val->getType());
12339f4dbff6SDimitry Andric uint64_t DstSize = DL.getTypeSizeInBits(DestIntTy);
12349f4dbff6SDimitry Andric
1235bfef3995SDimitry Andric if (SrcSize > DstSize) {
1236bfef3995SDimitry Andric Val = CGF.Builder.CreateLShr(Val, SrcSize - DstSize, "coerce.highbits");
1237bfef3995SDimitry Andric Val = CGF.Builder.CreateTrunc(Val, DestIntTy, "coerce.val.ii");
1238bfef3995SDimitry Andric } else {
1239bfef3995SDimitry Andric Val = CGF.Builder.CreateZExt(Val, DestIntTy, "coerce.val.ii");
1240bfef3995SDimitry Andric Val = CGF.Builder.CreateShl(Val, DstSize - SrcSize, "coerce.highbits");
1241bfef3995SDimitry Andric }
1242bfef3995SDimitry Andric } else {
1243bfef3995SDimitry Andric // Little-endian targets preserve the low bits. No shifts required.
12444ba67500SRoman Divacky Val = CGF.Builder.CreateIntCast(Val, DestIntTy, false, "coerce.val.ii");
1245bfef3995SDimitry Andric }
1246bfef3995SDimitry Andric }
12474ba67500SRoman Divacky
12484ba67500SRoman Divacky if (isa<llvm::PointerType>(Ty))
12494ba67500SRoman Divacky Val = CGF.Builder.CreateIntToPtr(Val, Ty, "coerce.val.ip");
12504ba67500SRoman Divacky return Val;
12514ba67500SRoman Divacky }
12524ba67500SRoman Divacky
12534ba67500SRoman Divacky
12544ba67500SRoman Divacky
1255ec2b103cSEd Schouten /// CreateCoercedLoad - Create a load from \arg SrcPtr interpreted as
125651ece4aaSDimitry Andric /// a pointer to an object of type \arg Ty, known to be aligned to
125751ece4aaSDimitry Andric /// \arg SrcAlign bytes.
1258ec2b103cSEd Schouten ///
1259ec2b103cSEd Schouten /// This safely handles the case when the src type is smaller than the
1260ec2b103cSEd Schouten /// destination type; in this situation the values of bits which not
1261ec2b103cSEd Schouten /// present in the src are undefined.
CreateCoercedLoad(Address Src,llvm::Type * Ty,CodeGenFunction & CGF)126245b53394SDimitry Andric static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
1263ec2b103cSEd Schouten CodeGenFunction &CGF) {
126445b53394SDimitry Andric llvm::Type *SrcTy = Src.getElementType();
12654ba67500SRoman Divacky
12664ba67500SRoman Divacky // If SrcTy and Ty are the same, just do a load.
12674ba67500SRoman Divacky if (SrcTy == Ty)
126845b53394SDimitry Andric return CGF.Builder.CreateLoad(Src);
12694ba67500SRoman Divacky
1270b60736ecSDimitry Andric llvm::TypeSize DstSize = CGF.CGM.getDataLayout().getTypeAllocSize(Ty);
1271ec2b103cSEd Schouten
127236981b17SDimitry Andric if (llvm::StructType *SrcSTy = dyn_cast<llvm::StructType>(SrcTy)) {
1273b60736ecSDimitry Andric Src = EnterStructPointerForCoercedAccess(Src, SrcSTy,
1274e3b55780SDimitry Andric DstSize.getFixedValue(), CGF);
1275cfca06d7SDimitry Andric SrcTy = Src.getElementType();
12764ba67500SRoman Divacky }
12774ba67500SRoman Divacky
1278b60736ecSDimitry Andric llvm::TypeSize SrcSize = CGF.CGM.getDataLayout().getTypeAllocSize(SrcTy);
12794ba67500SRoman Divacky
12804ba67500SRoman Divacky // If the source and destination are integer or pointer types, just do an
12814ba67500SRoman Divacky // extension or truncation to the desired type.
12824ba67500SRoman Divacky if ((isa<llvm::IntegerType>(Ty) || isa<llvm::PointerType>(Ty)) &&
12834ba67500SRoman Divacky (isa<llvm::IntegerType>(SrcTy) || isa<llvm::PointerType>(SrcTy))) {
128445b53394SDimitry Andric llvm::Value *Load = CGF.Builder.CreateLoad(Src);
12854ba67500SRoman Divacky return CoerceIntOrPtrToIntOrPtr(Load, Ty, CGF);
12864ba67500SRoman Divacky }
12874ba67500SRoman Divacky
1288ec2b103cSEd Schouten // If load is legal, just bitcast the src pointer.
1289b60736ecSDimitry Andric if (!SrcSize.isScalable() && !DstSize.isScalable() &&
1290e3b55780SDimitry Andric SrcSize.getFixedValue() >= DstSize.getFixedValue()) {
1291ec2b103cSEd Schouten // Generally SrcSize is never greater than DstSize, since this means we are
1292ec2b103cSEd Schouten // losing bits. However, this can happen in cases where the structure has
1293ec2b103cSEd Schouten // additional padding, for example due to a user specified alignment.
1294ec2b103cSEd Schouten //
1295ec2b103cSEd Schouten // FIXME: Assert that we aren't truncating non-padding bits when have access
1296ec2b103cSEd Schouten // to that information.
12977fa27ce4SDimitry Andric Src = Src.withElementType(Ty);
129845b53394SDimitry Andric return CGF.Builder.CreateLoad(Src);
12994ba67500SRoman Divacky }
13004ba67500SRoman Divacky
1301b60736ecSDimitry Andric // If coercing a fixed vector to a scalable vector for ABI compatibility, and
1302145449b1SDimitry Andric // the types match, use the llvm.vector.insert intrinsic to perform the
1303145449b1SDimitry Andric // conversion.
1304ac9a064cSDimitry Andric if (auto *ScalableDstTy = dyn_cast<llvm::ScalableVectorType>(Ty)) {
1305ac9a064cSDimitry Andric if (auto *FixedSrcTy = dyn_cast<llvm::FixedVectorType>(SrcTy)) {
1306ac9a064cSDimitry Andric // If we are casting a fixed i8 vector to a scalable i1 predicate
1307c0981da4SDimitry Andric // vector, use a vector insert and bitcast the result.
1308ac9a064cSDimitry Andric if (ScalableDstTy->getElementType()->isIntegerTy(1) &&
1309ac9a064cSDimitry Andric ScalableDstTy->getElementCount().isKnownMultipleOf(8) &&
1310ac9a064cSDimitry Andric FixedSrcTy->getElementType()->isIntegerTy(8)) {
1311ac9a064cSDimitry Andric ScalableDstTy = llvm::ScalableVectorType::get(
1312ac9a064cSDimitry Andric FixedSrcTy->getElementType(),
1313ac9a064cSDimitry Andric ScalableDstTy->getElementCount().getKnownMinValue() / 8);
1314c0981da4SDimitry Andric }
1315ac9a064cSDimitry Andric if (ScalableDstTy->getElementType() == FixedSrcTy->getElementType()) {
1316b60736ecSDimitry Andric auto *Load = CGF.Builder.CreateLoad(Src);
1317ac9a064cSDimitry Andric auto *UndefVec = llvm::UndefValue::get(ScalableDstTy);
1318b60736ecSDimitry Andric auto *Zero = llvm::Constant::getNullValue(CGF.CGM.Int64Ty);
1319c0981da4SDimitry Andric llvm::Value *Result = CGF.Builder.CreateInsertVector(
1320ac9a064cSDimitry Andric ScalableDstTy, UndefVec, Load, Zero, "cast.scalable");
1321ac9a064cSDimitry Andric if (ScalableDstTy != Ty)
1322ac9a064cSDimitry Andric Result = CGF.Builder.CreateBitCast(Result, Ty);
1323c0981da4SDimitry Andric return Result;
1324b60736ecSDimitry Andric }
1325b60736ecSDimitry Andric }
1326b60736ecSDimitry Andric }
1327b60736ecSDimitry Andric
132845b53394SDimitry Andric // Otherwise do coercion through memory. This is stupid, but simple.
1329ac9a064cSDimitry Andric RawAddress Tmp =
1330b60736ecSDimitry Andric CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName());
1331b60736ecSDimitry Andric CGF.Builder.CreateMemCpy(
1332ac9a064cSDimitry Andric Tmp.getPointer(), Tmp.getAlignment().getAsAlign(),
1333ac9a064cSDimitry Andric Src.emitRawPointer(CGF), Src.getAlignment().getAsAlign(),
1334e3b55780SDimitry Andric llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinValue()));
133545b53394SDimitry Andric return CGF.Builder.CreateLoad(Tmp);
1336ec2b103cSEd Schouten }
1337ec2b103cSEd Schouten
CreateCoercedStore(llvm::Value * Src,Address Dst,llvm::TypeSize DstSize,bool DstIsVolatile)13381de139fdSDimitry Andric void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
13391de139fdSDimitry Andric llvm::TypeSize DstSize,
13401de139fdSDimitry Andric bool DstIsVolatile) {
13411de139fdSDimitry Andric if (!DstSize)
13421de139fdSDimitry Andric return;
13431de139fdSDimitry Andric
13441de139fdSDimitry Andric llvm::Type *SrcTy = Src->getType();
13451de139fdSDimitry Andric llvm::TypeSize SrcSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
13461de139fdSDimitry Andric
13471de139fdSDimitry Andric // GEP into structs to try to make types match.
13481de139fdSDimitry Andric // FIXME: This isn't really that useful with opaque types, but it impacts a
13491de139fdSDimitry Andric // lot of regression tests.
13501de139fdSDimitry Andric if (SrcTy != Dst.getElementType()) {
13511de139fdSDimitry Andric if (llvm::StructType *DstSTy =
13521de139fdSDimitry Andric dyn_cast<llvm::StructType>(Dst.getElementType())) {
13531de139fdSDimitry Andric assert(!SrcSize.isScalable());
13541de139fdSDimitry Andric Dst = EnterStructPointerForCoercedAccess(Dst, DstSTy,
13551de139fdSDimitry Andric SrcSize.getFixedValue(), *this);
13561de139fdSDimitry Andric }
13571de139fdSDimitry Andric }
13581de139fdSDimitry Andric
13591de139fdSDimitry Andric if (SrcSize.isScalable() || SrcSize <= DstSize) {
13601de139fdSDimitry Andric if (SrcTy->isIntegerTy() && Dst.getElementType()->isPointerTy() &&
13611de139fdSDimitry Andric SrcSize == CGM.getDataLayout().getTypeAllocSize(Dst.getElementType())) {
13621de139fdSDimitry Andric // If the value is supposed to be a pointer, convert it before storing it.
13631de139fdSDimitry Andric Src = CoerceIntOrPtrToIntOrPtr(Src, Dst.getElementType(), *this);
13641de139fdSDimitry Andric Builder.CreateStore(Src, Dst, DstIsVolatile);
13651de139fdSDimitry Andric } else if (llvm::StructType *STy =
13661de139fdSDimitry Andric dyn_cast<llvm::StructType>(Src->getType())) {
136729cafa66SDimitry Andric // Prefer scalar stores to first-class aggregate stores.
13681de139fdSDimitry Andric Dst = Dst.withElementType(SrcTy);
136929cafa66SDimitry Andric for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
13701de139fdSDimitry Andric Address EltPtr = Builder.CreateStructGEP(Dst, i);
13711de139fdSDimitry Andric llvm::Value *Elt = Builder.CreateExtractValue(Src, i);
13721de139fdSDimitry Andric Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
137329cafa66SDimitry Andric }
137429cafa66SDimitry Andric } else {
13751de139fdSDimitry Andric Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile);
137629cafa66SDimitry Andric }
13771de139fdSDimitry Andric } else if (SrcTy->isIntegerTy()) {
13781de139fdSDimitry Andric // If the source is a simple integer, coerce it directly.
13791de139fdSDimitry Andric llvm::Type *DstIntTy = Builder.getIntNTy(DstSize.getFixedValue() * 8);
13801de139fdSDimitry Andric Src = CoerceIntOrPtrToIntOrPtr(Src, DstIntTy, *this);
13811de139fdSDimitry Andric Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile);
1382ec2b103cSEd Schouten } else {
1383ec2b103cSEd Schouten // Otherwise do coercion through memory. This is stupid, but
1384ec2b103cSEd Schouten // simple.
138537f6c480SEd Schouten
138637f6c480SEd Schouten // Generally SrcSize is never greater than DstSize, since this means we are
138737f6c480SEd Schouten // losing bits. However, this can happen in cases where the structure has
138837f6c480SEd Schouten // additional padding, for example due to a user specified alignment.
138937f6c480SEd Schouten //
139037f6c480SEd Schouten // FIXME: Assert that we aren't truncating non-padding bits when have access
139137f6c480SEd Schouten // to that information.
1392ac9a064cSDimitry Andric RawAddress Tmp =
13931de139fdSDimitry Andric CreateTempAllocaForCoercion(*this, SrcTy, Dst.getAlignment());
13941de139fdSDimitry Andric Builder.CreateStore(Src, Tmp);
13951de139fdSDimitry Andric Builder.CreateMemCpy(Dst.emitRawPointer(*this),
13961de139fdSDimitry Andric Dst.getAlignment().getAsAlign(), Tmp.getPointer(),
13971de139fdSDimitry Andric Tmp.getAlignment().getAsAlign(),
13981de139fdSDimitry Andric Builder.CreateTypeSize(IntPtrTy, DstSize));
1399ec2b103cSEd Schouten }
1400ec2b103cSEd Schouten }
1401ec2b103cSEd Schouten
emitAddressAtOffset(CodeGenFunction & CGF,Address addr,const ABIArgInfo & info)140245b53394SDimitry Andric static Address emitAddressAtOffset(CodeGenFunction &CGF, Address addr,
140345b53394SDimitry Andric const ABIArgInfo &info) {
140445b53394SDimitry Andric if (unsigned offset = info.getDirectOffset()) {
14057fa27ce4SDimitry Andric addr = addr.withElementType(CGF.Int8Ty);
140645b53394SDimitry Andric addr = CGF.Builder.CreateConstInBoundsByteGEP(addr,
140745b53394SDimitry Andric CharUnits::fromQuantity(offset));
14087fa27ce4SDimitry Andric addr = addr.withElementType(info.getCoerceToType());
140945b53394SDimitry Andric }
141045b53394SDimitry Andric return addr;
141145b53394SDimitry Andric }
141245b53394SDimitry Andric
141306d4ba38SDimitry Andric namespace {
141406d4ba38SDimitry Andric
141506d4ba38SDimitry Andric /// Encapsulates information about the way function arguments from
141606d4ba38SDimitry Andric /// CGFunctionInfo should be passed to actual LLVM IR function.
141706d4ba38SDimitry Andric class ClangToLLVMArgMapping {
141806d4ba38SDimitry Andric static const unsigned InvalidIndex = ~0U;
141906d4ba38SDimitry Andric unsigned InallocaArgNo;
142006d4ba38SDimitry Andric unsigned SRetArgNo;
142106d4ba38SDimitry Andric unsigned TotalIRArgs;
142206d4ba38SDimitry Andric
142306d4ba38SDimitry Andric /// Arguments of LLVM IR function corresponding to single Clang argument.
142406d4ba38SDimitry Andric struct IRArgs {
142506d4ba38SDimitry Andric unsigned PaddingArgIndex;
142606d4ba38SDimitry Andric // Argument is expanded to IR arguments at positions
142706d4ba38SDimitry Andric // [FirstArgIndex, FirstArgIndex + NumberOfArgs).
142806d4ba38SDimitry Andric unsigned FirstArgIndex;
142906d4ba38SDimitry Andric unsigned NumberOfArgs;
143006d4ba38SDimitry Andric
IRArgs__anon748148590511::ClangToLLVMArgMapping::IRArgs143106d4ba38SDimitry Andric IRArgs()
143206d4ba38SDimitry Andric : PaddingArgIndex(InvalidIndex), FirstArgIndex(InvalidIndex),
143306d4ba38SDimitry Andric NumberOfArgs(0) {}
143406d4ba38SDimitry Andric };
143506d4ba38SDimitry Andric
143606d4ba38SDimitry Andric SmallVector<IRArgs, 8> ArgInfo;
143706d4ba38SDimitry Andric
143806d4ba38SDimitry Andric public:
ClangToLLVMArgMapping(const ASTContext & Context,const CGFunctionInfo & FI,bool OnlyRequiredArgs=false)143906d4ba38SDimitry Andric ClangToLLVMArgMapping(const ASTContext &Context, const CGFunctionInfo &FI,
144006d4ba38SDimitry Andric bool OnlyRequiredArgs = false)
144106d4ba38SDimitry Andric : InallocaArgNo(InvalidIndex), SRetArgNo(InvalidIndex), TotalIRArgs(0),
144206d4ba38SDimitry Andric ArgInfo(OnlyRequiredArgs ? FI.getNumRequiredArgs() : FI.arg_size()) {
144306d4ba38SDimitry Andric construct(Context, FI, OnlyRequiredArgs);
144406d4ba38SDimitry Andric }
144506d4ba38SDimitry Andric
hasInallocaArg() const144606d4ba38SDimitry Andric bool hasInallocaArg() const { return InallocaArgNo != InvalidIndex; }
getInallocaArgNo() const144706d4ba38SDimitry Andric unsigned getInallocaArgNo() const {
144806d4ba38SDimitry Andric assert(hasInallocaArg());
144906d4ba38SDimitry Andric return InallocaArgNo;
145006d4ba38SDimitry Andric }
145106d4ba38SDimitry Andric
hasSRetArg() const145206d4ba38SDimitry Andric bool hasSRetArg() const { return SRetArgNo != InvalidIndex; }
getSRetArgNo() const145306d4ba38SDimitry Andric unsigned getSRetArgNo() const {
145406d4ba38SDimitry Andric assert(hasSRetArg());
145506d4ba38SDimitry Andric return SRetArgNo;
145606d4ba38SDimitry Andric }
145706d4ba38SDimitry Andric
totalIRArgs() const145806d4ba38SDimitry Andric unsigned totalIRArgs() const { return TotalIRArgs; }
145906d4ba38SDimitry Andric
hasPaddingArg(unsigned ArgNo) const146006d4ba38SDimitry Andric bool hasPaddingArg(unsigned ArgNo) const {
146106d4ba38SDimitry Andric assert(ArgNo < ArgInfo.size());
146206d4ba38SDimitry Andric return ArgInfo[ArgNo].PaddingArgIndex != InvalidIndex;
146306d4ba38SDimitry Andric }
getPaddingArgNo(unsigned ArgNo) const146406d4ba38SDimitry Andric unsigned getPaddingArgNo(unsigned ArgNo) const {
146506d4ba38SDimitry Andric assert(hasPaddingArg(ArgNo));
146606d4ba38SDimitry Andric return ArgInfo[ArgNo].PaddingArgIndex;
146706d4ba38SDimitry Andric }
146806d4ba38SDimitry Andric
146906d4ba38SDimitry Andric /// Returns index of first IR argument corresponding to ArgNo, and their
147006d4ba38SDimitry Andric /// quantity.
getIRArgs(unsigned ArgNo) const147106d4ba38SDimitry Andric std::pair<unsigned, unsigned> getIRArgs(unsigned ArgNo) const {
147206d4ba38SDimitry Andric assert(ArgNo < ArgInfo.size());
147306d4ba38SDimitry Andric return std::make_pair(ArgInfo[ArgNo].FirstArgIndex,
147406d4ba38SDimitry Andric ArgInfo[ArgNo].NumberOfArgs);
147506d4ba38SDimitry Andric }
147606d4ba38SDimitry Andric
147706d4ba38SDimitry Andric private:
147806d4ba38SDimitry Andric void construct(const ASTContext &Context, const CGFunctionInfo &FI,
147906d4ba38SDimitry Andric bool OnlyRequiredArgs);
148006d4ba38SDimitry Andric };
148106d4ba38SDimitry Andric
construct(const ASTContext & Context,const CGFunctionInfo & FI,bool OnlyRequiredArgs)148206d4ba38SDimitry Andric void ClangToLLVMArgMapping::construct(const ASTContext &Context,
148306d4ba38SDimitry Andric const CGFunctionInfo &FI,
148406d4ba38SDimitry Andric bool OnlyRequiredArgs) {
148506d4ba38SDimitry Andric unsigned IRArgNo = 0;
148606d4ba38SDimitry Andric bool SwapThisWithSRet = false;
148706d4ba38SDimitry Andric const ABIArgInfo &RetAI = FI.getReturnInfo();
148806d4ba38SDimitry Andric
148906d4ba38SDimitry Andric if (RetAI.getKind() == ABIArgInfo::Indirect) {
149006d4ba38SDimitry Andric SwapThisWithSRet = RetAI.isSRetAfterThis();
149106d4ba38SDimitry Andric SRetArgNo = SwapThisWithSRet ? 1 : IRArgNo++;
149206d4ba38SDimitry Andric }
149306d4ba38SDimitry Andric
149406d4ba38SDimitry Andric unsigned ArgNo = 0;
149506d4ba38SDimitry Andric unsigned NumArgs = OnlyRequiredArgs ? FI.getNumRequiredArgs() : FI.arg_size();
149606d4ba38SDimitry Andric for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(); ArgNo < NumArgs;
149706d4ba38SDimitry Andric ++I, ++ArgNo) {
149806d4ba38SDimitry Andric assert(I != FI.arg_end());
149906d4ba38SDimitry Andric QualType ArgType = I->type;
150006d4ba38SDimitry Andric const ABIArgInfo &AI = I->info;
150106d4ba38SDimitry Andric // Collect data about IR arguments corresponding to Clang argument ArgNo.
150206d4ba38SDimitry Andric auto &IRArgs = ArgInfo[ArgNo];
150306d4ba38SDimitry Andric
150406d4ba38SDimitry Andric if (AI.getPaddingType())
150506d4ba38SDimitry Andric IRArgs.PaddingArgIndex = IRArgNo++;
150606d4ba38SDimitry Andric
150706d4ba38SDimitry Andric switch (AI.getKind()) {
150806d4ba38SDimitry Andric case ABIArgInfo::Extend:
150906d4ba38SDimitry Andric case ABIArgInfo::Direct: {
151006d4ba38SDimitry Andric // FIXME: handle sseregparm someday...
151106d4ba38SDimitry Andric llvm::StructType *STy = dyn_cast<llvm::StructType>(AI.getCoerceToType());
151206d4ba38SDimitry Andric if (AI.isDirect() && AI.getCanBeFlattened() && STy) {
151306d4ba38SDimitry Andric IRArgs.NumberOfArgs = STy->getNumElements();
151406d4ba38SDimitry Andric } else {
151506d4ba38SDimitry Andric IRArgs.NumberOfArgs = 1;
151606d4ba38SDimitry Andric }
151706d4ba38SDimitry Andric break;
151806d4ba38SDimitry Andric }
151906d4ba38SDimitry Andric case ABIArgInfo::Indirect:
1520b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased:
152106d4ba38SDimitry Andric IRArgs.NumberOfArgs = 1;
152206d4ba38SDimitry Andric break;
152306d4ba38SDimitry Andric case ABIArgInfo::Ignore:
152406d4ba38SDimitry Andric case ABIArgInfo::InAlloca:
152506d4ba38SDimitry Andric // ignore and inalloca doesn't have matching LLVM parameters.
152606d4ba38SDimitry Andric IRArgs.NumberOfArgs = 0;
152706d4ba38SDimitry Andric break;
15282b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand:
15292b6b257fSDimitry Andric IRArgs.NumberOfArgs = AI.getCoerceAndExpandTypeSequence().size();
15302b6b257fSDimitry Andric break;
15312b6b257fSDimitry Andric case ABIArgInfo::Expand:
153206d4ba38SDimitry Andric IRArgs.NumberOfArgs = getExpansionSize(ArgType, Context);
153306d4ba38SDimitry Andric break;
153406d4ba38SDimitry Andric }
153506d4ba38SDimitry Andric
153606d4ba38SDimitry Andric if (IRArgs.NumberOfArgs > 0) {
153706d4ba38SDimitry Andric IRArgs.FirstArgIndex = IRArgNo;
153806d4ba38SDimitry Andric IRArgNo += IRArgs.NumberOfArgs;
153906d4ba38SDimitry Andric }
154006d4ba38SDimitry Andric
154106d4ba38SDimitry Andric // Skip over the sret parameter when it comes second. We already handled it
154206d4ba38SDimitry Andric // above.
154306d4ba38SDimitry Andric if (IRArgNo == 1 && SwapThisWithSRet)
154406d4ba38SDimitry Andric IRArgNo++;
154506d4ba38SDimitry Andric }
154606d4ba38SDimitry Andric assert(ArgNo == ArgInfo.size());
154706d4ba38SDimitry Andric
154806d4ba38SDimitry Andric if (FI.usesInAlloca())
154906d4ba38SDimitry Andric InallocaArgNo = IRArgNo++;
155006d4ba38SDimitry Andric
155106d4ba38SDimitry Andric TotalIRArgs = IRArgNo;
155206d4ba38SDimitry Andric }
155306d4ba38SDimitry Andric } // namespace
155406d4ba38SDimitry Andric
1555ec2b103cSEd Schouten /***/
1556ec2b103cSEd Schouten
ReturnTypeUsesSRet(const CGFunctionInfo & FI)15574e58654bSRoman Divacky bool CodeGenModule::ReturnTypeUsesSRet(const CGFunctionInfo &FI) {
155848675466SDimitry Andric const auto &RI = FI.getReturnInfo();
155948675466SDimitry Andric return RI.isIndirect() || (RI.isInAlloca() && RI.getInAllocaSRet());
1560ec2b103cSEd Schouten }
1561ec2b103cSEd Schouten
ReturnTypeHasInReg(const CGFunctionInfo & FI)1562ac9a064cSDimitry Andric bool CodeGenModule::ReturnTypeHasInReg(const CGFunctionInfo &FI) {
1563ac9a064cSDimitry Andric const auto &RI = FI.getReturnInfo();
1564ac9a064cSDimitry Andric return RI.getInReg();
1565ac9a064cSDimitry Andric }
1566ac9a064cSDimitry Andric
ReturnSlotInterferesWithArgs(const CGFunctionInfo & FI)15679f4dbff6SDimitry Andric bool CodeGenModule::ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI) {
15689f4dbff6SDimitry Andric return ReturnTypeUsesSRet(FI) &&
15699f4dbff6SDimitry Andric getTargetCodeGenInfo().doesReturnSlotInterfereWithArgs();
15709f4dbff6SDimitry Andric }
15719f4dbff6SDimitry Andric
ReturnTypeUsesFPRet(QualType ResultType)15724e58654bSRoman Divacky bool CodeGenModule::ReturnTypeUsesFPRet(QualType ResultType) {
15734e58654bSRoman Divacky if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) {
15744e58654bSRoman Divacky switch (BT->getKind()) {
15754e58654bSRoman Divacky default:
15764e58654bSRoman Divacky return false;
15774e58654bSRoman Divacky case BuiltinType::Float:
1578c0981da4SDimitry Andric return getTarget().useObjCFPRetForRealType(FloatModeKind::Float);
15794e58654bSRoman Divacky case BuiltinType::Double:
1580c0981da4SDimitry Andric return getTarget().useObjCFPRetForRealType(FloatModeKind::Double);
15814e58654bSRoman Divacky case BuiltinType::LongDouble:
1582c0981da4SDimitry Andric return getTarget().useObjCFPRetForRealType(FloatModeKind::LongDouble);
15834e58654bSRoman Divacky }
15844e58654bSRoman Divacky }
15854e58654bSRoman Divacky
15864e58654bSRoman Divacky return false;
15874e58654bSRoman Divacky }
15884e58654bSRoman Divacky
ReturnTypeUsesFP2Ret(QualType ResultType)1589dbe13110SDimitry Andric bool CodeGenModule::ReturnTypeUsesFP2Ret(QualType ResultType) {
1590dbe13110SDimitry Andric if (const ComplexType *CT = ResultType->getAs<ComplexType>()) {
1591dbe13110SDimitry Andric if (const BuiltinType *BT = CT->getElementType()->getAs<BuiltinType>()) {
1592dbe13110SDimitry Andric if (BT->getKind() == BuiltinType::LongDouble)
15936a037251SDimitry Andric return getTarget().useObjCFP2RetForComplexLongDouble();
1594dbe13110SDimitry Andric }
1595dbe13110SDimitry Andric }
1596dbe13110SDimitry Andric
1597dbe13110SDimitry Andric return false;
1598dbe13110SDimitry Andric }
1599dbe13110SDimitry Andric
GetFunctionType(GlobalDecl GD)1600180abc3dSDimitry Andric llvm::FunctionType *CodeGenTypes::GetFunctionType(GlobalDecl GD) {
1601dbe13110SDimitry Andric const CGFunctionInfo &FI = arrangeGlobalDeclaration(GD);
1602dbe13110SDimitry Andric return GetFunctionType(FI);
160379ade4e0SRoman Divacky }
160479ade4e0SRoman Divacky
1605180abc3dSDimitry Andric llvm::FunctionType *
GetFunctionType(const CGFunctionInfo & FI)1606dbe13110SDimitry Andric CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
1607180abc3dSDimitry Andric
160806d4ba38SDimitry Andric bool Inserted = FunctionsBeingProcessed.insert(&FI).second;
160906d4ba38SDimitry Andric (void)Inserted;
1610180abc3dSDimitry Andric assert(Inserted && "Recursively being processed?");
1611180abc3dSDimitry Andric
16129f4dbff6SDimitry Andric llvm::Type *resultType = nullptr;
161329cafa66SDimitry Andric const ABIArgInfo &retAI = FI.getReturnInfo();
161429cafa66SDimitry Andric switch (retAI.getKind()) {
1615ec2b103cSEd Schouten case ABIArgInfo::Expand:
1616b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased:
161729cafa66SDimitry Andric llvm_unreachable("Invalid ABI kind for return argument");
1618ec2b103cSEd Schouten
161970b4596dSEd Schouten case ABIArgInfo::Extend:
1620ec2b103cSEd Schouten case ABIArgInfo::Direct:
162129cafa66SDimitry Andric resultType = retAI.getCoerceToType();
1622ec2b103cSEd Schouten break;
1623ec2b103cSEd Schouten
16249f4dbff6SDimitry Andric case ABIArgInfo::InAlloca:
16259f4dbff6SDimitry Andric if (retAI.getInAllocaSRet()) {
16269f4dbff6SDimitry Andric // sret things on win32 aren't void, they return the sret pointer.
16279f4dbff6SDimitry Andric QualType ret = FI.getReturnType();
1628e3b55780SDimitry Andric unsigned addressSpace = CGM.getTypes().getTargetAddressSpace(ret);
16297fa27ce4SDimitry Andric resultType = llvm::PointerType::get(getLLVMContext(), addressSpace);
16309f4dbff6SDimitry Andric } else {
16319f4dbff6SDimitry Andric resultType = llvm::Type::getVoidTy(getLLVMContext());
16329f4dbff6SDimitry Andric }
16339f4dbff6SDimitry Andric break;
16349f4dbff6SDimitry Andric
16357e86edd6SDimitry Andric case ABIArgInfo::Indirect:
1636ec2b103cSEd Schouten case ABIArgInfo::Ignore:
163729cafa66SDimitry Andric resultType = llvm::Type::getVoidTy(getLLVMContext());
1638ec2b103cSEd Schouten break;
16392b6b257fSDimitry Andric
16402b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand:
16412b6b257fSDimitry Andric resultType = retAI.getUnpaddedCoerceAndExpandType();
16422b6b257fSDimitry Andric break;
1643ec2b103cSEd Schouten }
1644ec2b103cSEd Schouten
164506d4ba38SDimitry Andric ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI, true);
164606d4ba38SDimitry Andric SmallVector<llvm::Type*, 8> ArgTypes(IRFunctionArgs.totalIRArgs());
164706d4ba38SDimitry Andric
164806d4ba38SDimitry Andric // Add type for sret argument.
164906d4ba38SDimitry Andric if (IRFunctionArgs.hasSRetArg()) {
165006d4ba38SDimitry Andric QualType Ret = FI.getReturnType();
1651e3b55780SDimitry Andric unsigned AddressSpace = CGM.getTypes().getTargetAddressSpace(Ret);
165206d4ba38SDimitry Andric ArgTypes[IRFunctionArgs.getSRetArgNo()] =
16537fa27ce4SDimitry Andric llvm::PointerType::get(getLLVMContext(), AddressSpace);
1654809500fcSDimitry Andric }
165506d4ba38SDimitry Andric
165606d4ba38SDimitry Andric // Add type for inalloca argument.
16577fa27ce4SDimitry Andric if (IRFunctionArgs.hasInallocaArg())
16587fa27ce4SDimitry Andric ArgTypes[IRFunctionArgs.getInallocaArgNo()] =
16597fa27ce4SDimitry Andric llvm::PointerType::getUnqual(getLLVMContext());
166006d4ba38SDimitry Andric
166106d4ba38SDimitry Andric // Add in all of the required arguments.
166206d4ba38SDimitry Andric unsigned ArgNo = 0;
166306d4ba38SDimitry Andric CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
166406d4ba38SDimitry Andric ie = it + FI.getNumRequiredArgs();
166506d4ba38SDimitry Andric for (; it != ie; ++it, ++ArgNo) {
166606d4ba38SDimitry Andric const ABIArgInfo &ArgInfo = it->info;
1667ec2b103cSEd Schouten
166813cc256eSDimitry Andric // Insert a padding type to ensure proper alignment.
166906d4ba38SDimitry Andric if (IRFunctionArgs.hasPaddingArg(ArgNo))
167006d4ba38SDimitry Andric ArgTypes[IRFunctionArgs.getPaddingArgNo(ArgNo)] =
167106d4ba38SDimitry Andric ArgInfo.getPaddingType();
167213cc256eSDimitry Andric
167306d4ba38SDimitry Andric unsigned FirstIRArg, NumIRArgs;
167406d4ba38SDimitry Andric std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
167506d4ba38SDimitry Andric
167606d4ba38SDimitry Andric switch (ArgInfo.getKind()) {
1677ec2b103cSEd Schouten case ABIArgInfo::Ignore:
16789f4dbff6SDimitry Andric case ABIArgInfo::InAlloca:
167906d4ba38SDimitry Andric assert(NumIRArgs == 0);
1680ec2b103cSEd Schouten break;
1681ec2b103cSEd Schouten
16827fa27ce4SDimitry Andric case ABIArgInfo::Indirect:
168306d4ba38SDimitry Andric assert(NumIRArgs == 1);
1684583e75ccSDimitry Andric // indirect arguments are always on the stack, which is alloca addr space.
16857fa27ce4SDimitry Andric ArgTypes[FirstIRArg] = llvm::PointerType::get(
16867fa27ce4SDimitry Andric getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace());
16873d1dcd9bSDimitry Andric break;
16887fa27ce4SDimitry Andric case ABIArgInfo::IndirectAliased:
1689b60736ecSDimitry Andric assert(NumIRArgs == 1);
16907fa27ce4SDimitry Andric ArgTypes[FirstIRArg] = llvm::PointerType::get(
16917fa27ce4SDimitry Andric getLLVMContext(), ArgInfo.getIndirectAddrSpace());
1692b60736ecSDimitry Andric break;
16933d1dcd9bSDimitry Andric case ABIArgInfo::Extend:
16943d1dcd9bSDimitry Andric case ABIArgInfo::Direct: {
169506d4ba38SDimitry Andric // Fast-isel and the optimizer generally like scalar values better than
169606d4ba38SDimitry Andric // FCAs, so we flatten them if this is safe to do for this argument.
169706d4ba38SDimitry Andric llvm::Type *argType = ArgInfo.getCoerceToType();
16989f4dbff6SDimitry Andric llvm::StructType *st = dyn_cast<llvm::StructType>(argType);
169906d4ba38SDimitry Andric if (st && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) {
170006d4ba38SDimitry Andric assert(NumIRArgs == st->getNumElements());
170129cafa66SDimitry Andric for (unsigned i = 0, e = st->getNumElements(); i != e; ++i)
170206d4ba38SDimitry Andric ArgTypes[FirstIRArg + i] = st->getElementType(i);
17034ba67500SRoman Divacky } else {
170406d4ba38SDimitry Andric assert(NumIRArgs == 1);
170506d4ba38SDimitry Andric ArgTypes[FirstIRArg] = argType;
17064ba67500SRoman Divacky }
1707ec2b103cSEd Schouten break;
17084ba67500SRoman Divacky }
1709ec2b103cSEd Schouten
17102b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand: {
17112b6b257fSDimitry Andric auto ArgTypesIter = ArgTypes.begin() + FirstIRArg;
1712e3b55780SDimitry Andric for (auto *EltTy : ArgInfo.getCoerceAndExpandTypeSequence()) {
17132b6b257fSDimitry Andric *ArgTypesIter++ = EltTy;
17142b6b257fSDimitry Andric }
17152b6b257fSDimitry Andric assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs);
17162b6b257fSDimitry Andric break;
17172b6b257fSDimitry Andric }
17182b6b257fSDimitry Andric
1719ec2b103cSEd Schouten case ABIArgInfo::Expand:
172006d4ba38SDimitry Andric auto ArgTypesIter = ArgTypes.begin() + FirstIRArg;
172106d4ba38SDimitry Andric getExpandedTypes(it->type, ArgTypesIter);
172206d4ba38SDimitry Andric assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs);
1723ec2b103cSEd Schouten break;
1724ec2b103cSEd Schouten }
1725ec2b103cSEd Schouten }
1726ec2b103cSEd Schouten
1727180abc3dSDimitry Andric bool Erased = FunctionsBeingProcessed.erase(&FI); (void)Erased;
1728180abc3dSDimitry Andric assert(Erased && "Not in set?");
1729180abc3dSDimitry Andric
173006d4ba38SDimitry Andric return llvm::FunctionType::get(resultType, ArgTypes, FI.isVariadic());
1731ec2b103cSEd Schouten }
1732ec2b103cSEd Schouten
GetFunctionTypeForVTable(GlobalDecl GD)173336981b17SDimitry Andric llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
17343d1dcd9bSDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
17357fa27ce4SDimitry Andric const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
17361569ce68SRoman Divacky
1737180abc3dSDimitry Andric if (!isFuncTypeConvertible(FPT))
1738180abc3dSDimitry Andric return llvm::StructType::get(getLLVMContext());
1739180abc3dSDimitry Andric
174022989816SDimitry Andric return GetFunctionType(GD);
17411569ce68SRoman Divacky }
17421569ce68SRoman Divacky
AddAttributesFromFunctionProtoType(ASTContext & Ctx,llvm::AttrBuilder & FuncAttrs,const FunctionProtoType * FPT)174345b53394SDimitry Andric static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
174445b53394SDimitry Andric llvm::AttrBuilder &FuncAttrs,
174545b53394SDimitry Andric const FunctionProtoType *FPT) {
174645b53394SDimitry Andric if (!FPT)
174745b53394SDimitry Andric return;
174845b53394SDimitry Andric
174945b53394SDimitry Andric if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
175048675466SDimitry Andric FPT->isNothrow())
175145b53394SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
1752b1c73532SDimitry Andric
17534df029ccSDimitry Andric unsigned SMEBits = FPT->getAArch64SMEAttributes();
17544df029ccSDimitry Andric if (SMEBits & FunctionType::SME_PStateSMEnabledMask)
1755b1c73532SDimitry Andric FuncAttrs.addAttribute("aarch64_pstate_sm_enabled");
17564df029ccSDimitry Andric if (SMEBits & FunctionType::SME_PStateSMCompatibleMask)
1757b1c73532SDimitry Andric FuncAttrs.addAttribute("aarch64_pstate_sm_compatible");
17584df029ccSDimitry Andric
17594df029ccSDimitry Andric // ZA
1760ac9a064cSDimitry Andric if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves)
1761ac9a064cSDimitry Andric FuncAttrs.addAttribute("aarch64_preserves_za");
1762ac9a064cSDimitry Andric if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In)
1763ac9a064cSDimitry Andric FuncAttrs.addAttribute("aarch64_in_za");
1764ac9a064cSDimitry Andric if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out)
1765ac9a064cSDimitry Andric FuncAttrs.addAttribute("aarch64_out_za");
1766ac9a064cSDimitry Andric if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut)
1767ac9a064cSDimitry Andric FuncAttrs.addAttribute("aarch64_inout_za");
176845b53394SDimitry Andric
17694df029ccSDimitry Andric // ZT0
17704df029ccSDimitry Andric if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Preserves)
17714df029ccSDimitry Andric FuncAttrs.addAttribute("aarch64_preserves_zt0");
17724df029ccSDimitry Andric if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_In)
17734df029ccSDimitry Andric FuncAttrs.addAttribute("aarch64_in_zt0");
17744df029ccSDimitry Andric if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_Out)
17754df029ccSDimitry Andric FuncAttrs.addAttribute("aarch64_out_zt0");
17764df029ccSDimitry Andric if (FunctionType::getArmZT0State(SMEBits) == FunctionType::ARM_InOut)
17774df029ccSDimitry Andric FuncAttrs.addAttribute("aarch64_inout_zt0");
17784df029ccSDimitry Andric }
17794df029ccSDimitry Andric
AddAttributesFromOMPAssumes(llvm::AttrBuilder & FuncAttrs,const Decl * Callee)1780ac9a064cSDimitry Andric static void AddAttributesFromOMPAssumes(llvm::AttrBuilder &FuncAttrs,
1781c0981da4SDimitry Andric const Decl *Callee) {
1782c0981da4SDimitry Andric if (!Callee)
1783c0981da4SDimitry Andric return;
1784c0981da4SDimitry Andric
1785c0981da4SDimitry Andric SmallVector<StringRef, 4> Attrs;
1786c0981da4SDimitry Andric
1787ac9a064cSDimitry Andric for (const OMPAssumeAttr *AA : Callee->specific_attrs<OMPAssumeAttr>())
1788c0981da4SDimitry Andric AA->getAssumption().split(Attrs, ",");
1789c0981da4SDimitry Andric
1790c0981da4SDimitry Andric if (!Attrs.empty())
1791c0981da4SDimitry Andric FuncAttrs.addAttribute(llvm::AssumptionAttrKey,
1792c0981da4SDimitry Andric llvm::join(Attrs.begin(), Attrs.end(), ","));
1793c0981da4SDimitry Andric }
1794c0981da4SDimitry Andric
MayDropFunctionReturn(const ASTContext & Context,QualType ReturnType) const1795344a3780SDimitry Andric bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context,
1796e3b55780SDimitry Andric QualType ReturnType) const {
1797344a3780SDimitry Andric // We can't just discard the return value for a record type with a
1798344a3780SDimitry Andric // complex destructor or a non-trivially copyable type.
1799344a3780SDimitry Andric if (const RecordType *RT =
1800344a3780SDimitry Andric ReturnType.getCanonicalType()->getAs<RecordType>()) {
1801344a3780SDimitry Andric if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
1802344a3780SDimitry Andric return ClassDecl->hasTrivialDestructor();
1803344a3780SDimitry Andric }
1804344a3780SDimitry Andric return ReturnType.isTriviallyCopyableType(Context);
1805344a3780SDimitry Andric }
1806344a3780SDimitry Andric
HasStrictReturn(const CodeGenModule & Module,QualType RetTy,const Decl * TargetDecl)1807e3b55780SDimitry Andric static bool HasStrictReturn(const CodeGenModule &Module, QualType RetTy,
1808e3b55780SDimitry Andric const Decl *TargetDecl) {
1809e3b55780SDimitry Andric // As-is msan can not tolerate noundef mismatch between caller and
1810e3b55780SDimitry Andric // implementation. Mismatch is possible for e.g. indirect calls from C-caller
1811e3b55780SDimitry Andric // into C++. Such mismatches lead to confusing false reports. To avoid
1812e3b55780SDimitry Andric // expensive workaround on msan we enforce initialization event in uncommon
1813e3b55780SDimitry Andric // cases where it's allowed.
1814e3b55780SDimitry Andric if (Module.getLangOpts().Sanitize.has(SanitizerKind::Memory))
1815e3b55780SDimitry Andric return true;
1816e3b55780SDimitry Andric // C++ explicitly makes returning undefined values UB. C's rule only applies
1817e3b55780SDimitry Andric // to used values, so we never mark them noundef for now.
1818e3b55780SDimitry Andric if (!Module.getLangOpts().CPlusPlus)
1819e3b55780SDimitry Andric return false;
1820e3b55780SDimitry Andric if (TargetDecl) {
1821e3b55780SDimitry Andric if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(TargetDecl)) {
1822e3b55780SDimitry Andric if (FDecl->isExternC())
1823e3b55780SDimitry Andric return false;
1824e3b55780SDimitry Andric } else if (const VarDecl *VDecl = dyn_cast<VarDecl>(TargetDecl)) {
1825e3b55780SDimitry Andric // Function pointer.
1826e3b55780SDimitry Andric if (VDecl->isExternC())
1827e3b55780SDimitry Andric return false;
1828e3b55780SDimitry Andric }
1829e3b55780SDimitry Andric }
1830e3b55780SDimitry Andric
1831e3b55780SDimitry Andric // We don't want to be too aggressive with the return checking, unless
1832e3b55780SDimitry Andric // it's explicit in the code opts or we're using an appropriate sanitizer.
1833e3b55780SDimitry Andric // Try to respect what the programmer intended.
1834e3b55780SDimitry Andric return Module.getCodeGenOpts().StrictReturn ||
1835e3b55780SDimitry Andric !Module.MayDropFunctionReturn(Module.getContext(), RetTy) ||
1836e3b55780SDimitry Andric Module.getLangOpts().Sanitize.has(SanitizerKind::Return);
1837e3b55780SDimitry Andric }
1838e3b55780SDimitry Andric
18397fa27ce4SDimitry Andric /// Add denormal-fp-math and denormal-fp-math-f32 as appropriate for the
18407fa27ce4SDimitry Andric /// requested denormal behavior, accounting for the overriding behavior of the
18417fa27ce4SDimitry Andric /// -f32 case.
addDenormalModeAttrs(llvm::DenormalMode FPDenormalMode,llvm::DenormalMode FP32DenormalMode,llvm::AttrBuilder & FuncAttrs)18427fa27ce4SDimitry Andric static void addDenormalModeAttrs(llvm::DenormalMode FPDenormalMode,
18437fa27ce4SDimitry Andric llvm::DenormalMode FP32DenormalMode,
18447fa27ce4SDimitry Andric llvm::AttrBuilder &FuncAttrs) {
18457fa27ce4SDimitry Andric if (FPDenormalMode != llvm::DenormalMode::getDefault())
18467fa27ce4SDimitry Andric FuncAttrs.addAttribute("denormal-fp-math", FPDenormalMode.str());
18477fa27ce4SDimitry Andric
18487fa27ce4SDimitry Andric if (FP32DenormalMode != FPDenormalMode && FP32DenormalMode.isValid())
18497fa27ce4SDimitry Andric FuncAttrs.addAttribute("denormal-fp-math-f32", FP32DenormalMode.str());
18507fa27ce4SDimitry Andric }
18517fa27ce4SDimitry Andric
18527fa27ce4SDimitry Andric /// Add default attributes to a function, which have merge semantics under
18537fa27ce4SDimitry Andric /// -mlink-builtin-bitcode and should not simply overwrite any existing
18547fa27ce4SDimitry Andric /// attributes in the linked library.
18557fa27ce4SDimitry Andric static void
addMergableDefaultFunctionAttributes(const CodeGenOptions & CodeGenOpts,llvm::AttrBuilder & FuncAttrs)18567fa27ce4SDimitry Andric addMergableDefaultFunctionAttributes(const CodeGenOptions &CodeGenOpts,
18577fa27ce4SDimitry Andric llvm::AttrBuilder &FuncAttrs) {
18587fa27ce4SDimitry Andric addDenormalModeAttrs(CodeGenOpts.FPDenormalMode, CodeGenOpts.FP32DenormalMode,
18597fa27ce4SDimitry Andric FuncAttrs);
18607fa27ce4SDimitry Andric }
18617fa27ce4SDimitry Andric
getTrivialDefaultFunctionAttributes(StringRef Name,bool HasOptnone,const CodeGenOptions & CodeGenOpts,const LangOptions & LangOpts,bool AttrOnCallSite,llvm::AttrBuilder & FuncAttrs)18627fa27ce4SDimitry Andric static void getTrivialDefaultFunctionAttributes(
18637fa27ce4SDimitry Andric StringRef Name, bool HasOptnone, const CodeGenOptions &CodeGenOpts,
18647fa27ce4SDimitry Andric const LangOptions &LangOpts, bool AttrOnCallSite,
18657442d6faSDimitry Andric llvm::AttrBuilder &FuncAttrs) {
18667442d6faSDimitry Andric // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
18677442d6faSDimitry Andric if (!HasOptnone) {
18687442d6faSDimitry Andric if (CodeGenOpts.OptimizeSize)
18697442d6faSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize);
18707442d6faSDimitry Andric if (CodeGenOpts.OptimizeSize == 2)
18717442d6faSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::MinSize);
18727442d6faSDimitry Andric }
18737442d6faSDimitry Andric
18747442d6faSDimitry Andric if (CodeGenOpts.DisableRedZone)
18757442d6faSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoRedZone);
1876676fbe81SDimitry Andric if (CodeGenOpts.IndirectTlsSegRefs)
1877676fbe81SDimitry Andric FuncAttrs.addAttribute("indirect-tls-seg-refs");
18787442d6faSDimitry Andric if (CodeGenOpts.NoImplicitFloat)
18797442d6faSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat);
18807442d6faSDimitry Andric
18817442d6faSDimitry Andric if (AttrOnCallSite) {
18827442d6faSDimitry Andric // Attributes that should go on the call site only.
1883145449b1SDimitry Andric // FIXME: Look for 'BuiltinAttr' on the function rather than re-checking
1884145449b1SDimitry Andric // the -fno-builtin-foo list.
1885344a3780SDimitry Andric if (!CodeGenOpts.SimplifyLibCalls || LangOpts.isNoBuiltinFunc(Name))
18867442d6faSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
18877442d6faSDimitry Andric if (!CodeGenOpts.TrapFuncName.empty())
18887442d6faSDimitry Andric FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
18897442d6faSDimitry Andric } else {
1890519fc96cSDimitry Andric switch (CodeGenOpts.getFramePointer()) {
1891519fc96cSDimitry Andric case CodeGenOptions::FramePointerKind::None:
1892e3b55780SDimitry Andric // This is the default behavior.
1893519fc96cSDimitry Andric break;
1894ac9a064cSDimitry Andric case CodeGenOptions::FramePointerKind::Reserved:
1895519fc96cSDimitry Andric case CodeGenOptions::FramePointerKind::NonLeaf:
1896519fc96cSDimitry Andric case CodeGenOptions::FramePointerKind::All:
1897e3b55780SDimitry Andric FuncAttrs.addAttribute("frame-pointer",
1898e3b55780SDimitry Andric CodeGenOptions::getFramePointerKindName(
1899e3b55780SDimitry Andric CodeGenOpts.getFramePointer()));
19007442d6faSDimitry Andric }
19017442d6faSDimitry Andric
1902344a3780SDimitry Andric if (CodeGenOpts.LessPreciseFPMAD)
1903344a3780SDimitry Andric FuncAttrs.addAttribute("less-precise-fpmad", "true");
19047442d6faSDimitry Andric
190548675466SDimitry Andric if (CodeGenOpts.NullPointerIsValid)
1906cfca06d7SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NullPointerIsValid);
1907cfca06d7SDimitry Andric
1908145449b1SDimitry Andric if (LangOpts.getDefaultExceptionMode() == LangOptions::FPE_Ignore)
1909344a3780SDimitry Andric FuncAttrs.addAttribute("no-trapping-math", "true");
19107442d6faSDimitry Andric
19117442d6faSDimitry Andric // TODO: Are these all needed?
19127442d6faSDimitry Andric // unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
1913344a3780SDimitry Andric if (LangOpts.NoHonorInfs)
1914344a3780SDimitry Andric FuncAttrs.addAttribute("no-infs-fp-math", "true");
1915344a3780SDimitry Andric if (LangOpts.NoHonorNaNs)
1916344a3780SDimitry Andric FuncAttrs.addAttribute("no-nans-fp-math", "true");
1917c0981da4SDimitry Andric if (LangOpts.ApproxFunc)
1918c0981da4SDimitry Andric FuncAttrs.addAttribute("approx-func-fp-math", "true");
1919e3b55780SDimitry Andric if (LangOpts.AllowFPReassoc && LangOpts.AllowRecip &&
1920e3b55780SDimitry Andric LangOpts.NoSignedZero && LangOpts.ApproxFunc &&
1921e3b55780SDimitry Andric (LangOpts.getDefaultFPContractMode() ==
1922e3b55780SDimitry Andric LangOptions::FPModeKind::FPM_Fast ||
1923e3b55780SDimitry Andric LangOpts.getDefaultFPContractMode() ==
1924e3b55780SDimitry Andric LangOptions::FPModeKind::FPM_FastHonorPragmas))
1925344a3780SDimitry Andric FuncAttrs.addAttribute("unsafe-fp-math", "true");
1926344a3780SDimitry Andric if (CodeGenOpts.SoftFloat)
1927344a3780SDimitry Andric FuncAttrs.addAttribute("use-soft-float", "true");
19287442d6faSDimitry Andric FuncAttrs.addAttribute("stack-protector-buffer-size",
19297442d6faSDimitry Andric llvm::utostr(CodeGenOpts.SSPBufferSize));
1930344a3780SDimitry Andric if (LangOpts.NoSignedZero)
1931344a3780SDimitry Andric FuncAttrs.addAttribute("no-signed-zeros-fp-math", "true");
19327442d6faSDimitry Andric
19337442d6faSDimitry Andric // TODO: Reciprocal estimate codegen options should apply to instructions?
1934461a67faSDimitry Andric const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals;
19357442d6faSDimitry Andric if (!Recips.empty())
19367442d6faSDimitry Andric FuncAttrs.addAttribute("reciprocal-estimates",
1937461a67faSDimitry Andric llvm::join(Recips, ","));
1938461a67faSDimitry Andric
1939461a67faSDimitry Andric if (!CodeGenOpts.PreferVectorWidth.empty() &&
1940461a67faSDimitry Andric CodeGenOpts.PreferVectorWidth != "none")
1941461a67faSDimitry Andric FuncAttrs.addAttribute("prefer-vector-width",
1942461a67faSDimitry Andric CodeGenOpts.PreferVectorWidth);
19437442d6faSDimitry Andric
19447442d6faSDimitry Andric if (CodeGenOpts.StackRealignment)
19457442d6faSDimitry Andric FuncAttrs.addAttribute("stackrealign");
19467442d6faSDimitry Andric if (CodeGenOpts.Backchain)
19477442d6faSDimitry Andric FuncAttrs.addAttribute("backchain");
1948cfca06d7SDimitry Andric if (CodeGenOpts.EnableSegmentedStacks)
1949cfca06d7SDimitry Andric FuncAttrs.addAttribute("split-stack");
1950676fbe81SDimitry Andric
1951676fbe81SDimitry Andric if (CodeGenOpts.SpeculativeLoadHardening)
1952676fbe81SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening);
1953145449b1SDimitry Andric
1954145449b1SDimitry Andric // Add zero-call-used-regs attribute.
1955145449b1SDimitry Andric switch (CodeGenOpts.getZeroCallUsedRegs()) {
1956145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Skip:
1957145449b1SDimitry Andric FuncAttrs.removeAttribute("zero-call-used-regs");
1958145449b1SDimitry Andric break;
1959145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPRArg:
1960145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "used-gpr-arg");
1961145449b1SDimitry Andric break;
1962145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedGPR:
1963145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "used-gpr");
1964145449b1SDimitry Andric break;
1965145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::UsedArg:
1966145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "used-arg");
1967145449b1SDimitry Andric break;
1968145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::Used:
1969145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "used");
1970145449b1SDimitry Andric break;
1971145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPRArg:
1972145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "all-gpr-arg");
1973145449b1SDimitry Andric break;
1974145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllGPR:
1975145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "all-gpr");
1976145449b1SDimitry Andric break;
1977145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::AllArg:
1978145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "all-arg");
1979145449b1SDimitry Andric break;
1980145449b1SDimitry Andric case llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind::All:
1981145449b1SDimitry Andric FuncAttrs.addAttribute("zero-call-used-regs", "all");
1982145449b1SDimitry Andric break;
1983145449b1SDimitry Andric }
19847442d6faSDimitry Andric }
19857442d6faSDimitry Andric
19867fa27ce4SDimitry Andric if (LangOpts.assumeFunctionsAreConvergent()) {
1987461a67faSDimitry Andric // Conservatively, mark all functions and calls in CUDA and OpenCL as
1988461a67faSDimitry Andric // convergent (meaning, they may call an intrinsically convergent op, such
1989461a67faSDimitry Andric // as __syncthreads() / barrier(), and so can't have certain optimizations
1990461a67faSDimitry Andric // applied around them). LLVM will remove this attribute where it safely
1991461a67faSDimitry Andric // can.
19927442d6faSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::Convergent);
1993461a67faSDimitry Andric }
19947442d6faSDimitry Andric
1995e3b55780SDimitry Andric // TODO: NoUnwind attribute should be added for other GPU modes HIP,
19967fa27ce4SDimitry Andric // OpenMP offload. AFAIK, neither of them support exceptions in device code.
19977fa27ce4SDimitry Andric if ((LangOpts.CUDA && LangOpts.CUDAIsDevice) || LangOpts.OpenCL ||
19987fa27ce4SDimitry Andric LangOpts.SYCLIsDevice) {
19997442d6faSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
20007442d6faSDimitry Andric }
2001676fbe81SDimitry Andric
2002676fbe81SDimitry Andric for (StringRef Attr : CodeGenOpts.DefaultFunctionAttrs) {
2003676fbe81SDimitry Andric StringRef Var, Value;
2004676fbe81SDimitry Andric std::tie(Var, Value) = Attr.split('=');
2005676fbe81SDimitry Andric FuncAttrs.addAttribute(Var, Value);
2006676fbe81SDimitry Andric }
2007ac9a064cSDimitry Andric
2008ac9a064cSDimitry Andric TargetInfo::BranchProtectionInfo BPI(LangOpts);
2009adf62863SDimitry Andric TargetCodeGenInfo::initBranchProtectionFnAttributes(BPI, FuncAttrs);
20107442d6faSDimitry Andric }
20117442d6faSDimitry Andric
2012b1c73532SDimitry Andric /// Merges `target-features` from \TargetOpts and \F, and sets the result in
2013b1c73532SDimitry Andric /// \FuncAttr
2014b1c73532SDimitry Andric /// * features from \F are always kept
2015b1c73532SDimitry Andric /// * a feature from \TargetOpts is kept if itself and its opposite are absent
2016b1c73532SDimitry Andric /// from \F
2017b1c73532SDimitry Andric static void
overrideFunctionFeaturesWithTargetFeatures(llvm::AttrBuilder & FuncAttr,const llvm::Function & F,const TargetOptions & TargetOpts)2018b1c73532SDimitry Andric overrideFunctionFeaturesWithTargetFeatures(llvm::AttrBuilder &FuncAttr,
2019b1c73532SDimitry Andric const llvm::Function &F,
2020b1c73532SDimitry Andric const TargetOptions &TargetOpts) {
2021b1c73532SDimitry Andric auto FFeatures = F.getFnAttribute("target-features");
2022b1c73532SDimitry Andric
2023b1c73532SDimitry Andric llvm::StringSet<> MergedNames;
2024b1c73532SDimitry Andric SmallVector<StringRef> MergedFeatures;
2025b1c73532SDimitry Andric MergedFeatures.reserve(TargetOpts.Features.size());
2026b1c73532SDimitry Andric
2027b1c73532SDimitry Andric auto AddUnmergedFeatures = [&](auto &&FeatureRange) {
2028b1c73532SDimitry Andric for (StringRef Feature : FeatureRange) {
2029b1c73532SDimitry Andric if (Feature.empty())
2030b1c73532SDimitry Andric continue;
2031b1c73532SDimitry Andric assert(Feature[0] == '+' || Feature[0] == '-');
2032b1c73532SDimitry Andric StringRef Name = Feature.drop_front(1);
2033b1c73532SDimitry Andric bool Merged = !MergedNames.insert(Name).second;
2034b1c73532SDimitry Andric if (!Merged)
2035b1c73532SDimitry Andric MergedFeatures.push_back(Feature);
2036b1c73532SDimitry Andric }
2037b1c73532SDimitry Andric };
2038b1c73532SDimitry Andric
2039b1c73532SDimitry Andric if (FFeatures.isValid())
2040b1c73532SDimitry Andric AddUnmergedFeatures(llvm::split(FFeatures.getValueAsString(), ','));
2041b1c73532SDimitry Andric AddUnmergedFeatures(TargetOpts.Features);
2042b1c73532SDimitry Andric
2043b1c73532SDimitry Andric if (!MergedFeatures.empty()) {
2044b1c73532SDimitry Andric llvm::sort(MergedFeatures);
2045b1c73532SDimitry Andric FuncAttr.addAttribute("target-features", llvm::join(MergedFeatures, ","));
2046b1c73532SDimitry Andric }
2047b1c73532SDimitry Andric }
2048b1c73532SDimitry Andric
mergeDefaultFunctionDefinitionAttributes(llvm::Function & F,const CodeGenOptions & CodeGenOpts,const LangOptions & LangOpts,const TargetOptions & TargetOpts,bool WillInternalize)2049b1c73532SDimitry Andric void CodeGen::mergeDefaultFunctionDefinitionAttributes(
2050b1c73532SDimitry Andric llvm::Function &F, const CodeGenOptions &CodeGenOpts,
20517fa27ce4SDimitry Andric const LangOptions &LangOpts, const TargetOptions &TargetOpts,
20527fa27ce4SDimitry Andric bool WillInternalize) {
20537fa27ce4SDimitry Andric
20547fa27ce4SDimitry Andric llvm::AttrBuilder FuncAttrs(F.getContext());
20557fa27ce4SDimitry Andric // Here we only extract the options that are relevant compared to the version
20567fa27ce4SDimitry Andric // from GetCPUAndFeaturesAttributes.
20577fa27ce4SDimitry Andric if (!TargetOpts.CPU.empty())
20587fa27ce4SDimitry Andric FuncAttrs.addAttribute("target-cpu", TargetOpts.CPU);
20597fa27ce4SDimitry Andric if (!TargetOpts.TuneCPU.empty())
20607fa27ce4SDimitry Andric FuncAttrs.addAttribute("tune-cpu", TargetOpts.TuneCPU);
20617fa27ce4SDimitry Andric
20627fa27ce4SDimitry Andric ::getTrivialDefaultFunctionAttributes(F.getName(), F.hasOptNone(),
20637fa27ce4SDimitry Andric CodeGenOpts, LangOpts,
20647fa27ce4SDimitry Andric /*AttrOnCallSite=*/false, FuncAttrs);
20657fa27ce4SDimitry Andric
20667fa27ce4SDimitry Andric if (!WillInternalize && F.isInterposable()) {
20677fa27ce4SDimitry Andric // Do not promote "dynamic" denormal-fp-math to this translation unit's
20687fa27ce4SDimitry Andric // setting for weak functions that won't be internalized. The user has no
20697fa27ce4SDimitry Andric // real control for how builtin bitcode is linked, so we shouldn't assume
20707fa27ce4SDimitry Andric // later copies will use a consistent mode.
20717fa27ce4SDimitry Andric F.addFnAttrs(FuncAttrs);
20727fa27ce4SDimitry Andric return;
20737fa27ce4SDimitry Andric }
20747fa27ce4SDimitry Andric
20757fa27ce4SDimitry Andric llvm::AttributeMask AttrsToRemove;
20767fa27ce4SDimitry Andric
20777fa27ce4SDimitry Andric llvm::DenormalMode DenormModeToMerge = F.getDenormalModeRaw();
20787fa27ce4SDimitry Andric llvm::DenormalMode DenormModeToMergeF32 = F.getDenormalModeF32Raw();
20797fa27ce4SDimitry Andric llvm::DenormalMode Merged =
20807fa27ce4SDimitry Andric CodeGenOpts.FPDenormalMode.mergeCalleeMode(DenormModeToMerge);
20817fa27ce4SDimitry Andric llvm::DenormalMode MergedF32 = CodeGenOpts.FP32DenormalMode;
20827fa27ce4SDimitry Andric
20837fa27ce4SDimitry Andric if (DenormModeToMergeF32.isValid()) {
20847fa27ce4SDimitry Andric MergedF32 =
20857fa27ce4SDimitry Andric CodeGenOpts.FP32DenormalMode.mergeCalleeMode(DenormModeToMergeF32);
20867fa27ce4SDimitry Andric }
20877fa27ce4SDimitry Andric
20887fa27ce4SDimitry Andric if (Merged == llvm::DenormalMode::getDefault()) {
20897fa27ce4SDimitry Andric AttrsToRemove.addAttribute("denormal-fp-math");
20907fa27ce4SDimitry Andric } else if (Merged != DenormModeToMerge) {
20917fa27ce4SDimitry Andric // Overwrite existing attribute
20927fa27ce4SDimitry Andric FuncAttrs.addAttribute("denormal-fp-math",
20937fa27ce4SDimitry Andric CodeGenOpts.FPDenormalMode.str());
20947fa27ce4SDimitry Andric }
20957fa27ce4SDimitry Andric
20967fa27ce4SDimitry Andric if (MergedF32 == llvm::DenormalMode::getDefault()) {
20977fa27ce4SDimitry Andric AttrsToRemove.addAttribute("denormal-fp-math-f32");
20987fa27ce4SDimitry Andric } else if (MergedF32 != DenormModeToMergeF32) {
20997fa27ce4SDimitry Andric // Overwrite existing attribute
21007fa27ce4SDimitry Andric FuncAttrs.addAttribute("denormal-fp-math-f32",
21017fa27ce4SDimitry Andric CodeGenOpts.FP32DenormalMode.str());
21027fa27ce4SDimitry Andric }
21037fa27ce4SDimitry Andric
21047fa27ce4SDimitry Andric F.removeFnAttrs(AttrsToRemove);
21057fa27ce4SDimitry Andric addDenormalModeAttrs(Merged, MergedF32, FuncAttrs);
2106b1c73532SDimitry Andric
2107b1c73532SDimitry Andric overrideFunctionFeaturesWithTargetFeatures(FuncAttrs, F, TargetOpts);
2108b1c73532SDimitry Andric
21097fa27ce4SDimitry Andric F.addFnAttrs(FuncAttrs);
21107fa27ce4SDimitry Andric }
21117fa27ce4SDimitry Andric
getTrivialDefaultFunctionAttributes(StringRef Name,bool HasOptnone,bool AttrOnCallSite,llvm::AttrBuilder & FuncAttrs)21127fa27ce4SDimitry Andric void CodeGenModule::getTrivialDefaultFunctionAttributes(
21137fa27ce4SDimitry Andric StringRef Name, bool HasOptnone, bool AttrOnCallSite,
21147fa27ce4SDimitry Andric llvm::AttrBuilder &FuncAttrs) {
21157fa27ce4SDimitry Andric ::getTrivialDefaultFunctionAttributes(Name, HasOptnone, getCodeGenOpts(),
21167fa27ce4SDimitry Andric getLangOpts(), AttrOnCallSite,
21177fa27ce4SDimitry Andric FuncAttrs);
21187fa27ce4SDimitry Andric }
21197fa27ce4SDimitry Andric
getDefaultFunctionAttributes(StringRef Name,bool HasOptnone,bool AttrOnCallSite,llvm::AttrBuilder & FuncAttrs)21207fa27ce4SDimitry Andric void CodeGenModule::getDefaultFunctionAttributes(StringRef Name,
21217fa27ce4SDimitry Andric bool HasOptnone,
21227fa27ce4SDimitry Andric bool AttrOnCallSite,
21237fa27ce4SDimitry Andric llvm::AttrBuilder &FuncAttrs) {
21247fa27ce4SDimitry Andric getTrivialDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite,
21257fa27ce4SDimitry Andric FuncAttrs);
21267fa27ce4SDimitry Andric // If we're just getting the default, get the default values for mergeable
21277fa27ce4SDimitry Andric // attributes.
21287fa27ce4SDimitry Andric if (!AttrOnCallSite)
21297fa27ce4SDimitry Andric addMergableDefaultFunctionAttributes(CodeGenOpts, FuncAttrs);
21307fa27ce4SDimitry Andric }
21317fa27ce4SDimitry Andric
addDefaultFunctionDefinitionAttributes(llvm::AttrBuilder & attrs)2132cfca06d7SDimitry Andric void CodeGenModule::addDefaultFunctionDefinitionAttributes(
2133cfca06d7SDimitry Andric llvm::AttrBuilder &attrs) {
2134cfca06d7SDimitry Andric getDefaultFunctionAttributes(/*function name*/ "", /*optnone*/ false,
2135cfca06d7SDimitry Andric /*for call*/ false, attrs);
2136cfca06d7SDimitry Andric GetCPUAndFeaturesAttributes(GlobalDecl(), attrs);
2137cfca06d7SDimitry Andric }
2138cfca06d7SDimitry Andric
addNoBuiltinAttributes(llvm::AttrBuilder & FuncAttrs,const LangOptions & LangOpts,const NoBuiltinAttr * NBA=nullptr)2139cfca06d7SDimitry Andric static void addNoBuiltinAttributes(llvm::AttrBuilder &FuncAttrs,
2140cfca06d7SDimitry Andric const LangOptions &LangOpts,
2141cfca06d7SDimitry Andric const NoBuiltinAttr *NBA = nullptr) {
2142cfca06d7SDimitry Andric auto AddNoBuiltinAttr = [&FuncAttrs](StringRef BuiltinName) {
2143cfca06d7SDimitry Andric SmallString<32> AttributeName;
2144cfca06d7SDimitry Andric AttributeName += "no-builtin-";
2145cfca06d7SDimitry Andric AttributeName += BuiltinName;
2146cfca06d7SDimitry Andric FuncAttrs.addAttribute(AttributeName);
2147cfca06d7SDimitry Andric };
2148cfca06d7SDimitry Andric
2149cfca06d7SDimitry Andric // First, handle the language options passed through -fno-builtin.
2150cfca06d7SDimitry Andric if (LangOpts.NoBuiltin) {
2151cfca06d7SDimitry Andric // -fno-builtin disables them all.
2152cfca06d7SDimitry Andric FuncAttrs.addAttribute("no-builtins");
2153cfca06d7SDimitry Andric return;
2154cfca06d7SDimitry Andric }
2155cfca06d7SDimitry Andric
2156cfca06d7SDimitry Andric // Then, add attributes for builtins specified through -fno-builtin-<name>.
2157cfca06d7SDimitry Andric llvm::for_each(LangOpts.NoBuiltinFuncs, AddNoBuiltinAttr);
2158cfca06d7SDimitry Andric
2159cfca06d7SDimitry Andric // Now, let's check the __attribute__((no_builtin("...")) attribute added to
2160cfca06d7SDimitry Andric // the source.
2161cfca06d7SDimitry Andric if (!NBA)
2162cfca06d7SDimitry Andric return;
2163cfca06d7SDimitry Andric
2164cfca06d7SDimitry Andric // If there is a wildcard in the builtin names specified through the
2165cfca06d7SDimitry Andric // attribute, disable them all.
2166cfca06d7SDimitry Andric if (llvm::is_contained(NBA->builtinNames(), "*")) {
2167cfca06d7SDimitry Andric FuncAttrs.addAttribute("no-builtins");
2168cfca06d7SDimitry Andric return;
2169cfca06d7SDimitry Andric }
2170cfca06d7SDimitry Andric
2171cfca06d7SDimitry Andric // And last, add the rest of the builtin names.
2172cfca06d7SDimitry Andric llvm::for_each(NBA->builtinNames(), AddNoBuiltinAttr);
2173cfca06d7SDimitry Andric }
2174cfca06d7SDimitry Andric
DetermineNoUndef(QualType QTy,CodeGenTypes & Types,const llvm::DataLayout & DL,const ABIArgInfo & AI,bool CheckCoerce=true)2175344a3780SDimitry Andric static bool DetermineNoUndef(QualType QTy, CodeGenTypes &Types,
2176344a3780SDimitry Andric const llvm::DataLayout &DL, const ABIArgInfo &AI,
2177344a3780SDimitry Andric bool CheckCoerce = true) {
2178344a3780SDimitry Andric llvm::Type *Ty = Types.ConvertTypeForMem(QTy);
2179b1c73532SDimitry Andric if (AI.getKind() == ABIArgInfo::Indirect ||
2180b1c73532SDimitry Andric AI.getKind() == ABIArgInfo::IndirectAliased)
2181344a3780SDimitry Andric return true;
2182344a3780SDimitry Andric if (AI.getKind() == ABIArgInfo::Extend)
2183344a3780SDimitry Andric return true;
2184344a3780SDimitry Andric if (!DL.typeSizeEqualsStoreSize(Ty))
2185344a3780SDimitry Andric // TODO: This will result in a modest amount of values not marked noundef
2186344a3780SDimitry Andric // when they could be. We care about values that *invisibly* contain undef
2187344a3780SDimitry Andric // bits from the perspective of LLVM IR.
2188344a3780SDimitry Andric return false;
2189344a3780SDimitry Andric if (CheckCoerce && AI.canHaveCoerceToType()) {
2190344a3780SDimitry Andric llvm::Type *CoerceTy = AI.getCoerceToType();
2191344a3780SDimitry Andric if (llvm::TypeSize::isKnownGT(DL.getTypeSizeInBits(CoerceTy),
2192344a3780SDimitry Andric DL.getTypeSizeInBits(Ty)))
2193344a3780SDimitry Andric // If we're coercing to a type with a greater size than the canonical one,
2194344a3780SDimitry Andric // we're introducing new undef bits.
2195344a3780SDimitry Andric // Coercing to a type of smaller or equal size is ok, as we know that
2196344a3780SDimitry Andric // there's no internal padding (typeSizeEqualsStoreSize).
2197344a3780SDimitry Andric return false;
2198344a3780SDimitry Andric }
219977fc4c14SDimitry Andric if (QTy->isBitIntType())
2200344a3780SDimitry Andric return true;
2201344a3780SDimitry Andric if (QTy->isReferenceType())
2202344a3780SDimitry Andric return true;
2203344a3780SDimitry Andric if (QTy->isNullPtrType())
2204344a3780SDimitry Andric return false;
2205344a3780SDimitry Andric if (QTy->isMemberPointerType())
2206344a3780SDimitry Andric // TODO: Some member pointers are `noundef`, but it depends on the ABI. For
2207344a3780SDimitry Andric // now, never mark them.
2208344a3780SDimitry Andric return false;
2209344a3780SDimitry Andric if (QTy->isScalarType()) {
2210344a3780SDimitry Andric if (const ComplexType *Complex = dyn_cast<ComplexType>(QTy))
2211344a3780SDimitry Andric return DetermineNoUndef(Complex->getElementType(), Types, DL, AI, false);
2212344a3780SDimitry Andric return true;
2213344a3780SDimitry Andric }
2214344a3780SDimitry Andric if (const VectorType *Vector = dyn_cast<VectorType>(QTy))
2215344a3780SDimitry Andric return DetermineNoUndef(Vector->getElementType(), Types, DL, AI, false);
2216344a3780SDimitry Andric if (const MatrixType *Matrix = dyn_cast<MatrixType>(QTy))
2217344a3780SDimitry Andric return DetermineNoUndef(Matrix->getElementType(), Types, DL, AI, false);
2218344a3780SDimitry Andric if (const ArrayType *Array = dyn_cast<ArrayType>(QTy))
2219344a3780SDimitry Andric return DetermineNoUndef(Array->getElementType(), Types, DL, AI, false);
2220344a3780SDimitry Andric
2221344a3780SDimitry Andric // TODO: Some structs may be `noundef`, in specific situations.
2222344a3780SDimitry Andric return false;
2223344a3780SDimitry Andric }
2224344a3780SDimitry Andric
2225e3b55780SDimitry Andric /// Check if the argument of a function has maybe_undef attribute.
IsArgumentMaybeUndef(const Decl * TargetDecl,unsigned NumRequiredArgs,unsigned ArgNo)2226e3b55780SDimitry Andric static bool IsArgumentMaybeUndef(const Decl *TargetDecl,
2227e3b55780SDimitry Andric unsigned NumRequiredArgs, unsigned ArgNo) {
2228e3b55780SDimitry Andric const auto *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
2229e3b55780SDimitry Andric if (!FD)
2230e3b55780SDimitry Andric return false;
2231e3b55780SDimitry Andric
2232e3b55780SDimitry Andric // Assume variadic arguments do not have maybe_undef attribute.
2233e3b55780SDimitry Andric if (ArgNo >= NumRequiredArgs)
2234e3b55780SDimitry Andric return false;
2235e3b55780SDimitry Andric
2236e3b55780SDimitry Andric // Check if argument has maybe_undef attribute.
2237e3b55780SDimitry Andric if (ArgNo < FD->getNumParams()) {
2238e3b55780SDimitry Andric const ParmVarDecl *Param = FD->getParamDecl(ArgNo);
2239e3b55780SDimitry Andric if (Param && Param->hasAttr<MaybeUndefAttr>())
2240e3b55780SDimitry Andric return true;
2241e3b55780SDimitry Andric }
2242e3b55780SDimitry Andric
2243e3b55780SDimitry Andric return false;
2244e3b55780SDimitry Andric }
2245e3b55780SDimitry Andric
22467fa27ce4SDimitry Andric /// Test if it's legal to apply nofpclass for the given parameter type and it's
22477fa27ce4SDimitry Andric /// lowered IR type.
canApplyNoFPClass(const ABIArgInfo & AI,QualType ParamType,bool IsReturn)22487fa27ce4SDimitry Andric static bool canApplyNoFPClass(const ABIArgInfo &AI, QualType ParamType,
22497fa27ce4SDimitry Andric bool IsReturn) {
22507fa27ce4SDimitry Andric // Should only apply to FP types in the source, not ABI promoted.
22517fa27ce4SDimitry Andric if (!ParamType->hasFloatingRepresentation())
22527fa27ce4SDimitry Andric return false;
22537fa27ce4SDimitry Andric
22547fa27ce4SDimitry Andric // The promoted-to IR type also needs to support nofpclass.
22557fa27ce4SDimitry Andric llvm::Type *IRTy = AI.getCoerceToType();
22567fa27ce4SDimitry Andric if (llvm::AttributeFuncs::isNoFPClassCompatibleType(IRTy))
22577fa27ce4SDimitry Andric return true;
22587fa27ce4SDimitry Andric
22597fa27ce4SDimitry Andric if (llvm::StructType *ST = dyn_cast<llvm::StructType>(IRTy)) {
22607fa27ce4SDimitry Andric return !IsReturn && AI.getCanBeFlattened() &&
22617fa27ce4SDimitry Andric llvm::all_of(ST->elements(), [](llvm::Type *Ty) {
22627fa27ce4SDimitry Andric return llvm::AttributeFuncs::isNoFPClassCompatibleType(Ty);
22637fa27ce4SDimitry Andric });
22647fa27ce4SDimitry Andric }
22657fa27ce4SDimitry Andric
22667fa27ce4SDimitry Andric return false;
22677fa27ce4SDimitry Andric }
22687fa27ce4SDimitry Andric
22697fa27ce4SDimitry Andric /// Return the nofpclass mask that can be applied to floating-point parameters.
getNoFPClassTestMask(const LangOptions & LangOpts)22707fa27ce4SDimitry Andric static llvm::FPClassTest getNoFPClassTestMask(const LangOptions &LangOpts) {
22717fa27ce4SDimitry Andric llvm::FPClassTest Mask = llvm::fcNone;
22727fa27ce4SDimitry Andric if (LangOpts.NoHonorInfs)
22737fa27ce4SDimitry Andric Mask |= llvm::fcInf;
22747fa27ce4SDimitry Andric if (LangOpts.NoHonorNaNs)
22757fa27ce4SDimitry Andric Mask |= llvm::fcNan;
22767fa27ce4SDimitry Andric return Mask;
22777fa27ce4SDimitry Andric }
22787fa27ce4SDimitry Andric
AdjustMemoryAttribute(StringRef Name,CGCalleeInfo CalleeInfo,llvm::AttributeList & Attrs)2279b1c73532SDimitry Andric void CodeGenModule::AdjustMemoryAttribute(StringRef Name,
2280b1c73532SDimitry Andric CGCalleeInfo CalleeInfo,
2281b1c73532SDimitry Andric llvm::AttributeList &Attrs) {
2282b1c73532SDimitry Andric if (Attrs.getMemoryEffects().getModRef() == llvm::ModRefInfo::NoModRef) {
2283b1c73532SDimitry Andric Attrs = Attrs.removeFnAttribute(getLLVMContext(), llvm::Attribute::Memory);
2284b1c73532SDimitry Andric llvm::Attribute MemoryAttr = llvm::Attribute::getWithMemoryEffects(
2285b1c73532SDimitry Andric getLLVMContext(), llvm::MemoryEffects::writeOnly());
2286b1c73532SDimitry Andric Attrs = Attrs.addFnAttribute(getLLVMContext(), MemoryAttr);
2287b1c73532SDimitry Andric }
2288b1c73532SDimitry Andric }
2289b1c73532SDimitry Andric
2290cfca06d7SDimitry Andric /// Construct the IR attribute list of a function or call.
2291cfca06d7SDimitry Andric ///
2292cfca06d7SDimitry Andric /// When adding an attribute, please consider where it should be handled:
2293cfca06d7SDimitry Andric ///
2294cfca06d7SDimitry Andric /// - getDefaultFunctionAttributes is for attributes that are essentially
2295cfca06d7SDimitry Andric /// part of the global target configuration (but perhaps can be
2296cfca06d7SDimitry Andric /// overridden on a per-function basis). Adding attributes there
2297cfca06d7SDimitry Andric /// will cause them to also be set in frontends that build on Clang's
2298cfca06d7SDimitry Andric /// target-configuration logic, as well as for code defined in library
2299cfca06d7SDimitry Andric /// modules such as CUDA's libdevice.
2300cfca06d7SDimitry Andric ///
2301cfca06d7SDimitry Andric /// - ConstructAttributeList builds on top of getDefaultFunctionAttributes
2302cfca06d7SDimitry Andric /// and adds declaration-specific, convention-specific, and
2303cfca06d7SDimitry Andric /// frontend-specific logic. The last is of particular importance:
2304cfca06d7SDimitry Andric /// attributes that restrict how the frontend generates code must be
2305cfca06d7SDimitry Andric /// added here rather than getDefaultFunctionAttributes.
2306cfca06d7SDimitry Andric ///
ConstructAttributeList(StringRef Name,const CGFunctionInfo & FI,CGCalleeInfo CalleeInfo,llvm::AttributeList & AttrList,unsigned & CallingConv,bool AttrOnCallSite,bool IsThunk)2307344a3780SDimitry Andric void CodeGenModule::ConstructAttributeList(StringRef Name,
2308344a3780SDimitry Andric const CGFunctionInfo &FI,
2309344a3780SDimitry Andric CGCalleeInfo CalleeInfo,
2310344a3780SDimitry Andric llvm::AttributeList &AttrList,
2311344a3780SDimitry Andric unsigned &CallingConv,
2312344a3780SDimitry Andric bool AttrOnCallSite, bool IsThunk) {
23136f8fc217SDimitry Andric llvm::AttrBuilder FuncAttrs(getLLVMContext());
23146f8fc217SDimitry Andric llvm::AttrBuilder RetAttrs(getLLVMContext());
2315ec2b103cSEd Schouten
2316cfca06d7SDimitry Andric // Collect function IR attributes from the CC lowering.
2317cfca06d7SDimitry Andric // We'll collect the paramete and result attributes later.
23184c8b2481SRoman Divacky CallingConv = FI.getEffectiveCallingConvention();
2319ecb7e5c8SRoman Divacky if (FI.isNoReturn())
2320809500fcSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
2321cfca06d7SDimitry Andric if (FI.isCmseNSCall())
2322cfca06d7SDimitry Andric FuncAttrs.addAttribute("cmse_nonsecure_call");
2323ecb7e5c8SRoman Divacky
2324cfca06d7SDimitry Andric // Collect function IR attributes from the callee prototype if we have one.
232545b53394SDimitry Andric AddAttributesFromFunctionProtoType(getContext(), FuncAttrs,
232645b53394SDimitry Andric CalleeInfo.getCalleeFunctionProtoType());
232745b53394SDimitry Andric
2328676fbe81SDimitry Andric const Decl *TargetDecl = CalleeInfo.getCalleeDecl().getDecl();
232945b53394SDimitry Andric
2330c0981da4SDimitry Andric // Attach assumption attributes to the declaration. If this is a call
2331c0981da4SDimitry Andric // site, attach assumptions from the caller to the call as well.
2332ac9a064cSDimitry Andric AddAttributesFromOMPAssumes(FuncAttrs, TargetDecl);
2333c0981da4SDimitry Andric
23347442d6faSDimitry Andric bool HasOptnone = false;
2335cfca06d7SDimitry Andric // The NoBuiltinAttr attached to the target FunctionDecl.
2336cfca06d7SDimitry Andric const NoBuiltinAttr *NBA = nullptr;
2337cfca06d7SDimitry Andric
2338e3b55780SDimitry Andric // Some ABIs may result in additional accesses to arguments that may
2339e3b55780SDimitry Andric // otherwise not be present.
2340e3b55780SDimitry Andric auto AddPotentialArgAccess = [&]() {
2341e3b55780SDimitry Andric llvm::Attribute A = FuncAttrs.getAttribute(llvm::Attribute::Memory);
2342e3b55780SDimitry Andric if (A.isValid())
2343e3b55780SDimitry Andric FuncAttrs.addMemoryAttr(A.getMemoryEffects() |
2344e3b55780SDimitry Andric llvm::MemoryEffects::argMemOnly());
2345e3b55780SDimitry Andric };
2346e3b55780SDimitry Andric
2347cfca06d7SDimitry Andric // Collect function IR attributes based on declaration-specific
2348cfca06d7SDimitry Andric // information.
2349ec2b103cSEd Schouten // FIXME: handle sseregparm someday...
2350ec2b103cSEd Schouten if (TargetDecl) {
235136981b17SDimitry Andric if (TargetDecl->hasAttr<ReturnsTwiceAttr>())
2352809500fcSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::ReturnsTwice);
23535362a71cSEd Schouten if (TargetDecl->hasAttr<NoThrowAttr>())
2354809500fcSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
2355809500fcSDimitry Andric if (TargetDecl->hasAttr<NoReturnAttr>())
2356809500fcSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
2357325377b5SDimitry Andric if (TargetDecl->hasAttr<ColdAttr>())
2358325377b5SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::Cold);
2359b60736ecSDimitry Andric if (TargetDecl->hasAttr<HotAttr>())
2360b60736ecSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::Hot);
23619f4dbff6SDimitry Andric if (TargetDecl->hasAttr<NoDuplicateAttr>())
23629f4dbff6SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
2363bab175ecSDimitry Andric if (TargetDecl->hasAttr<ConvergentAttr>())
2364bab175ecSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::Convergent);
2365809500fcSDimitry Andric
2366809500fcSDimitry Andric if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
236745b53394SDimitry Andric AddAttributesFromFunctionProtoType(
236845b53394SDimitry Andric getContext(), FuncAttrs, Fn->getType()->getAs<FunctionProtoType>());
2369cfca06d7SDimitry Andric if (AttrOnCallSite && Fn->isReplaceableGlobalAllocationFunction()) {
2370cfca06d7SDimitry Andric // A sane operator new returns a non-aliasing pointer.
2371cfca06d7SDimitry Andric auto Kind = Fn->getDeclName().getCXXOverloadedOperator();
2372cfca06d7SDimitry Andric if (getCodeGenOpts().AssumeSaneOperatorNew &&
2373cfca06d7SDimitry Andric (Kind == OO_New || Kind == OO_Array_New))
2374cfca06d7SDimitry Andric RetAttrs.addAttribute(llvm::Attribute::NoAlias);
2375cfca06d7SDimitry Andric }
2376809500fcSDimitry Andric const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn);
2377706b4fc4SDimitry Andric const bool IsVirtualCall = MD && MD->isVirtual();
2378706b4fc4SDimitry Andric // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a call to a
2379706b4fc4SDimitry Andric // virtual function. These attributes are not inherited by overloads.
2380706b4fc4SDimitry Andric if (!(AttrOnCallSite && IsVirtualCall)) {
2381706b4fc4SDimitry Andric if (Fn->isNoReturn())
2382809500fcSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
2383cfca06d7SDimitry Andric NBA = Fn->getAttr<NoBuiltinAttr>();
2384706b4fc4SDimitry Andric }
23857fa27ce4SDimitry Andric }
23867fa27ce4SDimitry Andric
23877fa27ce4SDimitry Andric if (isa<FunctionDecl>(TargetDecl) || isa<VarDecl>(TargetDecl)) {
2388b60736ecSDimitry Andric // Only place nomerge attribute on call sites, never functions. This
2389b60736ecSDimitry Andric // allows it to work on indirect virtual function calls.
2390b60736ecSDimitry Andric if (AttrOnCallSite && TargetDecl->hasAttr<NoMergeAttr>())
2391b60736ecSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoMerge);
23924ba67500SRoman Divacky }
23934ba67500SRoman Divacky
239445b53394SDimitry Andric // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
239536981b17SDimitry Andric if (TargetDecl->hasAttr<ConstAttr>()) {
2396e3b55780SDimitry Andric FuncAttrs.addMemoryAttr(llvm::MemoryEffects::none());
2397809500fcSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
2398344a3780SDimitry Andric // gcc specifies that 'const' functions have greater restrictions than
2399344a3780SDimitry Andric // 'pure' functions, so they also cannot have infinite loops.
2400344a3780SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
240136981b17SDimitry Andric } else if (TargetDecl->hasAttr<PureAttr>()) {
2402e3b55780SDimitry Andric FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
2403809500fcSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
2404344a3780SDimitry Andric // gcc specifies that 'pure' functions cannot have infinite loops.
2405344a3780SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
240645b53394SDimitry Andric } else if (TargetDecl->hasAttr<NoAliasAttr>()) {
2407b1c73532SDimitry Andric FuncAttrs.addMemoryAttr(llvm::MemoryEffects::inaccessibleOrArgMemOnly());
240845b53394SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
240936981b17SDimitry Andric }
24105e20cdd8SDimitry Andric if (TargetDecl->hasAttr<RestrictAttr>())
2411809500fcSDimitry Andric RetAttrs.addAttribute(llvm::Attribute::NoAlias);
241248675466SDimitry Andric if (TargetDecl->hasAttr<ReturnsNonNullAttr>() &&
241348675466SDimitry Andric !CodeGenOpts.NullPointerIsValid)
24149f4dbff6SDimitry Andric RetAttrs.addAttribute(llvm::Attribute::NonNull);
241557091882SDimitry Andric if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
241657091882SDimitry Andric FuncAttrs.addAttribute("no_caller_saved_registers");
241748675466SDimitry Andric if (TargetDecl->hasAttr<AnyX86NoCfCheckAttr>())
241848675466SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoCfCheck);
2419b60736ecSDimitry Andric if (TargetDecl->hasAttr<LeafAttr>())
2420b60736ecSDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NoCallback);
242106d4ba38SDimitry Andric
242206d4ba38SDimitry Andric HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
2423bab175ecSDimitry Andric if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
2424e3b55780SDimitry Andric std::optional<unsigned> NumElemsParam;
242548675466SDimitry Andric if (AllocSize->getNumElemsParam().isValid())
242648675466SDimitry Andric NumElemsParam = AllocSize->getNumElemsParam().getLLVMIndex();
242748675466SDimitry Andric FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam().getLLVMIndex(),
2428bab175ecSDimitry Andric NumElemsParam);
2429bab175ecSDimitry Andric }
2430ec2b103cSEd Schouten
2431cfca06d7SDimitry Andric if (TargetDecl->hasAttr<OpenCLKernelAttr>()) {
243248675466SDimitry Andric if (getLangOpts().OpenCLVersion <= 120) {
243348675466SDimitry Andric // OpenCL v1.2 Work groups are always uniform
243448675466SDimitry Andric FuncAttrs.addAttribute("uniform-work-group-size", "true");
243548675466SDimitry Andric } else {
243648675466SDimitry Andric // OpenCL v2.0 Work groups may be whether uniform or not.
243748675466SDimitry Andric // '-cl-uniform-work-group-size' compile option gets a hint
243848675466SDimitry Andric // to the compiler that the global work-size be a multiple of
243948675466SDimitry Andric // the work-group size specified to clEnqueueNDRangeKernel
244048675466SDimitry Andric // (i.e. work groups are uniform).
2441b1c73532SDimitry Andric FuncAttrs.addAttribute(
2442b1c73532SDimitry Andric "uniform-work-group-size",
2443b1c73532SDimitry Andric llvm::toStringRef(getLangOpts().OffloadUniformBlock));
244448675466SDimitry Andric }
244548675466SDimitry Andric }
2446b1c73532SDimitry Andric
2447b1c73532SDimitry Andric if (TargetDecl->hasAttr<CUDAGlobalAttr>() &&
2448b1c73532SDimitry Andric getLangOpts().OffloadUniformBlock)
2449b1c73532SDimitry Andric FuncAttrs.addAttribute("uniform-work-group-size", "true");
2450b1c73532SDimitry Andric
2451b1c73532SDimitry Andric if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
2452b1c73532SDimitry Andric FuncAttrs.addAttribute("aarch64_pstate_sm_body");
2453cfca06d7SDimitry Andric }
245448675466SDimitry Andric
2455cfca06d7SDimitry Andric // Attach "no-builtins" attributes to:
2456cfca06d7SDimitry Andric // * call sites: both `nobuiltin` and "no-builtins" or "no-builtin-<name>".
2457cfca06d7SDimitry Andric // * definitions: "no-builtins" or "no-builtin-<name>" only.
2458cfca06d7SDimitry Andric // The attributes can come from:
2459cfca06d7SDimitry Andric // * LangOpts: -ffreestanding, -fno-builtin, -fno-builtin-<name>
2460cfca06d7SDimitry Andric // * FunctionDecl attributes: __attribute__((no_builtin(...)))
2461cfca06d7SDimitry Andric addNoBuiltinAttributes(FuncAttrs, getLangOpts(), NBA);
2462cfca06d7SDimitry Andric
2463cfca06d7SDimitry Andric // Collect function IR attributes based on global settiings.
2464cfca06d7SDimitry Andric getDefaultFunctionAttributes(Name, HasOptnone, AttrOnCallSite, FuncAttrs);
2465cfca06d7SDimitry Andric
2466cfca06d7SDimitry Andric // Override some default IR attributes based on declaration-specific
2467cfca06d7SDimitry Andric // information.
2468cfca06d7SDimitry Andric if (TargetDecl) {
2469cfca06d7SDimitry Andric if (TargetDecl->hasAttr<NoSpeculativeLoadHardeningAttr>())
2470cfca06d7SDimitry Andric FuncAttrs.removeAttribute(llvm::Attribute::SpeculativeLoadHardening);
2471cfca06d7SDimitry Andric if (TargetDecl->hasAttr<SpeculativeLoadHardeningAttr>())
2472cfca06d7SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening);
2473cfca06d7SDimitry Andric if (TargetDecl->hasAttr<NoSplitStackAttr>())
2474cfca06d7SDimitry Andric FuncAttrs.removeAttribute("split-stack");
2475145449b1SDimitry Andric if (TargetDecl->hasAttr<ZeroCallUsedRegsAttr>()) {
2476145449b1SDimitry Andric // A function "__attribute__((...))" overrides the command-line flag.
2477145449b1SDimitry Andric auto Kind =
2478145449b1SDimitry Andric TargetDecl->getAttr<ZeroCallUsedRegsAttr>()->getZeroCallUsedRegs();
2479145449b1SDimitry Andric FuncAttrs.removeAttribute("zero-call-used-regs");
2480145449b1SDimitry Andric FuncAttrs.addAttribute(
2481145449b1SDimitry Andric "zero-call-used-regs",
2482145449b1SDimitry Andric ZeroCallUsedRegsAttr::ConvertZeroCallUsedRegsKindToStr(Kind));
2483145449b1SDimitry Andric }
2484cfca06d7SDimitry Andric
2485cfca06d7SDimitry Andric // Add NonLazyBind attribute to function declarations when -fno-plt
2486cfca06d7SDimitry Andric // is used.
2487cfca06d7SDimitry Andric // FIXME: what if we just haven't processed the function definition
2488cfca06d7SDimitry Andric // yet, or if it's an external definition like C99 inline?
2489cfca06d7SDimitry Andric if (CodeGenOpts.NoPLT) {
2490cfca06d7SDimitry Andric if (auto *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
2491cfca06d7SDimitry Andric if (!Fn->isDefined() && !AttrOnCallSite) {
2492cfca06d7SDimitry Andric FuncAttrs.addAttribute(llvm::Attribute::NonLazyBind);
2493cfca06d7SDimitry Andric }
2494cfca06d7SDimitry Andric }
2495cfca06d7SDimitry Andric }
2496cfca06d7SDimitry Andric }
2497cfca06d7SDimitry Andric
2498344a3780SDimitry Andric // Add "sample-profile-suffix-elision-policy" attribute for internal linkage
2499344a3780SDimitry Andric // functions with -funique-internal-linkage-names.
2500344a3780SDimitry Andric if (TargetDecl && CodeGenOpts.UniqueInternalLinkageNames) {
2501e3b55780SDimitry Andric if (const auto *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
2502e3b55780SDimitry Andric if (!FD->isExternallyVisible())
2503344a3780SDimitry Andric FuncAttrs.addAttribute("sample-profile-suffix-elision-policy",
2504344a3780SDimitry Andric "selected");
2505344a3780SDimitry Andric }
2506344a3780SDimitry Andric }
2507344a3780SDimitry Andric
2508cfca06d7SDimitry Andric // Collect non-call-site function IR attributes from declaration-specific
2509cfca06d7SDimitry Andric // information.
25107442d6faSDimitry Andric if (!AttrOnCallSite) {
2511cfca06d7SDimitry Andric if (TargetDecl && TargetDecl->hasAttr<CmseNSEntryAttr>())
2512cfca06d7SDimitry Andric FuncAttrs.addAttribute("cmse_nonsecure_entry");
251348675466SDimitry Andric
2514cfca06d7SDimitry Andric // Whether tail calls are enabled.
2515cfca06d7SDimitry Andric auto shouldDisableTailCalls = [&] {
2516cfca06d7SDimitry Andric // Should this be honored in getDefaultFunctionAttributes?
251748675466SDimitry Andric if (CodeGenOpts.DisableTailCalls)
2518cfca06d7SDimitry Andric return true;
2519cfca06d7SDimitry Andric
2520cfca06d7SDimitry Andric if (!TargetDecl)
2521cfca06d7SDimitry Andric return false;
2522cfca06d7SDimitry Andric
252348675466SDimitry Andric if (TargetDecl->hasAttr<DisableTailCallsAttr>() ||
252448675466SDimitry Andric TargetDecl->hasAttr<AnyX86InterruptAttr>())
2525cfca06d7SDimitry Andric return true;
2526cfca06d7SDimitry Andric
2527cfca06d7SDimitry Andric if (CodeGenOpts.NoEscapingBlockTailCalls) {
252848675466SDimitry Andric if (const auto *BD = dyn_cast<BlockDecl>(TargetDecl))
252948675466SDimitry Andric if (!BD->doesNotEscape())
2530cfca06d7SDimitry Andric return true;
253148675466SDimitry Andric }
253248675466SDimitry Andric
2533cfca06d7SDimitry Andric return false;
2534cfca06d7SDimitry Andric };
2535344a3780SDimitry Andric if (shouldDisableTailCalls())
2536344a3780SDimitry Andric FuncAttrs.addAttribute("disable-tail-calls", "true");
2537cfca06d7SDimitry Andric
2538cfca06d7SDimitry Andric // CPU/feature overrides. addDefaultFunctionDefinitionAttributes
2539cfca06d7SDimitry Andric // handles these separately to set them based on the global defaults.
2540676fbe81SDimitry Andric GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs);
2541809500fcSDimitry Andric }
254237f6c480SEd Schouten
2543cfca06d7SDimitry Andric // Collect attributes from arguments and return values.
254406d4ba38SDimitry Andric ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI);
254506d4ba38SDimitry Andric
2546ec2b103cSEd Schouten QualType RetTy = FI.getReturnType();
2547ec2b103cSEd Schouten const ABIArgInfo &RetAI = FI.getReturnInfo();
2548344a3780SDimitry Andric const llvm::DataLayout &DL = getDataLayout();
2549344a3780SDimitry Andric
2550344a3780SDimitry Andric // Determine if the return type could be partially undef
2551e3b55780SDimitry Andric if (CodeGenOpts.EnableNoundefAttrs &&
2552e3b55780SDimitry Andric HasStrictReturn(*this, RetTy, TargetDecl)) {
2553344a3780SDimitry Andric if (!RetTy->isVoidType() && RetAI.getKind() != ABIArgInfo::Indirect &&
2554344a3780SDimitry Andric DetermineNoUndef(RetTy, getTypes(), DL, RetAI))
2555344a3780SDimitry Andric RetAttrs.addAttribute(llvm::Attribute::NoUndef);
2556344a3780SDimitry Andric }
2557344a3780SDimitry Andric
2558ec2b103cSEd Schouten switch (RetAI.getKind()) {
255970b4596dSEd Schouten case ABIArgInfo::Extend:
256048675466SDimitry Andric if (RetAI.isSignExt())
2561809500fcSDimitry Andric RetAttrs.addAttribute(llvm::Attribute::SExt);
256248675466SDimitry Andric else
2563809500fcSDimitry Andric RetAttrs.addAttribute(llvm::Attribute::ZExt);
2564e3b55780SDimitry Andric [[fallthrough]];
256570b4596dSEd Schouten case ABIArgInfo::Direct:
2566bfef3995SDimitry Andric if (RetAI.getInReg())
2567bfef3995SDimitry Andric RetAttrs.addAttribute(llvm::Attribute::InReg);
25687fa27ce4SDimitry Andric
25697fa27ce4SDimitry Andric if (canApplyNoFPClass(RetAI, RetTy, true))
25707fa27ce4SDimitry Andric RetAttrs.addNoFPClassAttr(getNoFPClassTestMask(getLangOpts()));
25717fa27ce4SDimitry Andric
2572bfef3995SDimitry Andric break;
25733d1dcd9bSDimitry Andric case ABIArgInfo::Ignore:
2574ec2b103cSEd Schouten break;
2575ec2b103cSEd Schouten
257606d4ba38SDimitry Andric case ABIArgInfo::InAlloca:
257756d91b49SDimitry Andric case ABIArgInfo::Indirect: {
257806d4ba38SDimitry Andric // inalloca and sret disable readnone and readonly
2579e3b55780SDimitry Andric AddPotentialArgAccess();
2580ec2b103cSEd Schouten break;
258156d91b49SDimitry Andric }
2582ec2b103cSEd Schouten
25832b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand:
25842b6b257fSDimitry Andric break;
25852b6b257fSDimitry Andric
2586ec2b103cSEd Schouten case ABIArgInfo::Expand:
2587b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased:
258836981b17SDimitry Andric llvm_unreachable("Invalid ABI kind for return argument");
2589ec2b103cSEd Schouten }
2590ec2b103cSEd Schouten
2591344a3780SDimitry Andric if (!IsThunk) {
2592344a3780SDimitry Andric // FIXME: fix this properly, https://reviews.llvm.org/D100388
25939f4dbff6SDimitry Andric if (const auto *RefTy = RetTy->getAs<ReferenceType>()) {
25949f4dbff6SDimitry Andric QualType PTy = RefTy->getPointeeType();
25959f4dbff6SDimitry Andric if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
2596cfca06d7SDimitry Andric RetAttrs.addDereferenceableAttr(
2597cfca06d7SDimitry Andric getMinimumObjectSize(PTy).getQuantity());
2598e3b55780SDimitry Andric if (getTypes().getTargetAddressSpace(PTy) == 0 &&
259948675466SDimitry Andric !CodeGenOpts.NullPointerIsValid)
26009f4dbff6SDimitry Andric RetAttrs.addAttribute(llvm::Attribute::NonNull);
2601cfca06d7SDimitry Andric if (PTy->isObjectType()) {
2602cfca06d7SDimitry Andric llvm::Align Alignment =
2603cfca06d7SDimitry Andric getNaturalPointeeTypeAlignment(RetTy).getAsAlign();
2604cfca06d7SDimitry Andric RetAttrs.addAlignmentAttr(Alignment);
2605cfca06d7SDimitry Andric }
26069f4dbff6SDimitry Andric }
2607344a3780SDimitry Andric }
26089f4dbff6SDimitry Andric
26092b6b257fSDimitry Andric bool hasUsedSRet = false;
2610583e75ccSDimitry Andric SmallVector<llvm::AttributeSet, 4> ArgAttrs(IRFunctionArgs.totalIRArgs());
26112b6b257fSDimitry Andric
261206d4ba38SDimitry Andric // Attach attributes to sret.
261306d4ba38SDimitry Andric if (IRFunctionArgs.hasSRetArg()) {
26146f8fc217SDimitry Andric llvm::AttrBuilder SRETAttrs(getLLVMContext());
2615b60736ecSDimitry Andric SRETAttrs.addStructRetAttr(getTypes().ConvertTypeForMem(RetTy));
2616950076cdSDimitry Andric SRETAttrs.addAttribute(llvm::Attribute::Writable);
2617950076cdSDimitry Andric SRETAttrs.addAttribute(llvm::Attribute::DeadOnUnwind);
26182b6b257fSDimitry Andric hasUsedSRet = true;
261906d4ba38SDimitry Andric if (RetAI.getInReg())
262006d4ba38SDimitry Andric SRETAttrs.addAttribute(llvm::Attribute::InReg);
2621cfca06d7SDimitry Andric SRETAttrs.addAlignmentAttr(RetAI.getIndirectAlign().getQuantity());
2622583e75ccSDimitry Andric ArgAttrs[IRFunctionArgs.getSRetArgNo()] =
2623583e75ccSDimitry Andric llvm::AttributeSet::get(getLLVMContext(), SRETAttrs);
262406d4ba38SDimitry Andric }
262506d4ba38SDimitry Andric
262606d4ba38SDimitry Andric // Attach attributes to inalloca argument.
262706d4ba38SDimitry Andric if (IRFunctionArgs.hasInallocaArg()) {
26286f8fc217SDimitry Andric llvm::AttrBuilder Attrs(getLLVMContext());
2629344a3780SDimitry Andric Attrs.addInAllocaAttr(FI.getArgStruct());
2630583e75ccSDimitry Andric ArgAttrs[IRFunctionArgs.getInallocaArgNo()] =
2631583e75ccSDimitry Andric llvm::AttributeSet::get(getLLVMContext(), Attrs);
263206d4ba38SDimitry Andric }
263306d4ba38SDimitry Andric
2634344a3780SDimitry Andric // Apply `nonnull`, `dereferencable(N)` and `align N` to the `this` argument,
2635344a3780SDimitry Andric // unless this is a thunk function.
2636344a3780SDimitry Andric // FIXME: fix this properly, https://reviews.llvm.org/D100388
2637b60736ecSDimitry Andric if (FI.isInstanceMethod() && !IRFunctionArgs.hasInallocaArg() &&
2638344a3780SDimitry Andric !FI.arg_begin()->type->isVoidPointerType() && !IsThunk) {
2639b60736ecSDimitry Andric auto IRArgs = IRFunctionArgs.getIRArgs(0);
2640b60736ecSDimitry Andric
2641b60736ecSDimitry Andric assert(IRArgs.second == 1 && "Expected only a single `this` pointer.");
2642b60736ecSDimitry Andric
26436f8fc217SDimitry Andric llvm::AttrBuilder Attrs(getLLVMContext());
2644b60736ecSDimitry Andric
2645344a3780SDimitry Andric QualType ThisTy =
2646b1c73532SDimitry Andric FI.arg_begin()->type.getTypePtr()->getPointeeType();
2647344a3780SDimitry Andric
2648b60736ecSDimitry Andric if (!CodeGenOpts.NullPointerIsValid &&
2649e3b55780SDimitry Andric getTypes().getTargetAddressSpace(FI.arg_begin()->type) == 0) {
2650b60736ecSDimitry Andric Attrs.addAttribute(llvm::Attribute::NonNull);
2651344a3780SDimitry Andric Attrs.addDereferenceableAttr(getMinimumObjectSize(ThisTy).getQuantity());
2652b60736ecSDimitry Andric } else {
2653b60736ecSDimitry Andric // FIXME dereferenceable should be correct here, regardless of
2654b60736ecSDimitry Andric // NullPointerIsValid. However, dereferenceable currently does not always
2655b60736ecSDimitry Andric // respect NullPointerIsValid and may imply nonnull and break the program.
2656b60736ecSDimitry Andric // See https://reviews.llvm.org/D66618 for discussions.
2657b60736ecSDimitry Andric Attrs.addDereferenceableOrNullAttr(
2658b60736ecSDimitry Andric getMinimumObjectSize(
2659b60736ecSDimitry Andric FI.arg_begin()->type.castAs<PointerType>()->getPointeeType())
2660b60736ecSDimitry Andric .getQuantity());
2661b60736ecSDimitry Andric }
2662b60736ecSDimitry Andric
2663344a3780SDimitry Andric llvm::Align Alignment =
2664344a3780SDimitry Andric getNaturalTypeAlignment(ThisTy, /*BaseInfo=*/nullptr,
2665344a3780SDimitry Andric /*TBAAInfo=*/nullptr, /*forPointeeType=*/true)
2666344a3780SDimitry Andric .getAsAlign();
2667344a3780SDimitry Andric Attrs.addAlignmentAttr(Alignment);
2668344a3780SDimitry Andric
2669b60736ecSDimitry Andric ArgAttrs[IRArgs.first] = llvm::AttributeSet::get(getLLVMContext(), Attrs);
2670b60736ecSDimitry Andric }
2671b60736ecSDimitry Andric
267206d4ba38SDimitry Andric unsigned ArgNo = 0;
267306d4ba38SDimitry Andric for (CGFunctionInfo::const_arg_iterator I = FI.arg_begin(),
267406d4ba38SDimitry Andric E = FI.arg_end();
267506d4ba38SDimitry Andric I != E; ++I, ++ArgNo) {
267606d4ba38SDimitry Andric QualType ParamType = I->type;
267706d4ba38SDimitry Andric const ABIArgInfo &AI = I->info;
26786f8fc217SDimitry Andric llvm::AttrBuilder Attrs(getLLVMContext());
267913cc256eSDimitry Andric
268006d4ba38SDimitry Andric // Add attribute for padding argument, if necessary.
268106d4ba38SDimitry Andric if (IRFunctionArgs.hasPaddingArg(ArgNo)) {
2682583e75ccSDimitry Andric if (AI.getPaddingInReg()) {
2683583e75ccSDimitry Andric ArgAttrs[IRFunctionArgs.getPaddingArgNo(ArgNo)] =
2684583e75ccSDimitry Andric llvm::AttributeSet::get(
2685583e75ccSDimitry Andric getLLVMContext(),
26866f8fc217SDimitry Andric llvm::AttrBuilder(getLLVMContext()).addAttribute(llvm::Attribute::InReg));
2687583e75ccSDimitry Andric }
268813cc256eSDimitry Andric }
2689ec2b103cSEd Schouten
2690344a3780SDimitry Andric // Decide whether the argument we're handling could be partially undef
2691145449b1SDimitry Andric if (CodeGenOpts.EnableNoundefAttrs &&
26926f8fc217SDimitry Andric DetermineNoUndef(ParamType, getTypes(), DL, AI)) {
2693344a3780SDimitry Andric Attrs.addAttribute(llvm::Attribute::NoUndef);
26946f8fc217SDimitry Andric }
2695344a3780SDimitry Andric
269611d2b2d2SRoman Divacky // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
269711d2b2d2SRoman Divacky // have the corresponding parameter variable. It doesn't make
2698bca07a45SDimitry Andric // sense to do it here because parameters are so messed up.
2699ec2b103cSEd Schouten switch (AI.getKind()) {
27003d1dcd9bSDimitry Andric case ABIArgInfo::Extend:
270148675466SDimitry Andric if (AI.isSignExt())
27025e20cdd8SDimitry Andric Attrs.addAttribute(llvm::Attribute::SExt);
27035e20cdd8SDimitry Andric else
2704809500fcSDimitry Andric Attrs.addAttribute(llvm::Attribute::ZExt);
2705e3b55780SDimitry Andric [[fallthrough]];
270606d4ba38SDimitry Andric case ABIArgInfo::Direct:
270706d4ba38SDimitry Andric if (ArgNo == 0 && FI.isChainCall())
270806d4ba38SDimitry Andric Attrs.addAttribute(llvm::Attribute::Nest);
270906d4ba38SDimitry Andric else if (AI.getInReg())
2710809500fcSDimitry Andric Attrs.addAttribute(llvm::Attribute::InReg);
2711344a3780SDimitry Andric Attrs.addStackAlignmentAttr(llvm::MaybeAlign(AI.getDirectAlign()));
271206d4ba38SDimitry Andric
27137fa27ce4SDimitry Andric if (canApplyNoFPClass(AI, ParamType, false))
27147fa27ce4SDimitry Andric Attrs.addNoFPClassAttr(getNoFPClassTestMask(getLangOpts()));
27157fa27ce4SDimitry Andric break;
271645b53394SDimitry Andric case ABIArgInfo::Indirect: {
271713cc256eSDimitry Andric if (AI.getInReg())
2718809500fcSDimitry Andric Attrs.addAttribute(llvm::Attribute::InReg);
27194c8b2481SRoman Divacky
272013cc256eSDimitry Andric if (AI.getIndirectByVal())
272122989816SDimitry Andric Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType));
272213cc256eSDimitry Andric
2723b60736ecSDimitry Andric auto *Decl = ParamType->getAsRecordDecl();
2724b60736ecSDimitry Andric if (CodeGenOpts.PassByValueIsNoAlias && Decl &&
2725b1c73532SDimitry Andric Decl->getArgPassingRestrictions() ==
2726b1c73532SDimitry Andric RecordArgPassingKind::CanPassInRegs)
2727b60736ecSDimitry Andric // When calling the function, the pointer passed in will be the only
2728b60736ecSDimitry Andric // reference to the underlying object. Mark it accordingly.
2729b60736ecSDimitry Andric Attrs.addAttribute(llvm::Attribute::NoAlias);
2730b60736ecSDimitry Andric
2731b60736ecSDimitry Andric // TODO: We could add the byref attribute if not byval, but it would
2732b60736ecSDimitry Andric // require updating many testcases.
2733b60736ecSDimitry Andric
273445b53394SDimitry Andric CharUnits Align = AI.getIndirectAlign();
273545b53394SDimitry Andric
273645b53394SDimitry Andric // In a byval argument, it is important that the required
273745b53394SDimitry Andric // alignment of the type is honored, as LLVM might be creating a
273845b53394SDimitry Andric // *new* stack object, and needs to know what alignment to give
273945b53394SDimitry Andric // it. (Sometimes it can deduce a sensible alignment on its own,
274045b53394SDimitry Andric // but not if clang decides it must emit a packed struct, or the
274145b53394SDimitry Andric // user specifies increased alignment requirements.)
274245b53394SDimitry Andric //
274345b53394SDimitry Andric // This is different from indirect *not* byval, where the object
274445b53394SDimitry Andric // exists already, and the align attribute is purely
274545b53394SDimitry Andric // informative.
274645b53394SDimitry Andric assert(!Align.isZero());
274745b53394SDimitry Andric
274845b53394SDimitry Andric // For now, only add this when we have a byval argument.
274945b53394SDimitry Andric // TODO: be less lazy about updating test cases.
275045b53394SDimitry Andric if (AI.getIndirectByVal())
275145b53394SDimitry Andric Attrs.addAlignmentAttr(Align.getQuantity());
275213cc256eSDimitry Andric
2753ec2b103cSEd Schouten // byval disables readnone and readonly.
2754e3b55780SDimitry Andric AddPotentialArgAccess();
2755b60736ecSDimitry Andric break;
2756b60736ecSDimitry Andric }
2757b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased: {
2758b60736ecSDimitry Andric CharUnits Align = AI.getIndirectAlign();
2759b60736ecSDimitry Andric Attrs.addByRefAttr(getTypes().ConvertTypeForMem(ParamType));
2760b60736ecSDimitry Andric Attrs.addAlignmentAttr(Align.getQuantity());
2761ec2b103cSEd Schouten break;
276245b53394SDimitry Andric }
2763ec2b103cSEd Schouten case ABIArgInfo::Ignore:
276406d4ba38SDimitry Andric case ABIArgInfo::Expand:
27652b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand:
27662b6b257fSDimitry Andric break;
2767ec2b103cSEd Schouten
27689f4dbff6SDimitry Andric case ABIArgInfo::InAlloca:
27699f4dbff6SDimitry Andric // inalloca disables readnone and readonly.
2770e3b55780SDimitry Andric AddPotentialArgAccess();
27719f4dbff6SDimitry Andric continue;
2772ec2b103cSEd Schouten }
2773ec2b103cSEd Schouten
27749f4dbff6SDimitry Andric if (const auto *RefTy = ParamType->getAs<ReferenceType>()) {
27759f4dbff6SDimitry Andric QualType PTy = RefTy->getPointeeType();
27769f4dbff6SDimitry Andric if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
2777cfca06d7SDimitry Andric Attrs.addDereferenceableAttr(
2778cfca06d7SDimitry Andric getMinimumObjectSize(PTy).getQuantity());
2779e3b55780SDimitry Andric if (getTypes().getTargetAddressSpace(PTy) == 0 &&
278048675466SDimitry Andric !CodeGenOpts.NullPointerIsValid)
27819f4dbff6SDimitry Andric Attrs.addAttribute(llvm::Attribute::NonNull);
2782cfca06d7SDimitry Andric if (PTy->isObjectType()) {
2783cfca06d7SDimitry Andric llvm::Align Alignment =
2784cfca06d7SDimitry Andric getNaturalPointeeTypeAlignment(ParamType).getAsAlign();
2785cfca06d7SDimitry Andric Attrs.addAlignmentAttr(Alignment);
2786cfca06d7SDimitry Andric }
27879f4dbff6SDimitry Andric }
27889f4dbff6SDimitry Andric
2789145449b1SDimitry Andric // From OpenCL spec v3.0.10 section 6.3.5 Alignment of Types:
2790145449b1SDimitry Andric // > For arguments to a __kernel function declared to be a pointer to a
2791145449b1SDimitry Andric // > data type, the OpenCL compiler can assume that the pointee is always
2792145449b1SDimitry Andric // > appropriately aligned as required by the data type.
2793145449b1SDimitry Andric if (TargetDecl && TargetDecl->hasAttr<OpenCLKernelAttr>() &&
2794145449b1SDimitry Andric ParamType->isPointerType()) {
2795145449b1SDimitry Andric QualType PTy = ParamType->getPointeeType();
2796145449b1SDimitry Andric if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) {
2797145449b1SDimitry Andric llvm::Align Alignment =
2798145449b1SDimitry Andric getNaturalPointeeTypeAlignment(ParamType).getAsAlign();
2799145449b1SDimitry Andric Attrs.addAlignmentAttr(Alignment);
2800145449b1SDimitry Andric }
2801145449b1SDimitry Andric }
2802145449b1SDimitry Andric
28032b6b257fSDimitry Andric switch (FI.getExtParameterInfo(ArgNo).getABI()) {
28042b6b257fSDimitry Andric case ParameterABI::Ordinary:
28052b6b257fSDimitry Andric break;
28062b6b257fSDimitry Andric
28072b6b257fSDimitry Andric case ParameterABI::SwiftIndirectResult: {
28082b6b257fSDimitry Andric // Add 'sret' if we haven't already used it for something, but
28092b6b257fSDimitry Andric // only if the result is void.
28102b6b257fSDimitry Andric if (!hasUsedSRet && RetTy->isVoidType()) {
2811b60736ecSDimitry Andric Attrs.addStructRetAttr(getTypes().ConvertTypeForMem(ParamType));
28122b6b257fSDimitry Andric hasUsedSRet = true;
28132b6b257fSDimitry Andric }
28142b6b257fSDimitry Andric
28152b6b257fSDimitry Andric // Add 'noalias' in either case.
28162b6b257fSDimitry Andric Attrs.addAttribute(llvm::Attribute::NoAlias);
28172b6b257fSDimitry Andric
28182b6b257fSDimitry Andric // Add 'dereferenceable' and 'alignment'.
28192b6b257fSDimitry Andric auto PTy = ParamType->getPointeeType();
28202b6b257fSDimitry Andric if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) {
28212b6b257fSDimitry Andric auto info = getContext().getTypeInfoInChars(PTy);
2822b60736ecSDimitry Andric Attrs.addDereferenceableAttr(info.Width.getQuantity());
2823b60736ecSDimitry Andric Attrs.addAlignmentAttr(info.Align.getAsAlign());
28242b6b257fSDimitry Andric }
28252b6b257fSDimitry Andric break;
28262b6b257fSDimitry Andric }
28272b6b257fSDimitry Andric
28282b6b257fSDimitry Andric case ParameterABI::SwiftErrorResult:
28292b6b257fSDimitry Andric Attrs.addAttribute(llvm::Attribute::SwiftError);
28302b6b257fSDimitry Andric break;
28312b6b257fSDimitry Andric
28322b6b257fSDimitry Andric case ParameterABI::SwiftContext:
28332b6b257fSDimitry Andric Attrs.addAttribute(llvm::Attribute::SwiftSelf);
28342b6b257fSDimitry Andric break;
2835344a3780SDimitry Andric
2836344a3780SDimitry Andric case ParameterABI::SwiftAsyncContext:
2837344a3780SDimitry Andric Attrs.addAttribute(llvm::Attribute::SwiftAsync);
2838344a3780SDimitry Andric break;
28392b6b257fSDimitry Andric }
28402b6b257fSDimitry Andric
2841461a67faSDimitry Andric if (FI.getExtParameterInfo(ArgNo).isNoEscape())
2842461a67faSDimitry Andric Attrs.addAttribute(llvm::Attribute::NoCapture);
2843461a67faSDimitry Andric
284406d4ba38SDimitry Andric if (Attrs.hasAttributes()) {
284506d4ba38SDimitry Andric unsigned FirstIRArg, NumIRArgs;
284606d4ba38SDimitry Andric std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
284706d4ba38SDimitry Andric for (unsigned i = 0; i < NumIRArgs; i++)
28486f8fc217SDimitry Andric ArgAttrs[FirstIRArg + i] = ArgAttrs[FirstIRArg + i].addAttributes(
28496f8fc217SDimitry Andric getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), Attrs));
2850ec2b103cSEd Schouten }
28519f4dbff6SDimitry Andric }
285206d4ba38SDimitry Andric assert(ArgNo == FI.arg_size());
28539f4dbff6SDimitry Andric
2854583e75ccSDimitry Andric AttrList = llvm::AttributeList::get(
2855583e75ccSDimitry Andric getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), FuncAttrs),
2856583e75ccSDimitry Andric llvm::AttributeSet::get(getLLVMContext(), RetAttrs), ArgAttrs);
2857ec2b103cSEd Schouten }
2858ec2b103cSEd Schouten
285901af97d3SDimitry Andric /// An argument came in as a promoted argument; demote it back to its
286001af97d3SDimitry Andric /// declared type.
emitArgumentDemotion(CodeGenFunction & CGF,const VarDecl * var,llvm::Value * value)286101af97d3SDimitry Andric static llvm::Value *emitArgumentDemotion(CodeGenFunction &CGF,
286201af97d3SDimitry Andric const VarDecl *var,
286301af97d3SDimitry Andric llvm::Value *value) {
286436981b17SDimitry Andric llvm::Type *varType = CGF.ConvertType(var->getType());
286501af97d3SDimitry Andric
286601af97d3SDimitry Andric // This can happen with promotions that actually don't change the
286701af97d3SDimitry Andric // underlying type, like the enum promotions.
286801af97d3SDimitry Andric if (value->getType() == varType) return value;
286901af97d3SDimitry Andric
287001af97d3SDimitry Andric assert((varType->isIntegerTy() || varType->isFloatingPointTy())
287101af97d3SDimitry Andric && "unexpected promotion type");
287201af97d3SDimitry Andric
287301af97d3SDimitry Andric if (isa<llvm::IntegerType>(varType))
287401af97d3SDimitry Andric return CGF.Builder.CreateTrunc(value, varType, "arg.unpromote");
287501af97d3SDimitry Andric
287601af97d3SDimitry Andric return CGF.Builder.CreateFPCast(value, varType, "arg.unpromote");
287701af97d3SDimitry Andric }
287801af97d3SDimitry Andric
287906d4ba38SDimitry Andric /// Returns the attribute (either parameter attribute, or function
288006d4ba38SDimitry Andric /// attribute), which declares argument ArgNo to be non-null.
getNonNullAttr(const Decl * FD,const ParmVarDecl * PVD,QualType ArgType,unsigned ArgNo)288106d4ba38SDimitry Andric static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD,
288206d4ba38SDimitry Andric QualType ArgType, unsigned ArgNo) {
288306d4ba38SDimitry Andric // FIXME: __attribute__((nonnull)) can also be applied to:
288406d4ba38SDimitry Andric // - references to pointers, where the pointee is known to be
288506d4ba38SDimitry Andric // nonnull (apparently a Clang extension)
288606d4ba38SDimitry Andric // - transparent unions containing pointers
288706d4ba38SDimitry Andric // In the former case, LLVM IR cannot represent the constraint. In
288806d4ba38SDimitry Andric // the latter case, we have no guarantee that the transparent union
288906d4ba38SDimitry Andric // is in fact passed as a pointer.
289006d4ba38SDimitry Andric if (!ArgType->isAnyPointerType() && !ArgType->isBlockPointerType())
289106d4ba38SDimitry Andric return nullptr;
289206d4ba38SDimitry Andric // First, check attribute on parameter itself.
289306d4ba38SDimitry Andric if (PVD) {
289406d4ba38SDimitry Andric if (auto ParmNNAttr = PVD->getAttr<NonNullAttr>())
289506d4ba38SDimitry Andric return ParmNNAttr;
289606d4ba38SDimitry Andric }
289706d4ba38SDimitry Andric // Check function attributes.
289806d4ba38SDimitry Andric if (!FD)
289906d4ba38SDimitry Andric return nullptr;
290006d4ba38SDimitry Andric for (const auto *NNAttr : FD->specific_attrs<NonNullAttr>()) {
290106d4ba38SDimitry Andric if (NNAttr->isNonNull(ArgNo))
290206d4ba38SDimitry Andric return NNAttr;
290306d4ba38SDimitry Andric }
290406d4ba38SDimitry Andric return nullptr;
290506d4ba38SDimitry Andric }
290606d4ba38SDimitry Andric
29072b6b257fSDimitry Andric namespace {
29082b6b257fSDimitry Andric struct CopyBackSwiftError final : EHScopeStack::Cleanup {
29092b6b257fSDimitry Andric Address Temp;
29102b6b257fSDimitry Andric Address Arg;
CopyBackSwiftError__anon748148590b11::CopyBackSwiftError29112b6b257fSDimitry Andric CopyBackSwiftError(Address temp, Address arg) : Temp(temp), Arg(arg) {}
Emit__anon748148590b11::CopyBackSwiftError29122b6b257fSDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
29132b6b257fSDimitry Andric llvm::Value *errorValue = CGF.Builder.CreateLoad(Temp);
29142b6b257fSDimitry Andric CGF.Builder.CreateStore(errorValue, Arg);
29152b6b257fSDimitry Andric }
29162b6b257fSDimitry Andric };
29172b6b257fSDimitry Andric }
29182b6b257fSDimitry Andric
EmitFunctionProlog(const CGFunctionInfo & FI,llvm::Function * Fn,const FunctionArgList & Args)2919ec2b103cSEd Schouten void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
2920ec2b103cSEd Schouten llvm::Function *Fn,
2921ec2b103cSEd Schouten const FunctionArgList &Args) {
292206d4ba38SDimitry Andric if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>())
292306d4ba38SDimitry Andric // Naked functions don't have prologues.
292406d4ba38SDimitry Andric return;
292506d4ba38SDimitry Andric
29264c8b2481SRoman Divacky // If this is an implicit-return-zero function, go ahead and
29274c8b2481SRoman Divacky // initialize the return value. TODO: it might be nice to have
29284c8b2481SRoman Divacky // a more general mechanism for this that didn't require synthesized
29294c8b2481SRoman Divacky // return statements.
29306a037251SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl)) {
29314c8b2481SRoman Divacky if (FD->hasImplicitReturnZero()) {
29329f4dbff6SDimitry Andric QualType RetTy = FD->getReturnType().getUnqualifiedType();
293336981b17SDimitry Andric llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy);
29344c8b2481SRoman Divacky llvm::Constant* Zero = llvm::Constant::getNullValue(LLVMTy);
29354c8b2481SRoman Divacky Builder.CreateStore(Zero, ReturnValue);
29364c8b2481SRoman Divacky }
29374c8b2481SRoman Divacky }
29384c8b2481SRoman Divacky
2939ec2b103cSEd Schouten // FIXME: We no longer need the types from FunctionArgList; lift up and
2940ec2b103cSEd Schouten // simplify.
2941ec2b103cSEd Schouten
294206d4ba38SDimitry Andric ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), FI);
2943cfca06d7SDimitry Andric assert(Fn->arg_size() == IRFunctionArgs.totalIRArgs());
2944ec2b103cSEd Schouten
29459f4dbff6SDimitry Andric // If we're using inalloca, all the memory arguments are GEPs off of the last
29469f4dbff6SDimitry Andric // parameter, which is a pointer to the complete memory area.
294745b53394SDimitry Andric Address ArgStruct = Address::invalid();
29487fa27ce4SDimitry Andric if (IRFunctionArgs.hasInallocaArg())
2949cfca06d7SDimitry Andric ArgStruct = Address(Fn->getArg(IRFunctionArgs.getInallocaArgNo()),
2950145449b1SDimitry Andric FI.getArgStruct(), FI.getArgStructAlignment());
295145b53394SDimitry Andric
295206d4ba38SDimitry Andric // Name the struct return parameter.
295306d4ba38SDimitry Andric if (IRFunctionArgs.hasSRetArg()) {
2954cfca06d7SDimitry Andric auto AI = Fn->getArg(IRFunctionArgs.getSRetArgNo());
29559f4dbff6SDimitry Andric AI->setName("agg.result");
2956583e75ccSDimitry Andric AI->addAttr(llvm::Attribute::NoAlias);
29579f4dbff6SDimitry Andric }
29589f4dbff6SDimitry Andric
29599f4dbff6SDimitry Andric // Track if we received the parameter as a pointer (indirect, byval, or
29609f4dbff6SDimitry Andric // inalloca). If already have a pointer, EmitParmDecl doesn't need to copy it
29619f4dbff6SDimitry Andric // into a local alloca for us.
296245b53394SDimitry Andric SmallVector<ParamValue, 16> ArgVals;
29639f4dbff6SDimitry Andric ArgVals.reserve(Args.size());
29649f4dbff6SDimitry Andric
29659f4dbff6SDimitry Andric // Create a pointer value for every parameter declaration. This usually
29669f4dbff6SDimitry Andric // entails copying one or more LLVM IR arguments into an alloca. Don't push
29679f4dbff6SDimitry Andric // any cleanups or do anything that might unwind. We do that separately, so
29689f4dbff6SDimitry Andric // we can push the cleanups in the correct order for the ABI.
2969ec2b103cSEd Schouten assert(FI.arg_size() == Args.size() &&
2970ec2b103cSEd Schouten "Mismatch between function signature & arguments.");
297106d4ba38SDimitry Andric unsigned ArgNo = 0;
2972ec2b103cSEd Schouten CGFunctionInfo::const_arg_iterator info_it = FI.arg_begin();
2973ec2b103cSEd Schouten for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end();
297401af97d3SDimitry Andric i != e; ++i, ++info_it, ++ArgNo) {
297501af97d3SDimitry Andric const VarDecl *Arg = *i;
2976ec2b103cSEd Schouten const ABIArgInfo &ArgI = info_it->info;
2977ec2b103cSEd Schouten
297801af97d3SDimitry Andric bool isPromoted =
297901af97d3SDimitry Andric isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted();
298048675466SDimitry Andric // We are converting from ABIArgInfo type to VarDecl type directly, unless
298148675466SDimitry Andric // the parameter is promoted. In this case we convert to
298248675466SDimitry Andric // CGFunctionInfo::ArgInfo type with subsequent argument demotion.
298348675466SDimitry Andric QualType Ty = isPromoted ? info_it->type : Arg->getType();
298448675466SDimitry Andric assert(hasScalarEvaluationKind(Ty) ==
298548675466SDimitry Andric hasScalarEvaluationKind(Arg->getType()));
298601af97d3SDimitry Andric
298706d4ba38SDimitry Andric unsigned FirstIRArg, NumIRArgs;
298806d4ba38SDimitry Andric std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
298913cc256eSDimitry Andric
2990ec2b103cSEd Schouten switch (ArgI.getKind()) {
29919f4dbff6SDimitry Andric case ABIArgInfo::InAlloca: {
299206d4ba38SDimitry Andric assert(NumIRArgs == 0);
299345b53394SDimitry Andric auto FieldIndex = ArgI.getInAllocaFieldIndex();
299422989816SDimitry Andric Address V =
299522989816SDimitry Andric Builder.CreateStructGEP(ArgStruct, FieldIndex, Arg->getName());
2996cfca06d7SDimitry Andric if (ArgI.getInAllocaIndirect())
2997145449b1SDimitry Andric V = Address(Builder.CreateLoad(V), ConvertTypeForMem(Ty),
2998cfca06d7SDimitry Andric getContext().getTypeAlignInChars(Ty));
299945b53394SDimitry Andric ArgVals.push_back(ParamValue::forIndirect(V));
300006d4ba38SDimitry Andric break;
30019f4dbff6SDimitry Andric }
30029f4dbff6SDimitry Andric
3003b60736ecSDimitry Andric case ABIArgInfo::Indirect:
3004b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased: {
300506d4ba38SDimitry Andric assert(NumIRArgs == 1);
3006ac9a064cSDimitry Andric Address ParamAddr = makeNaturalAddressForPointer(
3007ac9a064cSDimitry Andric Fn->getArg(FirstIRArg), Ty, ArgI.getIndirectAlign(), false, nullptr,
3008ac9a064cSDimitry Andric nullptr, KnownNonNull);
3009bca07a45SDimitry Andric
3010809500fcSDimitry Andric if (!hasScalarEvaluationKind(Ty)) {
3011bca07a45SDimitry Andric // Aggregates and complex variables are accessed by reference. All we
3012b60736ecSDimitry Andric // need to do is realign the value, if requested. Also, if the address
3013b60736ecSDimitry Andric // may be aliased, copy it to ensure that the parameter variable is
3014b60736ecSDimitry Andric // mutable and has a unique adress, as C requires.
3015b60736ecSDimitry Andric if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) {
3016ac9a064cSDimitry Andric RawAddress AlignedTemp = CreateMemTemp(Ty, "coerce");
3017bca07a45SDimitry Andric
3018bca07a45SDimitry Andric // Copy from the incoming argument pointer to the temporary with the
3019bca07a45SDimitry Andric // appropriate alignment.
3020bca07a45SDimitry Andric //
3021bca07a45SDimitry Andric // FIXME: We should have a common utility for generating an aggregate
3022bca07a45SDimitry Andric // copy.
3023bca07a45SDimitry Andric CharUnits Size = getContext().getTypeSizeInChars(Ty);
3024cfca06d7SDimitry Andric Builder.CreateMemCpy(
3025cfca06d7SDimitry Andric AlignedTemp.getPointer(), AlignedTemp.getAlignment().getAsAlign(),
3026ac9a064cSDimitry Andric ParamAddr.emitRawPointer(*this),
3027ac9a064cSDimitry Andric ParamAddr.getAlignment().getAsAlign(),
3028cfca06d7SDimitry Andric llvm::ConstantInt::get(IntPtrTy, Size.getQuantity()));
3029ac9a064cSDimitry Andric ParamAddr = AlignedTemp;
3030bca07a45SDimitry Andric }
3031ac9a064cSDimitry Andric ArgVals.push_back(ParamValue::forIndirect(ParamAddr));
3032ec2b103cSEd Schouten } else {
3033ec2b103cSEd Schouten // Load scalar value from indirect argument.
303445b53394SDimitry Andric llvm::Value *V =
3035676fbe81SDimitry Andric EmitLoadOfScalar(ParamAddr, false, Ty, Arg->getBeginLoc());
303601af97d3SDimitry Andric
303701af97d3SDimitry Andric if (isPromoted)
303801af97d3SDimitry Andric V = emitArgumentDemotion(*this, Arg, V);
303945b53394SDimitry Andric ArgVals.push_back(ParamValue::forDirect(V));
3040ec2b103cSEd Schouten }
3041ec2b103cSEd Schouten break;
3042ec2b103cSEd Schouten }
3043ec2b103cSEd Schouten
304470b4596dSEd Schouten case ABIArgInfo::Extend:
3045ec2b103cSEd Schouten case ABIArgInfo::Direct: {
3046cfca06d7SDimitry Andric auto AI = Fn->getArg(FirstIRArg);
3047cfca06d7SDimitry Andric llvm::Type *LTy = ConvertType(Arg->getType());
3048dbe13110SDimitry Andric
3049cfca06d7SDimitry Andric // Prepare parameter attributes. So far, only attributes for pointer
3050cfca06d7SDimitry Andric // parameters are prepared. See
3051cfca06d7SDimitry Andric // http://llvm.org/docs/LangRef.html#paramattrs.
3052cfca06d7SDimitry Andric if (ArgI.getDirectOffset() == 0 && LTy->isPointerTy() &&
3053cfca06d7SDimitry Andric ArgI.getCoerceToType()->isPointerTy()) {
305406d4ba38SDimitry Andric assert(NumIRArgs == 1);
30553d1dcd9bSDimitry Andric
30569f4dbff6SDimitry Andric if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
3057cfca06d7SDimitry Andric // Set `nonnull` attribute if any.
305806d4ba38SDimitry Andric if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(),
305948675466SDimitry Andric PVD->getFunctionScopeIndex()) &&
306048675466SDimitry Andric !CGM.getCodeGenOpts().NullPointerIsValid)
3061583e75ccSDimitry Andric AI->addAttr(llvm::Attribute::NonNull);
30629f4dbff6SDimitry Andric
30639f4dbff6SDimitry Andric QualType OTy = PVD->getOriginalType();
30649f4dbff6SDimitry Andric if (const auto *ArrTy =
30659f4dbff6SDimitry Andric getContext().getAsConstantArrayType(OTy)) {
30669f4dbff6SDimitry Andric // A C99 array parameter declaration with the static keyword also
30679f4dbff6SDimitry Andric // indicates dereferenceability, and if the size is constant we can
30689f4dbff6SDimitry Andric // use the dereferenceable attribute (which requires the size in
30699f4dbff6SDimitry Andric // bytes).
3070b1c73532SDimitry Andric if (ArrTy->getSizeModifier() == ArraySizeModifier::Static) {
30719f4dbff6SDimitry Andric QualType ETy = ArrTy->getElementType();
3072b60736ecSDimitry Andric llvm::Align Alignment =
3073b60736ecSDimitry Andric CGM.getNaturalTypeAlignment(ETy).getAsAlign();
30746f8fc217SDimitry Andric AI->addAttrs(llvm::AttrBuilder(getLLVMContext()).addAlignmentAttr(Alignment));
3075ac9a064cSDimitry Andric uint64_t ArrSize = ArrTy->getZExtSize();
30769f4dbff6SDimitry Andric if (!ETy->isIncompleteType() && ETy->isConstantSizeType() &&
30779f4dbff6SDimitry Andric ArrSize) {
30786f8fc217SDimitry Andric llvm::AttrBuilder Attrs(getLLVMContext());
30799f4dbff6SDimitry Andric Attrs.addDereferenceableAttr(
3080cfca06d7SDimitry Andric getContext().getTypeSizeInChars(ETy).getQuantity() *
3081cfca06d7SDimitry Andric ArrSize);
3082583e75ccSDimitry Andric AI->addAttrs(Attrs);
3083cfca06d7SDimitry Andric } else if (getContext().getTargetInfo().getNullPointerValue(
3084cfca06d7SDimitry Andric ETy.getAddressSpace()) == 0 &&
308548675466SDimitry Andric !CGM.getCodeGenOpts().NullPointerIsValid) {
3086583e75ccSDimitry Andric AI->addAttr(llvm::Attribute::NonNull);
30879f4dbff6SDimitry Andric }
30889f4dbff6SDimitry Andric }
30899f4dbff6SDimitry Andric } else if (const auto *ArrTy =
30909f4dbff6SDimitry Andric getContext().getAsVariableArrayType(OTy)) {
30919f4dbff6SDimitry Andric // For C99 VLAs with the static keyword, we don't know the size so
30929f4dbff6SDimitry Andric // we can't use the dereferenceable attribute, but in addrspace(0)
30939f4dbff6SDimitry Andric // we know that it must be nonnull.
3094b1c73532SDimitry Andric if (ArrTy->getSizeModifier() == ArraySizeModifier::Static) {
3095b60736ecSDimitry Andric QualType ETy = ArrTy->getElementType();
3096b60736ecSDimitry Andric llvm::Align Alignment =
3097b60736ecSDimitry Andric CGM.getNaturalTypeAlignment(ETy).getAsAlign();
30986f8fc217SDimitry Andric AI->addAttrs(llvm::AttrBuilder(getLLVMContext()).addAlignmentAttr(Alignment));
3099e3b55780SDimitry Andric if (!getTypes().getTargetAddressSpace(ETy) &&
310048675466SDimitry Andric !CGM.getCodeGenOpts().NullPointerIsValid)
3101583e75ccSDimitry Andric AI->addAttr(llvm::Attribute::NonNull);
31029f4dbff6SDimitry Andric }
3103b60736ecSDimitry Andric }
310406d4ba38SDimitry Andric
3105cfca06d7SDimitry Andric // Set `align` attribute if any.
310606d4ba38SDimitry Andric const auto *AVAttr = PVD->getAttr<AlignValueAttr>();
310706d4ba38SDimitry Andric if (!AVAttr)
3108e3b55780SDimitry Andric if (const auto *TOTy = OTy->getAs<TypedefType>())
310906d4ba38SDimitry Andric AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>();
3110676fbe81SDimitry Andric if (AVAttr && !SanOpts.has(SanitizerKind::Alignment)) {
3111676fbe81SDimitry Andric // If alignment-assumption sanitizer is enabled, we do *not* add
3112676fbe81SDimitry Andric // alignment attribute here, but emit normal alignment assumption,
3113676fbe81SDimitry Andric // so the UBSAN check could function.
311406d4ba38SDimitry Andric llvm::ConstantInt *AlignmentCI =
3115cfca06d7SDimitry Andric cast<llvm::ConstantInt>(EmitScalarExpr(AVAttr->getAlignment()));
3116c0981da4SDimitry Andric uint64_t AlignmentInt =
3117cfca06d7SDimitry Andric AlignmentCI->getLimitedValue(llvm::Value::MaximumAlignment);
3118cfca06d7SDimitry Andric if (AI->getParamAlign().valueOrOne() < AlignmentInt) {
3119cfca06d7SDimitry Andric AI->removeAttr(llvm::Attribute::AttrKind::Alignment);
31206f8fc217SDimitry Andric AI->addAttrs(llvm::AttrBuilder(getLLVMContext()).addAlignmentAttr(
3121cfca06d7SDimitry Andric llvm::Align(AlignmentInt)));
3122cfca06d7SDimitry Andric }
312306d4ba38SDimitry Andric }
31249f4dbff6SDimitry Andric }
31259f4dbff6SDimitry Andric
3126cfca06d7SDimitry Andric // Set 'noalias' if an argument type has the `restrict` qualifier.
312711d2b2d2SRoman Divacky if (Arg->getType().isRestrictQualified())
3128583e75ccSDimitry Andric AI->addAttr(llvm::Attribute::NoAlias);
3129cfca06d7SDimitry Andric }
3130cfca06d7SDimitry Andric
3131cfca06d7SDimitry Andric // Prepare the argument value. If we have the trivial case, handle it
3132cfca06d7SDimitry Andric // with no muss and fuss.
3133cfca06d7SDimitry Andric if (!isa<llvm::StructType>(ArgI.getCoerceToType()) &&
3134cfca06d7SDimitry Andric ArgI.getCoerceToType() == ConvertType(Ty) &&
3135cfca06d7SDimitry Andric ArgI.getDirectOffset() == 0) {
3136cfca06d7SDimitry Andric assert(NumIRArgs == 1);
313711d2b2d2SRoman Divacky
31382b6b257fSDimitry Andric // LLVM expects swifterror parameters to be used in very restricted
31392b6b257fSDimitry Andric // ways. Copy the value into a less-restricted temporary.
3140cfca06d7SDimitry Andric llvm::Value *V = AI;
31412b6b257fSDimitry Andric if (FI.getExtParameterInfo(ArgNo).getABI()
31422b6b257fSDimitry Andric == ParameterABI::SwiftErrorResult) {
31432b6b257fSDimitry Andric QualType pointeeTy = Ty->getPointeeType();
31442b6b257fSDimitry Andric assert(pointeeTy->isPointerType());
3145ac9a064cSDimitry Andric RawAddress temp =
31462b6b257fSDimitry Andric CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp");
3147ac9a064cSDimitry Andric Address arg = makeNaturalAddressForPointer(
3148ac9a064cSDimitry Andric V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy));
31492b6b257fSDimitry Andric llvm::Value *incomingErrorValue = Builder.CreateLoad(arg);
31502b6b257fSDimitry Andric Builder.CreateStore(incomingErrorValue, temp);
31512b6b257fSDimitry Andric V = temp.getPointer();
31522b6b257fSDimitry Andric
31532b6b257fSDimitry Andric // Push a cleanup to copy the value back at the end of the function.
31542b6b257fSDimitry Andric // The convention does not guarantee that the value will be written
31552b6b257fSDimitry Andric // back if the function exits with an unwind exception.
31562b6b257fSDimitry Andric EHStack.pushCleanup<CopyBackSwiftError>(NormalCleanup, temp, arg);
31572b6b257fSDimitry Andric }
31582b6b257fSDimitry Andric
315936981b17SDimitry Andric // Ensure the argument is the correct type.
316036981b17SDimitry Andric if (V->getType() != ArgI.getCoerceToType())
316136981b17SDimitry Andric V = Builder.CreateBitCast(V, ArgI.getCoerceToType());
316236981b17SDimitry Andric
316301af97d3SDimitry Andric if (isPromoted)
316401af97d3SDimitry Andric V = emitArgumentDemotion(*this, Arg, V);
316501af97d3SDimitry Andric
3166809500fcSDimitry Andric // Because of merging of function types from multiple decls it is
3167809500fcSDimitry Andric // possible for the type of an argument to not match the corresponding
3168809500fcSDimitry Andric // type in the function type. Since we are codegening the callee
3169809500fcSDimitry Andric // in here, add a cast to the argument type.
3170809500fcSDimitry Andric llvm::Type *LTy = ConvertType(Arg->getType());
3171809500fcSDimitry Andric if (V->getType() != LTy)
3172809500fcSDimitry Andric V = Builder.CreateBitCast(V, LTy);
3173809500fcSDimitry Andric
317445b53394SDimitry Andric ArgVals.push_back(ParamValue::forDirect(V));
3175ec2b103cSEd Schouten break;
3176ec2b103cSEd Schouten }
3177ec2b103cSEd Schouten
3178b60736ecSDimitry Andric // VLST arguments are coerced to VLATs at the function boundary for
3179b60736ecSDimitry Andric // ABI consistency. If this is a VLST that was coerced to
3180b60736ecSDimitry Andric // a VLAT at the function boundary and the types match up, use
3181145449b1SDimitry Andric // llvm.vector.extract to convert back to the original VLST.
3182b60736ecSDimitry Andric if (auto *VecTyTo = dyn_cast<llvm::FixedVectorType>(ConvertType(Ty))) {
3183c0981da4SDimitry Andric llvm::Value *Coerced = Fn->getArg(FirstIRArg);
3184b60736ecSDimitry Andric if (auto *VecTyFrom =
3185b60736ecSDimitry Andric dyn_cast<llvm::ScalableVectorType>(Coerced->getType())) {
3186ac9a064cSDimitry Andric // If we are casting a scalable i1 predicate vector to a fixed i8
3187c0981da4SDimitry Andric // vector, bitcast the source and use a vector extract.
3188ac9a064cSDimitry Andric if (VecTyFrom->getElementType()->isIntegerTy(1) &&
3189ac9a064cSDimitry Andric VecTyFrom->getElementCount().isKnownMultipleOf(8) &&
3190c0981da4SDimitry Andric VecTyTo->getElementType() == Builder.getInt8Ty()) {
3191ac9a064cSDimitry Andric VecTyFrom = llvm::ScalableVectorType::get(
3192ac9a064cSDimitry Andric VecTyTo->getElementType(),
3193ac9a064cSDimitry Andric VecTyFrom->getElementCount().getKnownMinValue() / 8);
3194c0981da4SDimitry Andric Coerced = Builder.CreateBitCast(Coerced, VecTyFrom);
3195c0981da4SDimitry Andric }
3196b60736ecSDimitry Andric if (VecTyFrom->getElementType() == VecTyTo->getElementType()) {
3197b60736ecSDimitry Andric llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int64Ty);
3198b60736ecSDimitry Andric
3199b60736ecSDimitry Andric assert(NumIRArgs == 1);
3200b60736ecSDimitry Andric Coerced->setName(Arg->getName() + ".coerce");
3201b60736ecSDimitry Andric ArgVals.push_back(ParamValue::forDirect(Builder.CreateExtractVector(
32027fa27ce4SDimitry Andric VecTyTo, Coerced, Zero, "cast.fixed")));
3203b60736ecSDimitry Andric break;
3204b60736ecSDimitry Andric }
3205b60736ecSDimitry Andric }
3206b60736ecSDimitry Andric }
3207b60736ecSDimitry Andric
3208ac9a064cSDimitry Andric llvm::StructType *STy =
3209ac9a064cSDimitry Andric dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
3210ac9a064cSDimitry Andric if (ArgI.isDirect() && !ArgI.getCanBeFlattened() && STy &&
3211ac9a064cSDimitry Andric STy->getNumElements() > 1) {
3212ac9a064cSDimitry Andric [[maybe_unused]] llvm::TypeSize StructSize =
3213ac9a064cSDimitry Andric CGM.getDataLayout().getTypeAllocSize(STy);
3214ac9a064cSDimitry Andric [[maybe_unused]] llvm::TypeSize PtrElementSize =
3215ac9a064cSDimitry Andric CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(Ty));
3216ac9a064cSDimitry Andric if (STy->containsHomogeneousScalableVectorTypes()) {
3217ac9a064cSDimitry Andric assert(StructSize == PtrElementSize &&
3218ac9a064cSDimitry Andric "Only allow non-fractional movement of structure with"
3219ac9a064cSDimitry Andric "homogeneous scalable vector type");
3220ac9a064cSDimitry Andric
3221ac9a064cSDimitry Andric ArgVals.push_back(ParamValue::forDirect(AI));
3222ac9a064cSDimitry Andric break;
3223ac9a064cSDimitry Andric }
3224ac9a064cSDimitry Andric }
3225ac9a064cSDimitry Andric
322645b53394SDimitry Andric Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),
322745b53394SDimitry Andric Arg->getName());
32283d1dcd9bSDimitry Andric
322945b53394SDimitry Andric // Pointer to store into.
323045b53394SDimitry Andric Address Ptr = emitAddressAtOffset(*this, Alloca, ArgI);
32314ba67500SRoman Divacky
323206d4ba38SDimitry Andric // Fast-isel and the optimizer generally like scalar values better than
323306d4ba38SDimitry Andric // FCAs, so we flatten them if this is safe to do for this argument.
323406d4ba38SDimitry Andric if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy &&
323506d4ba38SDimitry Andric STy->getNumElements() > 1) {
32367fa27ce4SDimitry Andric llvm::TypeSize StructSize = CGM.getDataLayout().getTypeAllocSize(STy);
32377fa27ce4SDimitry Andric llvm::TypeSize PtrElementSize =
32387fa27ce4SDimitry Andric CGM.getDataLayout().getTypeAllocSize(Ptr.getElementType());
32397fa27ce4SDimitry Andric if (StructSize.isScalable()) {
32407fa27ce4SDimitry Andric assert(STy->containsHomogeneousScalableVectorTypes() &&
32417fa27ce4SDimitry Andric "ABI only supports structure with homogeneous scalable vector "
32427fa27ce4SDimitry Andric "type");
32437fa27ce4SDimitry Andric assert(StructSize == PtrElementSize &&
32447fa27ce4SDimitry Andric "Only allow non-fractional movement of structure with"
32457fa27ce4SDimitry Andric "homogeneous scalable vector type");
32467fa27ce4SDimitry Andric assert(STy->getNumElements() == NumIRArgs);
32477fa27ce4SDimitry Andric
32487fa27ce4SDimitry Andric llvm::Value *LoadedStructValue = llvm::PoisonValue::get(STy);
32497fa27ce4SDimitry Andric for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
32507fa27ce4SDimitry Andric auto *AI = Fn->getArg(FirstIRArg + i);
32517fa27ce4SDimitry Andric AI->setName(Arg->getName() + ".coerce" + Twine(i));
32527fa27ce4SDimitry Andric LoadedStructValue =
32537fa27ce4SDimitry Andric Builder.CreateInsertValue(LoadedStructValue, AI, i);
32547fa27ce4SDimitry Andric }
32557fa27ce4SDimitry Andric
32567fa27ce4SDimitry Andric Builder.CreateStore(LoadedStructValue, Ptr);
32577fa27ce4SDimitry Andric } else {
32587fa27ce4SDimitry Andric uint64_t SrcSize = StructSize.getFixedValue();
32597fa27ce4SDimitry Andric uint64_t DstSize = PtrElementSize.getFixedValue();
3260dbe13110SDimitry Andric
326145b53394SDimitry Andric Address AddrToStoreInto = Address::invalid();
3262dbe13110SDimitry Andric if (SrcSize <= DstSize) {
32637fa27ce4SDimitry Andric AddrToStoreInto = Ptr.withElementType(STy);
32644ba67500SRoman Divacky } else {
326545b53394SDimitry Andric AddrToStoreInto =
326645b53394SDimitry Andric CreateTempAlloca(STy, Alloca.getAlignment(), "coerce");
326745b53394SDimitry Andric }
3268dbe13110SDimitry Andric
326906d4ba38SDimitry Andric assert(STy->getNumElements() == NumIRArgs);
3270dbe13110SDimitry Andric for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
3271cfca06d7SDimitry Andric auto AI = Fn->getArg(FirstIRArg + i);
3272dbe13110SDimitry Andric AI->setName(Arg->getName() + ".coerce" + Twine(i));
327322989816SDimitry Andric Address EltPtr = Builder.CreateStructGEP(AddrToStoreInto, i);
327406d4ba38SDimitry Andric Builder.CreateStore(AI, EltPtr);
3275dbe13110SDimitry Andric }
3276dbe13110SDimitry Andric
327745b53394SDimitry Andric if (SrcSize > DstSize) {
327845b53394SDimitry Andric Builder.CreateMemCpy(Ptr, AddrToStoreInto, DstSize);
3279dbe13110SDimitry Andric }
32807fa27ce4SDimitry Andric }
3281dbe13110SDimitry Andric } else {
32824ba67500SRoman Divacky // Simple case, just do a coerced store of the argument into the alloca.
328306d4ba38SDimitry Andric assert(NumIRArgs == 1);
3284cfca06d7SDimitry Andric auto AI = Fn->getArg(FirstIRArg);
32854ba67500SRoman Divacky AI->setName(Arg->getName() + ".coerce");
32861de139fdSDimitry Andric CreateCoercedStore(
32871de139fdSDimitry Andric AI, Ptr,
32881de139fdSDimitry Andric llvm::TypeSize::getFixed(
32891de139fdSDimitry Andric getContext().getTypeSizeInChars(Ty).getQuantity() -
32901de139fdSDimitry Andric ArgI.getDirectOffset()),
32911de139fdSDimitry Andric /*DstIsVolatile=*/false);
32924ba67500SRoman Divacky }
32934ba67500SRoman Divacky
3294ec2b103cSEd Schouten // Match to what EmitParmDecl is expecting for this type.
3295809500fcSDimitry Andric if (CodeGenFunction::hasScalarEvaluationKind(Ty)) {
329645b53394SDimitry Andric llvm::Value *V =
3297676fbe81SDimitry Andric EmitLoadOfScalar(Alloca, false, Ty, Arg->getBeginLoc());
329801af97d3SDimitry Andric if (isPromoted)
329901af97d3SDimitry Andric V = emitArgumentDemotion(*this, Arg, V);
330045b53394SDimitry Andric ArgVals.push_back(ParamValue::forDirect(V));
33019f4dbff6SDimitry Andric } else {
330245b53394SDimitry Andric ArgVals.push_back(ParamValue::forIndirect(Alloca));
3303ec2b103cSEd Schouten }
330406d4ba38SDimitry Andric break;
3305ec2b103cSEd Schouten }
33063d1dcd9bSDimitry Andric
33072b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand: {
33082b6b257fSDimitry Andric // Reconstruct into a temporary.
33092b6b257fSDimitry Andric Address alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg));
33102b6b257fSDimitry Andric ArgVals.push_back(ParamValue::forIndirect(alloca));
33112b6b257fSDimitry Andric
33122b6b257fSDimitry Andric auto coercionType = ArgI.getCoerceAndExpandType();
33137fa27ce4SDimitry Andric alloca = alloca.withElementType(coercionType);
33142b6b257fSDimitry Andric
33152b6b257fSDimitry Andric unsigned argIndex = FirstIRArg;
33162b6b257fSDimitry Andric for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
33172b6b257fSDimitry Andric llvm::Type *eltType = coercionType->getElementType(i);
33182b6b257fSDimitry Andric if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType))
33192b6b257fSDimitry Andric continue;
33202b6b257fSDimitry Andric
332122989816SDimitry Andric auto eltAddr = Builder.CreateStructGEP(alloca, i);
3322cfca06d7SDimitry Andric auto elt = Fn->getArg(argIndex++);
33232b6b257fSDimitry Andric Builder.CreateStore(elt, eltAddr);
33242b6b257fSDimitry Andric }
33252b6b257fSDimitry Andric assert(argIndex == FirstIRArg + NumIRArgs);
33262b6b257fSDimitry Andric break;
33272b6b257fSDimitry Andric }
33282b6b257fSDimitry Andric
33293d1dcd9bSDimitry Andric case ABIArgInfo::Expand: {
33303d1dcd9bSDimitry Andric // If this structure was expanded into multiple arguments then
33313d1dcd9bSDimitry Andric // we need to create a temporary and reconstruct it from the
33323d1dcd9bSDimitry Andric // arguments.
333345b53394SDimitry Andric Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg));
333445b53394SDimitry Andric LValue LV = MakeAddrLValue(Alloca, Ty);
333545b53394SDimitry Andric ArgVals.push_back(ParamValue::forIndirect(Alloca));
33363d1dcd9bSDimitry Andric
3337cfca06d7SDimitry Andric auto FnArgIter = Fn->arg_begin() + FirstIRArg;
333806d4ba38SDimitry Andric ExpandTypeFromArgs(Ty, LV, FnArgIter);
3339cfca06d7SDimitry Andric assert(FnArgIter == Fn->arg_begin() + FirstIRArg + NumIRArgs);
334006d4ba38SDimitry Andric for (unsigned i = 0, e = NumIRArgs; i != e; ++i) {
3341cfca06d7SDimitry Andric auto AI = Fn->getArg(FirstIRArg + i);
334206d4ba38SDimitry Andric AI->setName(Arg->getName() + "." + Twine(i));
334306d4ba38SDimitry Andric }
334406d4ba38SDimitry Andric break;
33453d1dcd9bSDimitry Andric }
33463d1dcd9bSDimitry Andric
33473d1dcd9bSDimitry Andric case ABIArgInfo::Ignore:
334806d4ba38SDimitry Andric assert(NumIRArgs == 0);
33493d1dcd9bSDimitry Andric // Initialize the local variable appropriately.
33509f4dbff6SDimitry Andric if (!hasScalarEvaluationKind(Ty)) {
335145b53394SDimitry Andric ArgVals.push_back(ParamValue::forIndirect(CreateMemTemp(Ty)));
33529f4dbff6SDimitry Andric } else {
33539f4dbff6SDimitry Andric llvm::Value *U = llvm::UndefValue::get(ConvertType(Arg->getType()));
335445b53394SDimitry Andric ArgVals.push_back(ParamValue::forDirect(U));
33559f4dbff6SDimitry Andric }
335606d4ba38SDimitry Andric break;
3357ec2b103cSEd Schouten }
3358ec2b103cSEd Schouten }
33599f4dbff6SDimitry Andric
33609f4dbff6SDimitry Andric if (getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
33619f4dbff6SDimitry Andric for (int I = Args.size() - 1; I >= 0; --I)
336245b53394SDimitry Andric EmitParmDecl(*Args[I], ArgVals[I], I + 1);
33639f4dbff6SDimitry Andric } else {
33649f4dbff6SDimitry Andric for (unsigned I = 0, E = Args.size(); I != E; ++I)
336545b53394SDimitry Andric EmitParmDecl(*Args[I], ArgVals[I], I + 1);
33669f4dbff6SDimitry Andric }
3367ec2b103cSEd Schouten }
3368ec2b103cSEd Schouten
eraseUnusedBitCasts(llvm::Instruction * insn)3369dbe13110SDimitry Andric static void eraseUnusedBitCasts(llvm::Instruction *insn) {
3370dbe13110SDimitry Andric while (insn->use_empty()) {
3371dbe13110SDimitry Andric llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(insn);
3372dbe13110SDimitry Andric if (!bitcast) return;
3373dbe13110SDimitry Andric
3374dbe13110SDimitry Andric // This is "safe" because we would have used a ConstantExpr otherwise.
3375dbe13110SDimitry Andric insn = cast<llvm::Instruction>(bitcast->getOperand(0));
3376dbe13110SDimitry Andric bitcast->eraseFromParent();
3377dbe13110SDimitry Andric }
3378dbe13110SDimitry Andric }
3379dbe13110SDimitry Andric
3380180abc3dSDimitry Andric /// Try to emit a fused autorelease of a return result.
tryEmitFusedAutoreleaseOfResult(CodeGenFunction & CGF,llvm::Value * result)3381180abc3dSDimitry Andric static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
3382180abc3dSDimitry Andric llvm::Value *result) {
3383180abc3dSDimitry Andric // We must be immediately followed the cast.
3384180abc3dSDimitry Andric llvm::BasicBlock *BB = CGF.Builder.GetInsertBlock();
33859f4dbff6SDimitry Andric if (BB->empty()) return nullptr;
33869f4dbff6SDimitry Andric if (&BB->back() != result) return nullptr;
3387180abc3dSDimitry Andric
338836981b17SDimitry Andric llvm::Type *resultType = result->getType();
3389180abc3dSDimitry Andric
3390180abc3dSDimitry Andric // result is in a BasicBlock and is therefore an Instruction.
3391180abc3dSDimitry Andric llvm::Instruction *generator = cast<llvm::Instruction>(result);
3392180abc3dSDimitry Andric
3393bab175ecSDimitry Andric SmallVector<llvm::Instruction *, 4> InstsToKill;
3394180abc3dSDimitry Andric
3395180abc3dSDimitry Andric // Look for:
3396180abc3dSDimitry Andric // %generator = bitcast %type1* %generator2 to %type2*
3397180abc3dSDimitry Andric while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(generator)) {
3398180abc3dSDimitry Andric // We would have emitted this as a constant if the operand weren't
3399180abc3dSDimitry Andric // an Instruction.
3400180abc3dSDimitry Andric generator = cast<llvm::Instruction>(bitcast->getOperand(0));
3401180abc3dSDimitry Andric
3402180abc3dSDimitry Andric // Require the generator to be immediately followed by the cast.
3403180abc3dSDimitry Andric if (generator->getNextNode() != bitcast)
34049f4dbff6SDimitry Andric return nullptr;
3405180abc3dSDimitry Andric
3406bab175ecSDimitry Andric InstsToKill.push_back(bitcast);
3407180abc3dSDimitry Andric }
3408180abc3dSDimitry Andric
3409180abc3dSDimitry Andric // Look for:
3410180abc3dSDimitry Andric // %generator = call i8* @objc_retain(i8* %originalResult)
3411180abc3dSDimitry Andric // or
3412180abc3dSDimitry Andric // %generator = call i8* @objc_retainAutoreleasedReturnValue(i8* %originalResult)
3413180abc3dSDimitry Andric llvm::CallInst *call = dyn_cast<llvm::CallInst>(generator);
34149f4dbff6SDimitry Andric if (!call) return nullptr;
3415180abc3dSDimitry Andric
3416180abc3dSDimitry Andric bool doRetainAutorelease;
3417180abc3dSDimitry Andric
3418cfca06d7SDimitry Andric if (call->getCalledOperand() == CGF.CGM.getObjCEntrypoints().objc_retain) {
3419180abc3dSDimitry Andric doRetainAutorelease = true;
3420cfca06d7SDimitry Andric } else if (call->getCalledOperand() ==
3421cfca06d7SDimitry Andric CGF.CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue) {
3422180abc3dSDimitry Andric doRetainAutorelease = false;
3423180abc3dSDimitry Andric
342413cc256eSDimitry Andric // If we emitted an assembly marker for this call (and the
342513cc256eSDimitry Andric // ARCEntrypoints field should have been set if so), go looking
342613cc256eSDimitry Andric // for that call. If we can't find it, we can't do this
342713cc256eSDimitry Andric // optimization. But it should always be the immediately previous
342813cc256eSDimitry Andric // instruction, unless we needed bitcasts around the call.
342945b53394SDimitry Andric if (CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker) {
3430180abc3dSDimitry Andric llvm::Instruction *prev = call->getPrevNode();
343113cc256eSDimitry Andric assert(prev);
343213cc256eSDimitry Andric if (isa<llvm::BitCastInst>(prev)) {
343313cc256eSDimitry Andric prev = prev->getPrevNode();
343413cc256eSDimitry Andric assert(prev);
343513cc256eSDimitry Andric }
343613cc256eSDimitry Andric assert(isa<llvm::CallInst>(prev));
3437cfca06d7SDimitry Andric assert(cast<llvm::CallInst>(prev)->getCalledOperand() ==
343845b53394SDimitry Andric CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker);
3439bab175ecSDimitry Andric InstsToKill.push_back(prev);
344013cc256eSDimitry Andric }
3441180abc3dSDimitry Andric } else {
34429f4dbff6SDimitry Andric return nullptr;
3443180abc3dSDimitry Andric }
3444180abc3dSDimitry Andric
3445180abc3dSDimitry Andric result = call->getArgOperand(0);
3446bab175ecSDimitry Andric InstsToKill.push_back(call);
3447180abc3dSDimitry Andric
3448180abc3dSDimitry Andric // Keep killing bitcasts, for sanity. Note that we no longer care
3449180abc3dSDimitry Andric // about precise ordering as long as there's exactly one use.
3450180abc3dSDimitry Andric while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) {
3451180abc3dSDimitry Andric if (!bitcast->hasOneUse()) break;
3452bab175ecSDimitry Andric InstsToKill.push_back(bitcast);
3453180abc3dSDimitry Andric result = bitcast->getOperand(0);
3454180abc3dSDimitry Andric }
3455180abc3dSDimitry Andric
3456180abc3dSDimitry Andric // Delete all the unnecessary instructions, from latest to earliest.
3457bab175ecSDimitry Andric for (auto *I : InstsToKill)
3458bab175ecSDimitry Andric I->eraseFromParent();
3459180abc3dSDimitry Andric
3460180abc3dSDimitry Andric // Do the fused retain/autorelease if we were asked to.
3461180abc3dSDimitry Andric if (doRetainAutorelease)
3462180abc3dSDimitry Andric result = CGF.EmitARCRetainAutoreleaseReturnValue(result);
3463180abc3dSDimitry Andric
3464180abc3dSDimitry Andric // Cast back to the result type.
3465180abc3dSDimitry Andric return CGF.Builder.CreateBitCast(result, resultType);
3466180abc3dSDimitry Andric }
3467180abc3dSDimitry Andric
3468dbe13110SDimitry Andric /// If this is a +1 of the value of an immutable 'self', remove it.
tryRemoveRetainOfSelf(CodeGenFunction & CGF,llvm::Value * result)3469dbe13110SDimitry Andric static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF,
3470dbe13110SDimitry Andric llvm::Value *result) {
3471dbe13110SDimitry Andric // This is only applicable to a method with an immutable 'self'.
347256d91b49SDimitry Andric const ObjCMethodDecl *method =
347356d91b49SDimitry Andric dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl);
34749f4dbff6SDimitry Andric if (!method) return nullptr;
3475dbe13110SDimitry Andric const VarDecl *self = method->getSelfDecl();
34769f4dbff6SDimitry Andric if (!self->getType().isConstQualified()) return nullptr;
3477dbe13110SDimitry Andric
3478b1c73532SDimitry Andric // Look for a retain call. Note: stripPointerCasts looks through returned arg
3479b1c73532SDimitry Andric // functions, which would cause us to miss the retain.
3480b1c73532SDimitry Andric llvm::CallInst *retainCall = dyn_cast<llvm::CallInst>(result);
3481cfca06d7SDimitry Andric if (!retainCall || retainCall->getCalledOperand() !=
3482cfca06d7SDimitry Andric CGF.CGM.getObjCEntrypoints().objc_retain)
34839f4dbff6SDimitry Andric return nullptr;
3484dbe13110SDimitry Andric
3485dbe13110SDimitry Andric // Look for an ordinary load of 'self'.
3486dbe13110SDimitry Andric llvm::Value *retainedValue = retainCall->getArgOperand(0);
3487dbe13110SDimitry Andric llvm::LoadInst *load =
3488dbe13110SDimitry Andric dyn_cast<llvm::LoadInst>(retainedValue->stripPointerCasts());
3489dbe13110SDimitry Andric if (!load || load->isAtomic() || load->isVolatile() ||
3490ac9a064cSDimitry Andric load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer())
34919f4dbff6SDimitry Andric return nullptr;
3492dbe13110SDimitry Andric
3493dbe13110SDimitry Andric // Okay! Burn it all down. This relies for correctness on the
3494dbe13110SDimitry Andric // assumption that the retain is emitted as part of the return and
3495dbe13110SDimitry Andric // that thereafter everything is used "linearly".
3496dbe13110SDimitry Andric llvm::Type *resultType = result->getType();
3497dbe13110SDimitry Andric eraseUnusedBitCasts(cast<llvm::Instruction>(result));
3498dbe13110SDimitry Andric assert(retainCall->use_empty());
3499dbe13110SDimitry Andric retainCall->eraseFromParent();
3500dbe13110SDimitry Andric eraseUnusedBitCasts(cast<llvm::Instruction>(retainedValue));
3501dbe13110SDimitry Andric
3502dbe13110SDimitry Andric return CGF.Builder.CreateBitCast(load, resultType);
3503dbe13110SDimitry Andric }
3504dbe13110SDimitry Andric
3505180abc3dSDimitry Andric /// Emit an ARC autorelease of the result of a function.
3506dbe13110SDimitry Andric ///
3507dbe13110SDimitry Andric /// \return the value to actually return from the function
emitAutoreleaseOfResult(CodeGenFunction & CGF,llvm::Value * result)3508180abc3dSDimitry Andric static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF,
3509180abc3dSDimitry Andric llvm::Value *result) {
3510dbe13110SDimitry Andric // If we're returning 'self', kill the initial retain. This is a
3511dbe13110SDimitry Andric // heuristic attempt to "encourage correctness" in the really unfortunate
3512dbe13110SDimitry Andric // case where we have a return of self during a dealloc and we desperately
3513dbe13110SDimitry Andric // need to avoid the possible autorelease.
3514dbe13110SDimitry Andric if (llvm::Value *self = tryRemoveRetainOfSelf(CGF, result))
3515dbe13110SDimitry Andric return self;
3516dbe13110SDimitry Andric
3517180abc3dSDimitry Andric // At -O0, try to emit a fused retain/autorelease.
3518180abc3dSDimitry Andric if (CGF.shouldUseFusedARCCalls())
3519180abc3dSDimitry Andric if (llvm::Value *fused = tryEmitFusedAutoreleaseOfResult(CGF, result))
3520180abc3dSDimitry Andric return fused;
3521180abc3dSDimitry Andric
3522180abc3dSDimitry Andric return CGF.EmitARCAutoreleaseReturnValue(result);
3523180abc3dSDimitry Andric }
3524180abc3dSDimitry Andric
3525dbe13110SDimitry Andric /// Heuristically search for a dominating store to the return-value slot.
findDominatingStoreToReturnValue(CodeGenFunction & CGF)3526dbe13110SDimitry Andric static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
3527ac9a064cSDimitry Andric llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer();
3528ac9a064cSDimitry Andric
352945b53394SDimitry Andric // Check if a User is a store which pointerOperand is the ReturnValue.
353045b53394SDimitry Andric // We are looking for stores to the ReturnValue, not for stores of the
353145b53394SDimitry Andric // ReturnValue to some other location.
3532ac9a064cSDimitry Andric auto GetStoreIfValid = [&CGF,
3533ac9a064cSDimitry Andric ReturnValuePtr](llvm::User *U) -> llvm::StoreInst * {
353445b53394SDimitry Andric auto *SI = dyn_cast<llvm::StoreInst>(U);
3535ac9a064cSDimitry Andric if (!SI || SI->getPointerOperand() != ReturnValuePtr ||
3536145449b1SDimitry Andric SI->getValueOperand()->getType() != CGF.ReturnValue.getElementType())
353745b53394SDimitry Andric return nullptr;
353845b53394SDimitry Andric // These aren't actually possible for non-coerced returns, and we
353945b53394SDimitry Andric // only care about non-coerced returns on this code path.
3540b1c73532SDimitry Andric // All memory instructions inside __try block are volatile.
3541b1c73532SDimitry Andric assert(!SI->isAtomic() &&
3542b1c73532SDimitry Andric (!SI->isVolatile() || CGF.currentFunctionUsesSEHTry()));
354345b53394SDimitry Andric return SI;
354445b53394SDimitry Andric };
3545dbe13110SDimitry Andric // If there are multiple uses of the return-value slot, just check
3546dbe13110SDimitry Andric // for something immediately preceding the IP. Sometimes this can
3547dbe13110SDimitry Andric // happen with how we generate implicit-returns; it can also happen
3548dbe13110SDimitry Andric // with noreturn cleanups.
3549ac9a064cSDimitry Andric if (!ReturnValuePtr->hasOneUse()) {
3550dbe13110SDimitry Andric llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();
35519f4dbff6SDimitry Andric if (IP->empty()) return nullptr;
35525e20cdd8SDimitry Andric
3553145449b1SDimitry Andric // Look at directly preceding instruction, skipping bitcasts and lifetime
3554145449b1SDimitry Andric // markers.
3555145449b1SDimitry Andric for (llvm::Instruction &I : make_range(IP->rbegin(), IP->rend())) {
3556145449b1SDimitry Andric if (isa<llvm::BitCastInst>(&I))
35575e20cdd8SDimitry Andric continue;
3558145449b1SDimitry Andric if (auto *II = dyn_cast<llvm::IntrinsicInst>(&I))
3559145449b1SDimitry Andric if (II->getIntrinsicID() == llvm::Intrinsic::lifetime_end)
3560145449b1SDimitry Andric continue;
35615e20cdd8SDimitry Andric
3562145449b1SDimitry Andric return GetStoreIfValid(&I);
3563145449b1SDimitry Andric }
3564145449b1SDimitry Andric return nullptr;
3565dbe13110SDimitry Andric }
3566dbe13110SDimitry Andric
3567ac9a064cSDimitry Andric llvm::StoreInst *store = GetStoreIfValid(ReturnValuePtr->user_back());
35689f4dbff6SDimitry Andric if (!store) return nullptr;
3569dbe13110SDimitry Andric
3570dbe13110SDimitry Andric // Now do a first-and-dirty dominance check: just walk up the
3571dbe13110SDimitry Andric // single-predecessors chain from the current insertion point.
3572dbe13110SDimitry Andric llvm::BasicBlock *StoreBB = store->getParent();
3573dbe13110SDimitry Andric llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();
35747fa27ce4SDimitry Andric llvm::SmallPtrSet<llvm::BasicBlock *, 4> SeenBBs;
3575dbe13110SDimitry Andric while (IP != StoreBB) {
35767fa27ce4SDimitry Andric if (!SeenBBs.insert(IP).second || !(IP = IP->getSinglePredecessor()))
35779f4dbff6SDimitry Andric return nullptr;
3578dbe13110SDimitry Andric }
3579dbe13110SDimitry Andric
3580dbe13110SDimitry Andric // Okay, the store's basic block dominates the insertion point; we
3581dbe13110SDimitry Andric // can do our thing.
3582dbe13110SDimitry Andric return store;
3583dbe13110SDimitry Andric }
3584dbe13110SDimitry Andric
3585cfca06d7SDimitry Andric // Helper functions for EmitCMSEClearRecord
3586cfca06d7SDimitry Andric
3587cfca06d7SDimitry Andric // Set the bits corresponding to a field having width `BitWidth` and located at
3588cfca06d7SDimitry Andric // offset `BitOffset` (from the least significant bit) within a storage unit of
3589cfca06d7SDimitry Andric // `Bits.size()` bytes. Each element of `Bits` corresponds to one target byte.
3590cfca06d7SDimitry Andric // Use little-endian layout, i.e.`Bits[0]` is the LSB.
setBitRange(SmallVectorImpl<uint64_t> & Bits,int BitOffset,int BitWidth,int CharWidth)3591cfca06d7SDimitry Andric static void setBitRange(SmallVectorImpl<uint64_t> &Bits, int BitOffset,
3592cfca06d7SDimitry Andric int BitWidth, int CharWidth) {
3593cfca06d7SDimitry Andric assert(CharWidth <= 64);
3594cfca06d7SDimitry Andric assert(static_cast<unsigned>(BitWidth) <= Bits.size() * CharWidth);
3595cfca06d7SDimitry Andric
3596cfca06d7SDimitry Andric int Pos = 0;
3597cfca06d7SDimitry Andric if (BitOffset >= CharWidth) {
3598cfca06d7SDimitry Andric Pos += BitOffset / CharWidth;
3599cfca06d7SDimitry Andric BitOffset = BitOffset % CharWidth;
3600cfca06d7SDimitry Andric }
3601cfca06d7SDimitry Andric
3602cfca06d7SDimitry Andric const uint64_t Used = (uint64_t(1) << CharWidth) - 1;
3603cfca06d7SDimitry Andric if (BitOffset + BitWidth >= CharWidth) {
3604cfca06d7SDimitry Andric Bits[Pos++] |= (Used << BitOffset) & Used;
3605cfca06d7SDimitry Andric BitWidth -= CharWidth - BitOffset;
3606cfca06d7SDimitry Andric BitOffset = 0;
3607cfca06d7SDimitry Andric }
3608cfca06d7SDimitry Andric
3609cfca06d7SDimitry Andric while (BitWidth >= CharWidth) {
3610cfca06d7SDimitry Andric Bits[Pos++] = Used;
3611cfca06d7SDimitry Andric BitWidth -= CharWidth;
3612cfca06d7SDimitry Andric }
3613cfca06d7SDimitry Andric
3614cfca06d7SDimitry Andric if (BitWidth > 0)
3615cfca06d7SDimitry Andric Bits[Pos++] |= (Used >> (CharWidth - BitWidth)) << BitOffset;
3616cfca06d7SDimitry Andric }
3617cfca06d7SDimitry Andric
3618cfca06d7SDimitry Andric // Set the bits corresponding to a field having width `BitWidth` and located at
3619cfca06d7SDimitry Andric // offset `BitOffset` (from the least significant bit) within a storage unit of
3620cfca06d7SDimitry Andric // `StorageSize` bytes, located at `StorageOffset` in `Bits`. Each element of
3621cfca06d7SDimitry Andric // `Bits` corresponds to one target byte. Use target endian layout.
setBitRange(SmallVectorImpl<uint64_t> & Bits,int StorageOffset,int StorageSize,int BitOffset,int BitWidth,int CharWidth,bool BigEndian)3622cfca06d7SDimitry Andric static void setBitRange(SmallVectorImpl<uint64_t> &Bits, int StorageOffset,
3623cfca06d7SDimitry Andric int StorageSize, int BitOffset, int BitWidth,
3624cfca06d7SDimitry Andric int CharWidth, bool BigEndian) {
3625cfca06d7SDimitry Andric
3626cfca06d7SDimitry Andric SmallVector<uint64_t, 8> TmpBits(StorageSize);
3627cfca06d7SDimitry Andric setBitRange(TmpBits, BitOffset, BitWidth, CharWidth);
3628cfca06d7SDimitry Andric
3629cfca06d7SDimitry Andric if (BigEndian)
3630cfca06d7SDimitry Andric std::reverse(TmpBits.begin(), TmpBits.end());
3631cfca06d7SDimitry Andric
3632cfca06d7SDimitry Andric for (uint64_t V : TmpBits)
3633cfca06d7SDimitry Andric Bits[StorageOffset++] |= V;
3634cfca06d7SDimitry Andric }
3635cfca06d7SDimitry Andric
3636cfca06d7SDimitry Andric static void setUsedBits(CodeGenModule &, QualType, int,
3637cfca06d7SDimitry Andric SmallVectorImpl<uint64_t> &);
3638cfca06d7SDimitry Andric
3639cfca06d7SDimitry Andric // Set the bits in `Bits`, which correspond to the value representations of
3640cfca06d7SDimitry Andric // the actual members of the record type `RTy`. Note that this function does
3641cfca06d7SDimitry Andric // not handle base classes, virtual tables, etc, since they cannot happen in
3642cfca06d7SDimitry Andric // CMSE function arguments or return. The bit mask corresponds to the target
3643cfca06d7SDimitry Andric // memory layout, i.e. it's endian dependent.
setUsedBits(CodeGenModule & CGM,const RecordType * RTy,int Offset,SmallVectorImpl<uint64_t> & Bits)3644cfca06d7SDimitry Andric static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset,
3645cfca06d7SDimitry Andric SmallVectorImpl<uint64_t> &Bits) {
3646cfca06d7SDimitry Andric ASTContext &Context = CGM.getContext();
3647cfca06d7SDimitry Andric int CharWidth = Context.getCharWidth();
3648cfca06d7SDimitry Andric const RecordDecl *RD = RTy->getDecl()->getDefinition();
3649cfca06d7SDimitry Andric const ASTRecordLayout &ASTLayout = Context.getASTRecordLayout(RD);
3650cfca06d7SDimitry Andric const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(RD);
3651cfca06d7SDimitry Andric
3652cfca06d7SDimitry Andric int Idx = 0;
3653cfca06d7SDimitry Andric for (auto I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Idx) {
3654cfca06d7SDimitry Andric const FieldDecl *F = *I;
3655cfca06d7SDimitry Andric
3656ac9a064cSDimitry Andric if (F->isUnnamedBitField() || F->isZeroLengthBitField(Context) ||
3657cfca06d7SDimitry Andric F->getType()->isIncompleteArrayType())
3658cfca06d7SDimitry Andric continue;
3659cfca06d7SDimitry Andric
3660cfca06d7SDimitry Andric if (F->isBitField()) {
3661cfca06d7SDimitry Andric const CGBitFieldInfo &BFI = Layout.getBitFieldInfo(F);
3662cfca06d7SDimitry Andric setBitRange(Bits, Offset + BFI.StorageOffset.getQuantity(),
3663cfca06d7SDimitry Andric BFI.StorageSize / CharWidth, BFI.Offset,
3664cfca06d7SDimitry Andric BFI.Size, CharWidth,
3665cfca06d7SDimitry Andric CGM.getDataLayout().isBigEndian());
3666cfca06d7SDimitry Andric continue;
3667cfca06d7SDimitry Andric }
3668cfca06d7SDimitry Andric
3669cfca06d7SDimitry Andric setUsedBits(CGM, F->getType(),
3670cfca06d7SDimitry Andric Offset + ASTLayout.getFieldOffset(Idx) / CharWidth, Bits);
3671cfca06d7SDimitry Andric }
3672cfca06d7SDimitry Andric }
3673cfca06d7SDimitry Andric
3674cfca06d7SDimitry Andric // Set the bits in `Bits`, which correspond to the value representations of
3675cfca06d7SDimitry Andric // the elements of an array type `ATy`.
setUsedBits(CodeGenModule & CGM,const ConstantArrayType * ATy,int Offset,SmallVectorImpl<uint64_t> & Bits)3676cfca06d7SDimitry Andric static void setUsedBits(CodeGenModule &CGM, const ConstantArrayType *ATy,
3677cfca06d7SDimitry Andric int Offset, SmallVectorImpl<uint64_t> &Bits) {
3678cfca06d7SDimitry Andric const ASTContext &Context = CGM.getContext();
3679cfca06d7SDimitry Andric
3680cfca06d7SDimitry Andric QualType ETy = Context.getBaseElementType(ATy);
3681cfca06d7SDimitry Andric int Size = Context.getTypeSizeInChars(ETy).getQuantity();
3682cfca06d7SDimitry Andric SmallVector<uint64_t, 4> TmpBits(Size);
3683cfca06d7SDimitry Andric setUsedBits(CGM, ETy, 0, TmpBits);
3684cfca06d7SDimitry Andric
3685cfca06d7SDimitry Andric for (int I = 0, N = Context.getConstantArrayElementCount(ATy); I < N; ++I) {
3686cfca06d7SDimitry Andric auto Src = TmpBits.begin();
3687cfca06d7SDimitry Andric auto Dst = Bits.begin() + Offset + I * Size;
3688cfca06d7SDimitry Andric for (int J = 0; J < Size; ++J)
3689cfca06d7SDimitry Andric *Dst++ |= *Src++;
3690cfca06d7SDimitry Andric }
3691cfca06d7SDimitry Andric }
3692cfca06d7SDimitry Andric
3693cfca06d7SDimitry Andric // Set the bits in `Bits`, which correspond to the value representations of
3694cfca06d7SDimitry Andric // the type `QTy`.
setUsedBits(CodeGenModule & CGM,QualType QTy,int Offset,SmallVectorImpl<uint64_t> & Bits)3695cfca06d7SDimitry Andric static void setUsedBits(CodeGenModule &CGM, QualType QTy, int Offset,
3696cfca06d7SDimitry Andric SmallVectorImpl<uint64_t> &Bits) {
3697cfca06d7SDimitry Andric if (const auto *RTy = QTy->getAs<RecordType>())
3698cfca06d7SDimitry Andric return setUsedBits(CGM, RTy, Offset, Bits);
3699cfca06d7SDimitry Andric
3700cfca06d7SDimitry Andric ASTContext &Context = CGM.getContext();
3701cfca06d7SDimitry Andric if (const auto *ATy = Context.getAsConstantArrayType(QTy))
3702cfca06d7SDimitry Andric return setUsedBits(CGM, ATy, Offset, Bits);
3703cfca06d7SDimitry Andric
3704cfca06d7SDimitry Andric int Size = Context.getTypeSizeInChars(QTy).getQuantity();
3705cfca06d7SDimitry Andric if (Size <= 0)
3706cfca06d7SDimitry Andric return;
3707cfca06d7SDimitry Andric
3708cfca06d7SDimitry Andric std::fill_n(Bits.begin() + Offset, Size,
3709cfca06d7SDimitry Andric (uint64_t(1) << Context.getCharWidth()) - 1);
3710cfca06d7SDimitry Andric }
3711cfca06d7SDimitry Andric
buildMultiCharMask(const SmallVectorImpl<uint64_t> & Bits,int Pos,int Size,int CharWidth,bool BigEndian)3712cfca06d7SDimitry Andric static uint64_t buildMultiCharMask(const SmallVectorImpl<uint64_t> &Bits,
3713cfca06d7SDimitry Andric int Pos, int Size, int CharWidth,
3714cfca06d7SDimitry Andric bool BigEndian) {
3715cfca06d7SDimitry Andric assert(Size > 0);
3716cfca06d7SDimitry Andric uint64_t Mask = 0;
3717cfca06d7SDimitry Andric if (BigEndian) {
3718cfca06d7SDimitry Andric for (auto P = Bits.begin() + Pos, E = Bits.begin() + Pos + Size; P != E;
3719cfca06d7SDimitry Andric ++P)
3720cfca06d7SDimitry Andric Mask = (Mask << CharWidth) | *P;
3721cfca06d7SDimitry Andric } else {
3722cfca06d7SDimitry Andric auto P = Bits.begin() + Pos + Size, End = Bits.begin() + Pos;
3723cfca06d7SDimitry Andric do
3724cfca06d7SDimitry Andric Mask = (Mask << CharWidth) | *--P;
3725cfca06d7SDimitry Andric while (P != End);
3726cfca06d7SDimitry Andric }
3727cfca06d7SDimitry Andric return Mask;
3728cfca06d7SDimitry Andric }
3729cfca06d7SDimitry Andric
3730cfca06d7SDimitry Andric // Emit code to clear the bits in a record, which aren't a part of any user
3731cfca06d7SDimitry Andric // declared member, when the record is a function return.
EmitCMSEClearRecord(llvm::Value * Src,llvm::IntegerType * ITy,QualType QTy)3732cfca06d7SDimitry Andric llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src,
3733cfca06d7SDimitry Andric llvm::IntegerType *ITy,
3734cfca06d7SDimitry Andric QualType QTy) {
3735cfca06d7SDimitry Andric assert(Src->getType() == ITy);
3736cfca06d7SDimitry Andric assert(ITy->getScalarSizeInBits() <= 64);
3737cfca06d7SDimitry Andric
3738cfca06d7SDimitry Andric const llvm::DataLayout &DataLayout = CGM.getDataLayout();
3739cfca06d7SDimitry Andric int Size = DataLayout.getTypeStoreSize(ITy);
3740cfca06d7SDimitry Andric SmallVector<uint64_t, 4> Bits(Size);
3741b60736ecSDimitry Andric setUsedBits(CGM, QTy->castAs<RecordType>(), 0, Bits);
3742cfca06d7SDimitry Andric
3743cfca06d7SDimitry Andric int CharWidth = CGM.getContext().getCharWidth();
3744cfca06d7SDimitry Andric uint64_t Mask =
3745cfca06d7SDimitry Andric buildMultiCharMask(Bits, 0, Size, CharWidth, DataLayout.isBigEndian());
3746cfca06d7SDimitry Andric
3747cfca06d7SDimitry Andric return Builder.CreateAnd(Src, Mask, "cmse.clear");
3748cfca06d7SDimitry Andric }
3749cfca06d7SDimitry Andric
3750cfca06d7SDimitry Andric // Emit code to clear the bits in a record, which aren't a part of any user
3751cfca06d7SDimitry Andric // declared member, when the record is a function argument.
EmitCMSEClearRecord(llvm::Value * Src,llvm::ArrayType * ATy,QualType QTy)3752cfca06d7SDimitry Andric llvm::Value *CodeGenFunction::EmitCMSEClearRecord(llvm::Value *Src,
3753cfca06d7SDimitry Andric llvm::ArrayType *ATy,
3754cfca06d7SDimitry Andric QualType QTy) {
3755cfca06d7SDimitry Andric const llvm::DataLayout &DataLayout = CGM.getDataLayout();
3756cfca06d7SDimitry Andric int Size = DataLayout.getTypeStoreSize(ATy);
3757cfca06d7SDimitry Andric SmallVector<uint64_t, 16> Bits(Size);
3758b60736ecSDimitry Andric setUsedBits(CGM, QTy->castAs<RecordType>(), 0, Bits);
3759cfca06d7SDimitry Andric
3760cfca06d7SDimitry Andric // Clear each element of the LLVM array.
3761cfca06d7SDimitry Andric int CharWidth = CGM.getContext().getCharWidth();
3762cfca06d7SDimitry Andric int CharsPerElt =
3763cfca06d7SDimitry Andric ATy->getArrayElementType()->getScalarSizeInBits() / CharWidth;
3764cfca06d7SDimitry Andric int MaskIndex = 0;
3765145449b1SDimitry Andric llvm::Value *R = llvm::PoisonValue::get(ATy);
3766cfca06d7SDimitry Andric for (int I = 0, N = ATy->getArrayNumElements(); I != N; ++I) {
3767cfca06d7SDimitry Andric uint64_t Mask = buildMultiCharMask(Bits, MaskIndex, CharsPerElt, CharWidth,
3768cfca06d7SDimitry Andric DataLayout.isBigEndian());
3769cfca06d7SDimitry Andric MaskIndex += CharsPerElt;
3770cfca06d7SDimitry Andric llvm::Value *T0 = Builder.CreateExtractValue(Src, I);
3771cfca06d7SDimitry Andric llvm::Value *T1 = Builder.CreateAnd(T0, Mask, "cmse.clear");
3772cfca06d7SDimitry Andric R = Builder.CreateInsertValue(R, T1, I);
3773cfca06d7SDimitry Andric }
3774cfca06d7SDimitry Andric
3775cfca06d7SDimitry Andric return R;
3776cfca06d7SDimitry Andric }
3777cfca06d7SDimitry Andric
EmitFunctionEpilog(const CGFunctionInfo & FI,bool EmitRetDbgLoc,SourceLocation EndLoc)37786a037251SDimitry Andric void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
3779bfef3995SDimitry Andric bool EmitRetDbgLoc,
3780bfef3995SDimitry Andric SourceLocation EndLoc) {
37816252156dSDimitry Andric if (FI.isNoReturn()) {
37826252156dSDimitry Andric // Noreturn functions don't return.
37836252156dSDimitry Andric EmitUnreachable(EndLoc);
37846252156dSDimitry Andric return;
37856252156dSDimitry Andric }
37866252156dSDimitry Andric
378706d4ba38SDimitry Andric if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) {
378806d4ba38SDimitry Andric // Naked functions don't have epilogues.
378906d4ba38SDimitry Andric Builder.CreateUnreachable();
379006d4ba38SDimitry Andric return;
379106d4ba38SDimitry Andric }
379206d4ba38SDimitry Andric
3793ec2b103cSEd Schouten // Functions with no result always return void.
379445b53394SDimitry Andric if (!ReturnValue.isValid()) {
37954ba67500SRoman Divacky Builder.CreateRetVoid();
37964ba67500SRoman Divacky return;
37974ba67500SRoman Divacky }
37984ba67500SRoman Divacky
37993d1dcd9bSDimitry Andric llvm::DebugLoc RetDbgLoc;
38009f4dbff6SDimitry Andric llvm::Value *RV = nullptr;
3801ec2b103cSEd Schouten QualType RetTy = FI.getReturnType();
3802ec2b103cSEd Schouten const ABIArgInfo &RetAI = FI.getReturnInfo();
3803ec2b103cSEd Schouten
3804ec2b103cSEd Schouten switch (RetAI.getKind()) {
38059f4dbff6SDimitry Andric case ABIArgInfo::InAlloca:
3806e3b55780SDimitry Andric // Aggregates get evaluated directly into the destination. Sometimes we
38079f4dbff6SDimitry Andric // need to return the sret value in a register, though.
38089f4dbff6SDimitry Andric assert(hasAggregateEvaluationKind(RetTy));
38099f4dbff6SDimitry Andric if (RetAI.getInAllocaSRet()) {
38109f4dbff6SDimitry Andric llvm::Function::arg_iterator EI = CurFn->arg_end();
38119f4dbff6SDimitry Andric --EI;
381245b53394SDimitry Andric llvm::Value *ArgStruct = &*EI;
38135e20cdd8SDimitry Andric llvm::Value *SRet = Builder.CreateStructGEP(
3814145449b1SDimitry Andric FI.getArgStruct(), ArgStruct, RetAI.getInAllocaFieldIndex());
3815344a3780SDimitry Andric llvm::Type *Ty =
3816344a3780SDimitry Andric cast<llvm::GetElementPtrInst>(SRet)->getResultElementType();
3817344a3780SDimitry Andric RV = Builder.CreateAlignedLoad(Ty, SRet, getPointerAlign(), "sret");
38189f4dbff6SDimitry Andric }
38199f4dbff6SDimitry Andric break;
38209f4dbff6SDimitry Andric
38213d1dcd9bSDimitry Andric case ABIArgInfo::Indirect: {
38229f4dbff6SDimitry Andric auto AI = CurFn->arg_begin();
38239f4dbff6SDimitry Andric if (RetAI.isSRetAfterThis())
38249f4dbff6SDimitry Andric ++AI;
3825809500fcSDimitry Andric switch (getEvaluationKind(RetTy)) {
3826809500fcSDimitry Andric case TEK_Complex: {
3827809500fcSDimitry Andric ComplexPairTy RT =
382845b53394SDimitry Andric EmitLoadOfComplex(MakeAddrLValue(ReturnValue, RetTy), EndLoc);
382945b53394SDimitry Andric EmitStoreOfComplex(RT, MakeNaturalAlignAddrLValue(&*AI, RetTy),
3830809500fcSDimitry Andric /*isInit*/ true);
3831809500fcSDimitry Andric break;
3832809500fcSDimitry Andric }
3833809500fcSDimitry Andric case TEK_Aggregate:
3834e3b55780SDimitry Andric // Do nothing; aggregates get evaluated directly into the destination.
3835809500fcSDimitry Andric break;
383677fc4c14SDimitry Andric case TEK_Scalar: {
383777fc4c14SDimitry Andric LValueBaseInfo BaseInfo;
383877fc4c14SDimitry Andric TBAAAccessInfo TBAAInfo;
383977fc4c14SDimitry Andric CharUnits Alignment =
384077fc4c14SDimitry Andric CGM.getNaturalTypeAlignment(RetTy, &BaseInfo, &TBAAInfo);
384177fc4c14SDimitry Andric Address ArgAddr(&*AI, ConvertType(RetTy), Alignment);
384277fc4c14SDimitry Andric LValue ArgVal =
384377fc4c14SDimitry Andric LValue::MakeAddr(ArgAddr, RetTy, getContext(), BaseInfo, TBAAInfo);
384477fc4c14SDimitry Andric EmitStoreOfScalar(
3845ac9a064cSDimitry Andric EmitLoadOfScalar(MakeAddrLValue(ReturnValue, RetTy), EndLoc), ArgVal,
3846ac9a064cSDimitry Andric /*isInit*/ true);
3847809500fcSDimitry Andric break;
3848ec2b103cSEd Schouten }
384977fc4c14SDimitry Andric }
3850ec2b103cSEd Schouten break;
38513d1dcd9bSDimitry Andric }
3852ec2b103cSEd Schouten
385370b4596dSEd Schouten case ABIArgInfo::Extend:
38543d1dcd9bSDimitry Andric case ABIArgInfo::Direct:
38553d1dcd9bSDimitry Andric if (RetAI.getCoerceToType() == ConvertType(RetTy) &&
38563d1dcd9bSDimitry Andric RetAI.getDirectOffset() == 0) {
38574ba67500SRoman Divacky // The internal return value temp always will have pointer-to-return-type
38584ba67500SRoman Divacky // type, just do a load.
3859ec2b103cSEd Schouten
3860dbe13110SDimitry Andric // If there is a dominating store to ReturnValue, we can elide
3861dbe13110SDimitry Andric // the load, zap the store, and usually zap the alloca.
38625e20cdd8SDimitry Andric if (llvm::StoreInst *SI =
38635e20cdd8SDimitry Andric findDominatingStoreToReturnValue(*this)) {
3864bfef3995SDimitry Andric // Reuse the debug location from the store unless there is
3865bfef3995SDimitry Andric // cleanup code to be emitted between the store and return
3866bfef3995SDimitry Andric // instruction.
3867bfef3995SDimitry Andric if (EmitRetDbgLoc && !AutoreleaseResult)
38683d1dcd9bSDimitry Andric RetDbgLoc = SI->getDebugLoc();
38696a037251SDimitry Andric // Get the stored value and nuke the now-dead store.
38704ba67500SRoman Divacky RV = SI->getValueOperand();
38714ba67500SRoman Divacky SI->eraseFromParent();
38724ba67500SRoman Divacky
3873dbe13110SDimitry Andric // Otherwise, we have to do a simple load.
3874dbe13110SDimitry Andric } else {
3875dbe13110SDimitry Andric RV = Builder.CreateLoad(ReturnValue);
38764ba67500SRoman Divacky }
38773d1dcd9bSDimitry Andric } else {
38783d1dcd9bSDimitry Andric // If the value is offset in memory, apply the offset now.
387945b53394SDimitry Andric Address V = emitAddressAtOffset(*this, ReturnValue, RetAI);
38803d1dcd9bSDimitry Andric
388145b53394SDimitry Andric RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
38823d1dcd9bSDimitry Andric }
3883180abc3dSDimitry Andric
3884180abc3dSDimitry Andric // In ARC, end functions that return a retainable type with a call
3885180abc3dSDimitry Andric // to objc_autoreleaseReturnValue.
3886180abc3dSDimitry Andric if (AutoreleaseResult) {
38872b6b257fSDimitry Andric #ifndef NDEBUG
38882b6b257fSDimitry Andric // Type::isObjCRetainabletype has to be called on a QualType that hasn't
38892b6b257fSDimitry Andric // been stripped of the typedefs, so we cannot use RetTy here. Get the
38902b6b257fSDimitry Andric // original return type of FunctionDecl, CurCodeDecl, and BlockDecl from
38912b6b257fSDimitry Andric // CurCodeDecl or BlockInfo.
38922b6b257fSDimitry Andric QualType RT;
38932b6b257fSDimitry Andric
38942b6b257fSDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(CurCodeDecl))
38952b6b257fSDimitry Andric RT = FD->getReturnType();
38962b6b257fSDimitry Andric else if (auto *MD = dyn_cast<ObjCMethodDecl>(CurCodeDecl))
38972b6b257fSDimitry Andric RT = MD->getReturnType();
38982b6b257fSDimitry Andric else if (isa<BlockDecl>(CurCodeDecl))
38992b6b257fSDimitry Andric RT = BlockInfo->BlockExpression->getFunctionType()->getReturnType();
39002b6b257fSDimitry Andric else
39012b6b257fSDimitry Andric llvm_unreachable("Unexpected function/method type");
39022b6b257fSDimitry Andric
3903dbe13110SDimitry Andric assert(getLangOpts().ObjCAutoRefCount &&
3904180abc3dSDimitry Andric !FI.isReturnsRetained() &&
39052b6b257fSDimitry Andric RT->isObjCRetainableType());
39062b6b257fSDimitry Andric #endif
3907180abc3dSDimitry Andric RV = emitAutoreleaseOfResult(*this, RV);
3908180abc3dSDimitry Andric }
3909180abc3dSDimitry Andric
3910ec2b103cSEd Schouten break;
3911ec2b103cSEd Schouten
39123d1dcd9bSDimitry Andric case ABIArgInfo::Ignore:
3913ec2b103cSEd Schouten break;
3914ec2b103cSEd Schouten
39152b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand: {
39162b6b257fSDimitry Andric auto coercionType = RetAI.getCoerceAndExpandType();
39172b6b257fSDimitry Andric
39182b6b257fSDimitry Andric // Load all of the coerced elements out into results.
39192b6b257fSDimitry Andric llvm::SmallVector<llvm::Value*, 4> results;
39207fa27ce4SDimitry Andric Address addr = ReturnValue.withElementType(coercionType);
39212b6b257fSDimitry Andric for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
39222b6b257fSDimitry Andric auto coercedEltType = coercionType->getElementType(i);
39232b6b257fSDimitry Andric if (ABIArgInfo::isPaddingForCoerceAndExpand(coercedEltType))
39242b6b257fSDimitry Andric continue;
39252b6b257fSDimitry Andric
392622989816SDimitry Andric auto eltAddr = Builder.CreateStructGEP(addr, i);
39272b6b257fSDimitry Andric auto elt = Builder.CreateLoad(eltAddr);
39282b6b257fSDimitry Andric results.push_back(elt);
39292b6b257fSDimitry Andric }
39302b6b257fSDimitry Andric
39312b6b257fSDimitry Andric // If we have one result, it's the single direct result type.
39322b6b257fSDimitry Andric if (results.size() == 1) {
39332b6b257fSDimitry Andric RV = results[0];
39342b6b257fSDimitry Andric
39352b6b257fSDimitry Andric // Otherwise, we need to make a first-class aggregate.
39362b6b257fSDimitry Andric } else {
39372b6b257fSDimitry Andric // Construct a return type that lacks padding elements.
39382b6b257fSDimitry Andric llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType();
39392b6b257fSDimitry Andric
3940145449b1SDimitry Andric RV = llvm::PoisonValue::get(returnType);
39412b6b257fSDimitry Andric for (unsigned i = 0, e = results.size(); i != e; ++i) {
39422b6b257fSDimitry Andric RV = Builder.CreateInsertValue(RV, results[i], i);
39432b6b257fSDimitry Andric }
39442b6b257fSDimitry Andric }
39452b6b257fSDimitry Andric break;
39462b6b257fSDimitry Andric }
3947ec2b103cSEd Schouten case ABIArgInfo::Expand:
3948b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased:
394936981b17SDimitry Andric llvm_unreachable("Invalid ABI kind for return argument");
3950ec2b103cSEd Schouten }
3951ec2b103cSEd Schouten
395206d4ba38SDimitry Andric llvm::Instruction *Ret;
395306d4ba38SDimitry Andric if (RV) {
3954cfca06d7SDimitry Andric if (CurFuncDecl && CurFuncDecl->hasAttr<CmseNSEntryAttr>()) {
3955cfca06d7SDimitry Andric // For certain return types, clear padding bits, as they may reveal
3956cfca06d7SDimitry Andric // sensitive information.
3957cfca06d7SDimitry Andric // Small struct/union types are passed as integers.
3958cfca06d7SDimitry Andric auto *ITy = dyn_cast<llvm::IntegerType>(RV->getType());
3959cfca06d7SDimitry Andric if (ITy != nullptr && isa<RecordType>(RetTy.getCanonicalType()))
3960cfca06d7SDimitry Andric RV = EmitCMSEClearRecord(RV, ITy, RetTy);
3961cfca06d7SDimitry Andric }
3962ef915aabSDimitry Andric EmitReturnValueCheck(RV);
396306d4ba38SDimitry Andric Ret = Builder.CreateRet(RV);
396406d4ba38SDimitry Andric } else {
396506d4ba38SDimitry Andric Ret = Builder.CreateRetVoid();
396606d4ba38SDimitry Andric }
396706d4ba38SDimitry Andric
39685e20cdd8SDimitry Andric if (RetDbgLoc)
39695e20cdd8SDimitry Andric Ret->setDebugLoc(std::move(RetDbgLoc));
3970ec2b103cSEd Schouten }
3971ec2b103cSEd Schouten
EmitReturnValueCheck(llvm::Value * RV)3972ef915aabSDimitry Andric void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
39737442d6faSDimitry Andric // A current decl may not be available when emitting vtable thunks.
39747442d6faSDimitry Andric if (!CurCodeDecl)
39757442d6faSDimitry Andric return;
39767442d6faSDimitry Andric
3977cfca06d7SDimitry Andric // If the return block isn't reachable, neither is this check, so don't emit
3978cfca06d7SDimitry Andric // it.
3979cfca06d7SDimitry Andric if (ReturnBlock.isValid() && ReturnBlock.getBlock()->use_empty())
3980cfca06d7SDimitry Andric return;
3981cfca06d7SDimitry Andric
39827442d6faSDimitry Andric ReturnsNonNullAttr *RetNNAttr = nullptr;
39837442d6faSDimitry Andric if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute))
39847442d6faSDimitry Andric RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>();
39857442d6faSDimitry Andric
39867442d6faSDimitry Andric if (!RetNNAttr && !requiresReturnValueNullabilityCheck())
39877442d6faSDimitry Andric return;
39887442d6faSDimitry Andric
39897442d6faSDimitry Andric // Prefer the returns_nonnull attribute if it's present.
39907442d6faSDimitry Andric SourceLocation AttrLoc;
39917442d6faSDimitry Andric SanitizerMask CheckKind;
39927442d6faSDimitry Andric SanitizerHandler Handler;
39937442d6faSDimitry Andric if (RetNNAttr) {
39947442d6faSDimitry Andric assert(!requiresReturnValueNullabilityCheck() &&
39957442d6faSDimitry Andric "Cannot check nullability and the nonnull attribute");
39967442d6faSDimitry Andric AttrLoc = RetNNAttr->getLocation();
39977442d6faSDimitry Andric CheckKind = SanitizerKind::ReturnsNonnullAttribute;
39987442d6faSDimitry Andric Handler = SanitizerHandler::NonnullReturn;
39997442d6faSDimitry Andric } else {
40007442d6faSDimitry Andric if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl))
40017442d6faSDimitry Andric if (auto *TSI = DD->getTypeSourceInfo())
4002cfca06d7SDimitry Andric if (auto FTL = TSI->getTypeLoc().getAsAdjusted<FunctionTypeLoc>())
40037442d6faSDimitry Andric AttrLoc = FTL.getReturnLoc().findNullabilityLoc();
40047442d6faSDimitry Andric CheckKind = SanitizerKind::NullabilityReturn;
40057442d6faSDimitry Andric Handler = SanitizerHandler::NullabilityReturn;
40067442d6faSDimitry Andric }
40077442d6faSDimitry Andric
40087442d6faSDimitry Andric SanitizerScope SanScope(this);
40097442d6faSDimitry Andric
4010ef915aabSDimitry Andric // Make sure the "return" source location is valid. If we're checking a
4011ef915aabSDimitry Andric // nullability annotation, make sure the preconditions for the check are met.
4012ef915aabSDimitry Andric llvm::BasicBlock *Check = createBasicBlock("nullcheck");
4013ef915aabSDimitry Andric llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck");
4014ef915aabSDimitry Andric llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load");
4015ef915aabSDimitry Andric llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr);
40167442d6faSDimitry Andric if (requiresReturnValueNullabilityCheck())
4017ef915aabSDimitry Andric CanNullCheck =
4018ef915aabSDimitry Andric Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition);
4019ef915aabSDimitry Andric Builder.CreateCondBr(CanNullCheck, Check, NoCheck);
4020ef915aabSDimitry Andric EmitBlock(Check);
4021ef915aabSDimitry Andric
4022ef915aabSDimitry Andric // Now do the null check.
4023ef915aabSDimitry Andric llvm::Value *Cond = Builder.CreateIsNotNull(RV);
4024ef915aabSDimitry Andric llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)};
4025ef915aabSDimitry Andric llvm::Value *DynamicData[] = {SLocPtr};
4026ef915aabSDimitry Andric EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData);
4027ef915aabSDimitry Andric
40287442d6faSDimitry Andric EmitBlock(NoCheck);
4029ef915aabSDimitry Andric
4030ef915aabSDimitry Andric #ifndef NDEBUG
4031ef915aabSDimitry Andric // The return location should not be used after the check has been emitted.
4032ef915aabSDimitry Andric ReturnLocation = Address::invalid();
4033ef915aabSDimitry Andric #endif
40347442d6faSDimitry Andric }
40357442d6faSDimitry Andric
isInAllocaArgument(CGCXXABI & ABI,QualType type)40369f4dbff6SDimitry Andric static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) {
40379f4dbff6SDimitry Andric const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
40389f4dbff6SDimitry Andric return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
40399f4dbff6SDimitry Andric }
40409f4dbff6SDimitry Andric
createPlaceholderSlot(CodeGenFunction & CGF,QualType Ty)404145b53394SDimitry Andric static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF,
404245b53394SDimitry Andric QualType Ty) {
40439f4dbff6SDimitry Andric // FIXME: Generate IR in one pass, rather than going back and fixing up these
40449f4dbff6SDimitry Andric // placeholders.
40459f4dbff6SDimitry Andric llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty);
40467fa27ce4SDimitry Andric llvm::Type *IRPtrTy = llvm::PointerType::getUnqual(CGF.getLLVMContext());
40477fa27ce4SDimitry Andric llvm::Value *Placeholder = llvm::PoisonValue::get(IRPtrTy);
404845b53394SDimitry Andric
404945b53394SDimitry Andric // FIXME: When we generate this IR in one pass, we shouldn't need
405045b53394SDimitry Andric // this win32-specific alignment hack.
405145b53394SDimitry Andric CharUnits Align = CharUnits::fromQuantity(4);
4052bab175ecSDimitry Andric Placeholder = CGF.Builder.CreateAlignedLoad(IRPtrTy, Placeholder, Align);
405345b53394SDimitry Andric
4054145449b1SDimitry Andric return AggValueSlot::forAddr(Address(Placeholder, IRTy, Align),
40559f4dbff6SDimitry Andric Ty.getQualifiers(),
40569f4dbff6SDimitry Andric AggValueSlot::IsNotDestructed,
40579f4dbff6SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers,
405848675466SDimitry Andric AggValueSlot::IsNotAliased,
405948675466SDimitry Andric AggValueSlot::DoesNotOverlap);
40609f4dbff6SDimitry Andric }
40619f4dbff6SDimitry Andric
EmitDelegateCallArg(CallArgList & args,const VarDecl * param,SourceLocation loc)406201af97d3SDimitry Andric void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
4063bfef3995SDimitry Andric const VarDecl *param,
4064bfef3995SDimitry Andric SourceLocation loc) {
4065d7279c4cSRoman Divacky // StartFunction converted the ABI-lowered parameter(s) into a
4066d7279c4cSRoman Divacky // local alloca. We need to turn that into an r-value suitable
4067d7279c4cSRoman Divacky // for EmitCall.
406845b53394SDimitry Andric Address local = GetAddrOfLocalVar(param);
4069d7279c4cSRoman Divacky
407001af97d3SDimitry Andric QualType type = param->getType();
4071d7279c4cSRoman Divacky
4072bab175ecSDimitry Andric // GetAddrOfLocalVar returns a pointer-to-pointer for references,
4073bab175ecSDimitry Andric // but the argument needs to be the original pointer.
4074bab175ecSDimitry Andric if (type->isReferenceType()) {
4075bab175ecSDimitry Andric args.add(RValue::get(Builder.CreateLoad(local)), type);
4076bab175ecSDimitry Andric
4077bab175ecSDimitry Andric // In ARC, move out of consumed arguments so that the release cleanup
4078bab175ecSDimitry Andric // entered by StartFunction doesn't cause an over-release. This isn't
4079bab175ecSDimitry Andric // optimal -O0 code generation, but it should get cleaned up when
4080bab175ecSDimitry Andric // optimization is enabled. This also assumes that delegate calls are
4081bab175ecSDimitry Andric // performed exactly once for a set of arguments, but that should be safe.
4082bab175ecSDimitry Andric } else if (getLangOpts().ObjCAutoRefCount &&
4083bab175ecSDimitry Andric param->hasAttr<NSConsumedAttr>() &&
4084bab175ecSDimitry Andric type->isObjCRetainableType()) {
4085bab175ecSDimitry Andric llvm::Value *ptr = Builder.CreateLoad(local);
4086bab175ecSDimitry Andric auto null =
4087bab175ecSDimitry Andric llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType()));
4088bab175ecSDimitry Andric Builder.CreateStore(null, local);
4089bab175ecSDimitry Andric args.add(RValue::get(ptr), type);
4090bab175ecSDimitry Andric
40912b6b257fSDimitry Andric // For the most part, we just need to load the alloca, except that
40922b6b257fSDimitry Andric // aggregate r-values are actually pointers to temporaries.
4093bab175ecSDimitry Andric } else {
4094bfef3995SDimitry Andric args.add(convertTempToRValue(local, type, loc), type);
409501af97d3SDimitry Andric }
409648675466SDimitry Andric
409748675466SDimitry Andric // Deactivate the cleanup for the callee-destructed param that was pushed.
4098344a3780SDimitry Andric if (type->isRecordType() && !CurFuncIsThunk &&
4099519fc96cSDimitry Andric type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee() &&
4100519fc96cSDimitry Andric param->needsDestruction(getContext())) {
410148675466SDimitry Andric EHScopeStack::stable_iterator cleanup =
410248675466SDimitry Andric CalleeDestructedParamCleanups.lookup(cast<ParmVarDecl>(param));
410348675466SDimitry Andric assert(cleanup.isValid() &&
410448675466SDimitry Andric "cleanup for callee-destructed param not recorded");
410548675466SDimitry Andric // This unreachable is a temporary marker which will be removed later.
410648675466SDimitry Andric llvm::Instruction *isActive = Builder.CreateUnreachable();
410748675466SDimitry Andric args.addArgCleanupDeactivation(cleanup, isActive);
410848675466SDimitry Andric }
4109bab175ecSDimitry Andric }
411001af97d3SDimitry Andric
isProvablyNull(llvm::Value * addr)4111180abc3dSDimitry Andric static bool isProvablyNull(llvm::Value *addr) {
4112ac9a064cSDimitry Andric return llvm::isa_and_nonnull<llvm::ConstantPointerNull>(addr);
4113ac9a064cSDimitry Andric }
4114ac9a064cSDimitry Andric
isProvablyNonNull(Address Addr,CodeGenFunction & CGF)4115ac9a064cSDimitry Andric static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) {
4116ac9a064cSDimitry Andric return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout());
4117180abc3dSDimitry Andric }
4118180abc3dSDimitry Andric
4119180abc3dSDimitry Andric /// Emit the actual writing-back of a writeback.
emitWriteback(CodeGenFunction & CGF,const CallArgList::Writeback & writeback)4120180abc3dSDimitry Andric static void emitWriteback(CodeGenFunction &CGF,
4121180abc3dSDimitry Andric const CallArgList::Writeback &writeback) {
4122809500fcSDimitry Andric const LValue &srcLV = writeback.Source;
4123ac9a064cSDimitry Andric Address srcAddr = srcLV.getAddress();
4124ac9a064cSDimitry Andric assert(!isProvablyNull(srcAddr.getBasePointer()) &&
4125180abc3dSDimitry Andric "shouldn't have writeback for provably null argument");
4126180abc3dSDimitry Andric
41279f4dbff6SDimitry Andric llvm::BasicBlock *contBB = nullptr;
4128180abc3dSDimitry Andric
4129180abc3dSDimitry Andric // If the argument wasn't provably non-null, we need to null check
4130180abc3dSDimitry Andric // before doing the store.
4131ac9a064cSDimitry Andric bool provablyNonNull = isProvablyNonNull(srcAddr, CGF);
4132ac9a064cSDimitry Andric
4133180abc3dSDimitry Andric if (!provablyNonNull) {
4134180abc3dSDimitry Andric llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback");
4135180abc3dSDimitry Andric contBB = CGF.createBasicBlock("icr.done");
4136180abc3dSDimitry Andric
4137ac9a064cSDimitry Andric llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull");
4138180abc3dSDimitry Andric CGF.Builder.CreateCondBr(isNull, contBB, writebackBB);
4139180abc3dSDimitry Andric CGF.EmitBlock(writebackBB);
4140180abc3dSDimitry Andric }
4141180abc3dSDimitry Andric
4142180abc3dSDimitry Andric // Load the value to writeback.
4143180abc3dSDimitry Andric llvm::Value *value = CGF.Builder.CreateLoad(writeback.Temporary);
4144180abc3dSDimitry Andric
4145180abc3dSDimitry Andric // Cast it back, in case we're writing an id to a Foo* or something.
414645b53394SDimitry Andric value = CGF.Builder.CreateBitCast(value, srcAddr.getElementType(),
4147180abc3dSDimitry Andric "icr.writeback-cast");
4148180abc3dSDimitry Andric
4149180abc3dSDimitry Andric // Perform the writeback.
4150809500fcSDimitry Andric
4151809500fcSDimitry Andric // If we have a "to use" value, it's something we need to emit a use
4152809500fcSDimitry Andric // of. This has to be carefully threaded in: if it's done after the
4153809500fcSDimitry Andric // release it's potentially undefined behavior (and the optimizer
4154809500fcSDimitry Andric // will ignore it), and if it happens before the retain then the
4155809500fcSDimitry Andric // optimizer could move the release there.
4156809500fcSDimitry Andric if (writeback.ToUse) {
4157809500fcSDimitry Andric assert(srcLV.getObjCLifetime() == Qualifiers::OCL_Strong);
4158809500fcSDimitry Andric
4159809500fcSDimitry Andric // Retain the new value. No need to block-copy here: the block's
4160809500fcSDimitry Andric // being passed up the stack.
4161809500fcSDimitry Andric value = CGF.EmitARCRetainNonBlock(value);
4162809500fcSDimitry Andric
4163809500fcSDimitry Andric // Emit the intrinsic use here.
4164809500fcSDimitry Andric CGF.EmitARCIntrinsicUse(writeback.ToUse);
4165809500fcSDimitry Andric
4166809500fcSDimitry Andric // Load the old value (primitively).
4167bfef3995SDimitry Andric llvm::Value *oldValue = CGF.EmitLoadOfScalar(srcLV, SourceLocation());
4168809500fcSDimitry Andric
4169809500fcSDimitry Andric // Put the new value in place (primitively).
4170809500fcSDimitry Andric CGF.EmitStoreOfScalar(value, srcLV, /*init*/ false);
4171809500fcSDimitry Andric
4172809500fcSDimitry Andric // Release the old value.
4173809500fcSDimitry Andric CGF.EmitARCRelease(oldValue, srcLV.isARCPreciseLifetime());
4174809500fcSDimitry Andric
4175809500fcSDimitry Andric // Otherwise, we can just do a normal lvalue store.
4176809500fcSDimitry Andric } else {
4177809500fcSDimitry Andric CGF.EmitStoreThroughLValue(RValue::get(value), srcLV);
4178809500fcSDimitry Andric }
4179180abc3dSDimitry Andric
4180180abc3dSDimitry Andric // Jump to the continuation block.
4181180abc3dSDimitry Andric if (!provablyNonNull)
4182180abc3dSDimitry Andric CGF.EmitBlock(contBB);
4183180abc3dSDimitry Andric }
4184180abc3dSDimitry Andric
emitWritebacks(CodeGenFunction & CGF,const CallArgList & args)4185180abc3dSDimitry Andric static void emitWritebacks(CodeGenFunction &CGF,
4186180abc3dSDimitry Andric const CallArgList &args) {
41879f4dbff6SDimitry Andric for (const auto &I : args.writebacks())
41889f4dbff6SDimitry Andric emitWriteback(CGF, I);
4189180abc3dSDimitry Andric }
4190180abc3dSDimitry Andric
deactivateArgCleanupsBeforeCall(CodeGenFunction & CGF,const CallArgList & CallArgs)4191bfef3995SDimitry Andric static void deactivateArgCleanupsBeforeCall(CodeGenFunction &CGF,
4192bfef3995SDimitry Andric const CallArgList &CallArgs) {
4193bfef3995SDimitry Andric ArrayRef<CallArgList::CallArgCleanup> Cleanups =
4194bfef3995SDimitry Andric CallArgs.getCleanupsToDeactivate();
4195bfef3995SDimitry Andric // Iterate in reverse to increase the likelihood of popping the cleanup.
419645b53394SDimitry Andric for (const auto &I : llvm::reverse(Cleanups)) {
419745b53394SDimitry Andric CGF.DeactivateCleanupBlock(I.Cleanup, I.IsActiveIP);
419845b53394SDimitry Andric I.IsActiveIP->eraseFromParent();
4199bfef3995SDimitry Andric }
4200bfef3995SDimitry Andric }
4201bfef3995SDimitry Andric
maybeGetUnaryAddrOfOperand(const Expr * E)4202809500fcSDimitry Andric static const Expr *maybeGetUnaryAddrOfOperand(const Expr *E) {
4203809500fcSDimitry Andric if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E->IgnoreParens()))
4204809500fcSDimitry Andric if (uop->getOpcode() == UO_AddrOf)
4205809500fcSDimitry Andric return uop->getSubExpr();
42069f4dbff6SDimitry Andric return nullptr;
4207809500fcSDimitry Andric }
4208809500fcSDimitry Andric
4209180abc3dSDimitry Andric /// Emit an argument that's being passed call-by-writeback. That is,
421045b53394SDimitry Andric /// we are passing the address of an __autoreleased temporary; it
421145b53394SDimitry Andric /// might be copy-initialized with the current value of the given
421245b53394SDimitry Andric /// address, but it will definitely be copied out of after the call.
emitWritebackArg(CodeGenFunction & CGF,CallArgList & args,const ObjCIndirectCopyRestoreExpr * CRE)4213180abc3dSDimitry Andric static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
4214180abc3dSDimitry Andric const ObjCIndirectCopyRestoreExpr *CRE) {
4215809500fcSDimitry Andric LValue srcLV;
4216809500fcSDimitry Andric
4217809500fcSDimitry Andric // Make an optimistic effort to emit the address as an l-value.
42182e645aa5SDimitry Andric // This can fail if the argument expression is more complicated.
4219809500fcSDimitry Andric if (const Expr *lvExpr = maybeGetUnaryAddrOfOperand(CRE->getSubExpr())) {
4220809500fcSDimitry Andric srcLV = CGF.EmitLValue(lvExpr);
4221809500fcSDimitry Andric
4222809500fcSDimitry Andric // Otherwise, just emit it as a scalar.
4223809500fcSDimitry Andric } else {
422445b53394SDimitry Andric Address srcAddr = CGF.EmitPointerWithAlignment(CRE->getSubExpr());
4225180abc3dSDimitry Andric
4226809500fcSDimitry Andric QualType srcAddrType =
4227809500fcSDimitry Andric CRE->getSubExpr()->getType()->castAs<PointerType>()->getPointeeType();
422845b53394SDimitry Andric srcLV = CGF.MakeAddrLValue(srcAddr, srcAddrType);
4229809500fcSDimitry Andric }
4230ac9a064cSDimitry Andric Address srcAddr = srcLV.getAddress();
4231809500fcSDimitry Andric
4232180abc3dSDimitry Andric // The dest and src types don't necessarily match in LLVM terms
4233180abc3dSDimitry Andric // because of the crazy ObjC compatibility rules.
4234180abc3dSDimitry Andric
423536981b17SDimitry Andric llvm::PointerType *destType =
4236180abc3dSDimitry Andric cast<llvm::PointerType>(CGF.ConvertType(CRE->getType()));
4237145449b1SDimitry Andric llvm::Type *destElemType =
4238145449b1SDimitry Andric CGF.ConvertTypeForMem(CRE->getType()->getPointeeType());
4239180abc3dSDimitry Andric
4240180abc3dSDimitry Andric // If the address is a constant null, just pass the appropriate null.
4241ac9a064cSDimitry Andric if (isProvablyNull(srcAddr.getBasePointer())) {
4242180abc3dSDimitry Andric args.add(RValue::get(llvm::ConstantPointerNull::get(destType)),
4243180abc3dSDimitry Andric CRE->getType());
4244180abc3dSDimitry Andric return;
4245180abc3dSDimitry Andric }
4246180abc3dSDimitry Andric
4247180abc3dSDimitry Andric // Create the temporary.
4248145449b1SDimitry Andric Address temp =
4249145449b1SDimitry Andric CGF.CreateTempAlloca(destElemType, CGF.getPointerAlign(), "icr.temp");
4250809500fcSDimitry Andric // Loading an l-value can introduce a cleanup if the l-value is __weak,
4251809500fcSDimitry Andric // and that cleanup will be conditional if we can't prove that the l-value
4252809500fcSDimitry Andric // isn't null, so we need to register a dominating point so that the cleanups
4253809500fcSDimitry Andric // system will make valid IR.
4254809500fcSDimitry Andric CodeGenFunction::ConditionalEvaluation condEval(CGF);
4255180abc3dSDimitry Andric
4256180abc3dSDimitry Andric // Zero-initialize it if we're not doing a copy-initialization.
4257180abc3dSDimitry Andric bool shouldCopy = CRE->shouldCopy();
4258180abc3dSDimitry Andric if (!shouldCopy) {
4259145449b1SDimitry Andric llvm::Value *null =
4260145449b1SDimitry Andric llvm::ConstantPointerNull::get(cast<llvm::PointerType>(destElemType));
4261180abc3dSDimitry Andric CGF.Builder.CreateStore(null, temp);
4262180abc3dSDimitry Andric }
4263180abc3dSDimitry Andric
42649f4dbff6SDimitry Andric llvm::BasicBlock *contBB = nullptr;
42659f4dbff6SDimitry Andric llvm::BasicBlock *originBB = nullptr;
4266180abc3dSDimitry Andric
4267180abc3dSDimitry Andric // If the address is *not* known to be non-null, we need to switch.
4268180abc3dSDimitry Andric llvm::Value *finalArgument;
4269180abc3dSDimitry Andric
4270ac9a064cSDimitry Andric bool provablyNonNull = isProvablyNonNull(srcAddr, CGF);
4271180abc3dSDimitry Andric
4272ac9a064cSDimitry Andric if (provablyNonNull) {
4273ac9a064cSDimitry Andric finalArgument = temp.emitRawPointer(CGF);
4274ac9a064cSDimitry Andric } else {
4275ac9a064cSDimitry Andric llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull");
4276ac9a064cSDimitry Andric
4277ac9a064cSDimitry Andric finalArgument = CGF.Builder.CreateSelect(
4278ac9a064cSDimitry Andric isNull, llvm::ConstantPointerNull::get(destType),
4279ac9a064cSDimitry Andric temp.emitRawPointer(CGF), "icr.argument");
4280180abc3dSDimitry Andric
4281180abc3dSDimitry Andric // If we need to copy, then the load has to be conditional, which
4282180abc3dSDimitry Andric // means we need control flow.
4283180abc3dSDimitry Andric if (shouldCopy) {
4284809500fcSDimitry Andric originBB = CGF.Builder.GetInsertBlock();
4285180abc3dSDimitry Andric contBB = CGF.createBasicBlock("icr.cont");
4286180abc3dSDimitry Andric llvm::BasicBlock *copyBB = CGF.createBasicBlock("icr.copy");
4287180abc3dSDimitry Andric CGF.Builder.CreateCondBr(isNull, contBB, copyBB);
4288180abc3dSDimitry Andric CGF.EmitBlock(copyBB);
4289809500fcSDimitry Andric condEval.begin(CGF);
4290180abc3dSDimitry Andric }
4291180abc3dSDimitry Andric }
4292180abc3dSDimitry Andric
42939f4dbff6SDimitry Andric llvm::Value *valueToUse = nullptr;
4294809500fcSDimitry Andric
4295180abc3dSDimitry Andric // Perform a copy if necessary.
4296180abc3dSDimitry Andric if (shouldCopy) {
4297bfef3995SDimitry Andric RValue srcRV = CGF.EmitLoadOfLValue(srcLV, SourceLocation());
4298180abc3dSDimitry Andric assert(srcRV.isScalar());
4299180abc3dSDimitry Andric
4300180abc3dSDimitry Andric llvm::Value *src = srcRV.getScalarVal();
4301145449b1SDimitry Andric src = CGF.Builder.CreateBitCast(src, destElemType, "icr.cast");
4302180abc3dSDimitry Andric
4303180abc3dSDimitry Andric // Use an ordinary store, not a store-to-lvalue.
4304180abc3dSDimitry Andric CGF.Builder.CreateStore(src, temp);
4305809500fcSDimitry Andric
4306809500fcSDimitry Andric // If optimization is enabled, and the value was held in a
4307809500fcSDimitry Andric // __strong variable, we need to tell the optimizer that this
4308809500fcSDimitry Andric // value has to stay alive until we're doing the store back.
4309809500fcSDimitry Andric // This is because the temporary is effectively unretained,
4310809500fcSDimitry Andric // and so otherwise we can violate the high-level semantics.
4311809500fcSDimitry Andric if (CGF.CGM.getCodeGenOpts().OptimizationLevel != 0 &&
4312809500fcSDimitry Andric srcLV.getObjCLifetime() == Qualifiers::OCL_Strong) {
4313809500fcSDimitry Andric valueToUse = src;
4314809500fcSDimitry Andric }
4315180abc3dSDimitry Andric }
4316180abc3dSDimitry Andric
4317180abc3dSDimitry Andric // Finish the control flow if we needed it.
4318809500fcSDimitry Andric if (shouldCopy && !provablyNonNull) {
4319809500fcSDimitry Andric llvm::BasicBlock *copyBB = CGF.Builder.GetInsertBlock();
4320180abc3dSDimitry Andric CGF.EmitBlock(contBB);
4321180abc3dSDimitry Andric
4322809500fcSDimitry Andric // Make a phi for the value to intrinsically use.
4323809500fcSDimitry Andric if (valueToUse) {
4324809500fcSDimitry Andric llvm::PHINode *phiToUse = CGF.Builder.CreatePHI(valueToUse->getType(), 2,
4325809500fcSDimitry Andric "icr.to-use");
4326809500fcSDimitry Andric phiToUse->addIncoming(valueToUse, copyBB);
4327809500fcSDimitry Andric phiToUse->addIncoming(llvm::UndefValue::get(valueToUse->getType()),
4328809500fcSDimitry Andric originBB);
4329809500fcSDimitry Andric valueToUse = phiToUse;
4330809500fcSDimitry Andric }
4331809500fcSDimitry Andric
4332809500fcSDimitry Andric condEval.end(CGF);
4333809500fcSDimitry Andric }
4334809500fcSDimitry Andric
4335809500fcSDimitry Andric args.addWriteback(srcLV, temp, valueToUse);
4336180abc3dSDimitry Andric args.add(RValue::get(finalArgument), CRE->getType());
4337180abc3dSDimitry Andric }
4338180abc3dSDimitry Andric
allocateArgumentMemory(CodeGenFunction & CGF)43399f4dbff6SDimitry Andric void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) {
4340bab175ecSDimitry Andric assert(!StackBase);
43419f4dbff6SDimitry Andric
43429f4dbff6SDimitry Andric // Save the stack.
4343b1c73532SDimitry Andric StackBase = CGF.Builder.CreateStackSave("inalloca.save");
43449f4dbff6SDimitry Andric }
43459f4dbff6SDimitry Andric
freeArgumentMemory(CodeGenFunction & CGF) const43469f4dbff6SDimitry Andric void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const {
43479f4dbff6SDimitry Andric if (StackBase) {
434845b53394SDimitry Andric // Restore the stack after the call.
4349b1c73532SDimitry Andric CGF.Builder.CreateStackRestore(StackBase);
43509f4dbff6SDimitry Andric }
43519f4dbff6SDimitry Andric }
43529f4dbff6SDimitry Andric
EmitNonNullArgCheck(RValue RV,QualType ArgType,SourceLocation ArgLoc,AbstractCallee AC,unsigned ParmNum)4353798321d8SDimitry Andric void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
4354798321d8SDimitry Andric SourceLocation ArgLoc,
43557442d6faSDimitry Andric AbstractCallee AC,
4356798321d8SDimitry Andric unsigned ParmNum) {
43577442d6faSDimitry Andric if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) ||
43587442d6faSDimitry Andric SanOpts.has(SanitizerKind::NullabilityArg)))
435906d4ba38SDimitry Andric return;
43607442d6faSDimitry Andric
43617442d6faSDimitry Andric // The param decl may be missing in a variadic function.
43627442d6faSDimitry Andric auto PVD = ParmNum < AC.getNumParams() ? AC.getParamDecl(ParmNum) : nullptr;
436306d4ba38SDimitry Andric unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum;
43647442d6faSDimitry Andric
43657442d6faSDimitry Andric // Prefer the nonnull attribute if it's present.
43667442d6faSDimitry Andric const NonNullAttr *NNAttr = nullptr;
43677442d6faSDimitry Andric if (SanOpts.has(SanitizerKind::NonnullAttribute))
43687442d6faSDimitry Andric NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo);
43697442d6faSDimitry Andric
43707442d6faSDimitry Andric bool CanCheckNullability = false;
4371ac9a064cSDimitry Andric if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD &&
4372ac9a064cSDimitry Andric !PVD->getType()->isRecordType()) {
4373e3b55780SDimitry Andric auto Nullability = PVD->getType()->getNullability();
43747442d6faSDimitry Andric CanCheckNullability = Nullability &&
43757442d6faSDimitry Andric *Nullability == NullabilityKind::NonNull &&
43767442d6faSDimitry Andric PVD->getTypeSourceInfo();
43777442d6faSDimitry Andric }
43787442d6faSDimitry Andric
43797442d6faSDimitry Andric if (!NNAttr && !CanCheckNullability)
438006d4ba38SDimitry Andric return;
43817442d6faSDimitry Andric
43827442d6faSDimitry Andric SourceLocation AttrLoc;
43837442d6faSDimitry Andric SanitizerMask CheckKind;
43847442d6faSDimitry Andric SanitizerHandler Handler;
43857442d6faSDimitry Andric if (NNAttr) {
43867442d6faSDimitry Andric AttrLoc = NNAttr->getLocation();
43877442d6faSDimitry Andric CheckKind = SanitizerKind::NonnullAttribute;
43887442d6faSDimitry Andric Handler = SanitizerHandler::NonnullArg;
43897442d6faSDimitry Andric } else {
43907442d6faSDimitry Andric AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc();
43917442d6faSDimitry Andric CheckKind = SanitizerKind::NullabilityArg;
43927442d6faSDimitry Andric Handler = SanitizerHandler::NullabilityArg;
43937442d6faSDimitry Andric }
43947442d6faSDimitry Andric
4395798321d8SDimitry Andric SanitizerScope SanScope(this);
4396b60736ecSDimitry Andric llvm::Value *Cond = EmitNonNullRValueCheck(RV, ArgType);
439706d4ba38SDimitry Andric llvm::Constant *StaticData[] = {
43987442d6faSDimitry Andric EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc),
4399798321d8SDimitry Andric llvm::ConstantInt::get(Int32Ty, ArgNo + 1),
440006d4ba38SDimitry Andric };
4401e3b55780SDimitry Andric EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, std::nullopt);
440206d4ba38SDimitry Andric }
440306d4ba38SDimitry Andric
EmitNonNullArgCheck(Address Addr,QualType ArgType,SourceLocation ArgLoc,AbstractCallee AC,unsigned ParmNum)4404ac9a064cSDimitry Andric void CodeGenFunction::EmitNonNullArgCheck(Address Addr, QualType ArgType,
4405ac9a064cSDimitry Andric SourceLocation ArgLoc,
4406ac9a064cSDimitry Andric AbstractCallee AC, unsigned ParmNum) {
4407ac9a064cSDimitry Andric if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) ||
4408ac9a064cSDimitry Andric SanOpts.has(SanitizerKind::NullabilityArg)))
4409ac9a064cSDimitry Andric return;
4410ac9a064cSDimitry Andric
4411ac9a064cSDimitry Andric EmitNonNullArgCheck(RValue::get(Addr, *this), ArgType, ArgLoc, AC, ParmNum);
4412ac9a064cSDimitry Andric }
4413ac9a064cSDimitry Andric
4414b60736ecSDimitry Andric // Check if the call is going to use the inalloca convention. This needs to
4415b60736ecSDimitry Andric // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged
4416b60736ecSDimitry Andric // later, so we can't check it directly.
hasInAllocaArgs(CodeGenModule & CGM,CallingConv ExplicitCC,ArrayRef<QualType> ArgTypes)4417b60736ecSDimitry Andric static bool hasInAllocaArgs(CodeGenModule &CGM, CallingConv ExplicitCC,
4418b60736ecSDimitry Andric ArrayRef<QualType> ArgTypes) {
4419344a3780SDimitry Andric // The Swift calling conventions don't go through the target-specific
4420344a3780SDimitry Andric // argument classification, they never use inalloca.
4421b60736ecSDimitry Andric // TODO: Consider limiting inalloca use to only calling conventions supported
4422b60736ecSDimitry Andric // by MSVC.
4423344a3780SDimitry Andric if (ExplicitCC == CC_Swift || ExplicitCC == CC_SwiftAsync)
4424b60736ecSDimitry Andric return false;
4425b60736ecSDimitry Andric if (!CGM.getTarget().getCXXABI().isMicrosoft())
4426b60736ecSDimitry Andric return false;
4427b60736ecSDimitry Andric return llvm::any_of(ArgTypes, [&](QualType Ty) {
4428b60736ecSDimitry Andric return isInAllocaArgument(CGM.getCXXABI(), Ty);
4429b60736ecSDimitry Andric });
4430b60736ecSDimitry Andric }
4431b60736ecSDimitry Andric
4432b60736ecSDimitry Andric #ifndef NDEBUG
4433b60736ecSDimitry Andric // Determine whether the given argument is an Objective-C method
4434b60736ecSDimitry Andric // that may have type parameters in its signature.
isObjCMethodWithTypeParams(const ObjCMethodDecl * method)4435b60736ecSDimitry Andric static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) {
4436b60736ecSDimitry Andric const DeclContext *dc = method->getDeclContext();
4437b60736ecSDimitry Andric if (const ObjCInterfaceDecl *classDecl = dyn_cast<ObjCInterfaceDecl>(dc)) {
4438b60736ecSDimitry Andric return classDecl->getTypeParamListAsWritten();
4439b60736ecSDimitry Andric }
4440b60736ecSDimitry Andric
4441b60736ecSDimitry Andric if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) {
4442b60736ecSDimitry Andric return catDecl->getTypeParamList();
4443b60736ecSDimitry Andric }
4444b60736ecSDimitry Andric
4445b60736ecSDimitry Andric return false;
4446b60736ecSDimitry Andric }
4447b60736ecSDimitry Andric #endif
4448b60736ecSDimitry Andric
4449b60736ecSDimitry Andric /// EmitCallArgs - Emit call arguments for a function.
EmitCallArgs(CallArgList & Args,PrototypeWrapper Prototype,llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,AbstractCallee AC,unsigned ParamsToSkip,EvaluationOrder Order)445045b53394SDimitry Andric void CodeGenFunction::EmitCallArgs(
4451b60736ecSDimitry Andric CallArgList &Args, PrototypeWrapper Prototype,
445245b53394SDimitry Andric llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
44537442d6faSDimitry Andric AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) {
4454b60736ecSDimitry Andric SmallVector<QualType, 16> ArgTypes;
4455b60736ecSDimitry Andric
4456b60736ecSDimitry Andric assert((ParamsToSkip == 0 || Prototype.P) &&
4457b60736ecSDimitry Andric "Can't skip parameters if type info is not provided");
4458b60736ecSDimitry Andric
4459b60736ecSDimitry Andric // This variable only captures *explicitly* written conventions, not those
4460b60736ecSDimitry Andric // applied by default via command line flags or target defaults, such as
4461b60736ecSDimitry Andric // thiscall, aapcs, stdcall via -mrtd, etc. Computing that correctly would
4462b60736ecSDimitry Andric // require knowing if this is a C++ instance method or being able to see
4463b60736ecSDimitry Andric // unprototyped FunctionTypes.
4464b60736ecSDimitry Andric CallingConv ExplicitCC = CC_C;
4465b60736ecSDimitry Andric
4466b60736ecSDimitry Andric // First, if a prototype was provided, use those argument types.
4467b60736ecSDimitry Andric bool IsVariadic = false;
4468b60736ecSDimitry Andric if (Prototype.P) {
4469b60736ecSDimitry Andric const auto *MD = Prototype.P.dyn_cast<const ObjCMethodDecl *>();
4470b60736ecSDimitry Andric if (MD) {
4471b60736ecSDimitry Andric IsVariadic = MD->isVariadic();
4472b60736ecSDimitry Andric ExplicitCC = getCallingConventionForDecl(
4473b60736ecSDimitry Andric MD, CGM.getTarget().getTriple().isOSWindows());
4474b60736ecSDimitry Andric ArgTypes.assign(MD->param_type_begin() + ParamsToSkip,
4475b60736ecSDimitry Andric MD->param_type_end());
4476b60736ecSDimitry Andric } else {
4477b60736ecSDimitry Andric const auto *FPT = Prototype.P.get<const FunctionProtoType *>();
4478b60736ecSDimitry Andric IsVariadic = FPT->isVariadic();
4479b60736ecSDimitry Andric ExplicitCC = FPT->getExtInfo().getCC();
4480b60736ecSDimitry Andric ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip,
4481b60736ecSDimitry Andric FPT->param_type_end());
4482b60736ecSDimitry Andric }
4483b60736ecSDimitry Andric
4484b60736ecSDimitry Andric #ifndef NDEBUG
4485b60736ecSDimitry Andric // Check that the prototyped types match the argument expression types.
4486b60736ecSDimitry Andric bool isGenericMethod = MD && isObjCMethodWithTypeParams(MD);
4487b60736ecSDimitry Andric CallExpr::const_arg_iterator Arg = ArgRange.begin();
4488b60736ecSDimitry Andric for (QualType Ty : ArgTypes) {
4489b60736ecSDimitry Andric assert(Arg != ArgRange.end() && "Running over edge of argument list!");
4490b60736ecSDimitry Andric assert(
4491b60736ecSDimitry Andric (isGenericMethod || Ty->isVariablyModifiedType() ||
4492b60736ecSDimitry Andric Ty.getNonReferenceType()->isObjCRetainableType() ||
4493b60736ecSDimitry Andric getContext()
4494b60736ecSDimitry Andric .getCanonicalType(Ty.getNonReferenceType())
4495b60736ecSDimitry Andric .getTypePtr() ==
4496b60736ecSDimitry Andric getContext().getCanonicalType((*Arg)->getType()).getTypePtr()) &&
4497b60736ecSDimitry Andric "type mismatch in call argument!");
4498b60736ecSDimitry Andric ++Arg;
4499b60736ecSDimitry Andric }
4500b60736ecSDimitry Andric
4501b60736ecSDimitry Andric // Either we've emitted all the call args, or we have a call to variadic
4502b60736ecSDimitry Andric // function.
4503b60736ecSDimitry Andric assert((Arg == ArgRange.end() || IsVariadic) &&
4504b60736ecSDimitry Andric "Extra arguments in non-variadic function!");
4505b60736ecSDimitry Andric #endif
4506b60736ecSDimitry Andric }
4507b60736ecSDimitry Andric
4508b60736ecSDimitry Andric // If we still have any arguments, emit them using the type of the argument.
450977fc4c14SDimitry Andric for (auto *A : llvm::drop_begin(ArgRange, ArgTypes.size()))
4510b60736ecSDimitry Andric ArgTypes.push_back(IsVariadic ? getVarArgType(A) : A->getType());
451145b53394SDimitry Andric assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin()));
451245b53394SDimitry Andric
4513b60736ecSDimitry Andric // We must evaluate arguments from right to left in the MS C++ ABI,
4514bab175ecSDimitry Andric // because arguments are destroyed left to right in the callee. As a special
4515bab175ecSDimitry Andric // case, there are certain language constructs that require left-to-right
4516bab175ecSDimitry Andric // evaluation, and in those cases we consider the evaluation order requirement
4517bab175ecSDimitry Andric // to trump the "destruction order is reverse construction order" guarantee.
4518bab175ecSDimitry Andric bool LeftToRight =
4519bab175ecSDimitry Andric CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()
4520bab175ecSDimitry Andric ? Order == EvaluationOrder::ForceLeftToRight
4521bab175ecSDimitry Andric : Order != EvaluationOrder::ForceRightToLeft;
4522bab175ecSDimitry Andric
45237442d6faSDimitry Andric auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg,
45247442d6faSDimitry Andric RValue EmittedArg) {
45257442d6faSDimitry Andric if (!AC.hasFunctionDecl() || I >= AC.getNumParams())
45267442d6faSDimitry Andric return;
45277442d6faSDimitry Andric auto *PS = AC.getParamDecl(I)->getAttr<PassObjectSizeAttr>();
45287442d6faSDimitry Andric if (PS == nullptr)
45297442d6faSDimitry Andric return;
45307442d6faSDimitry Andric
45317442d6faSDimitry Andric const auto &Context = getContext();
45327442d6faSDimitry Andric auto SizeTy = Context.getSizeType();
45337442d6faSDimitry Andric auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
45347442d6faSDimitry Andric assert(EmittedArg.getScalarVal() && "We emitted nothing for the arg?");
45357442d6faSDimitry Andric llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T,
453622989816SDimitry Andric EmittedArg.getScalarVal(),
453722989816SDimitry Andric PS->isDynamic());
45387442d6faSDimitry Andric Args.add(RValue::get(V), SizeTy);
45397442d6faSDimitry Andric // If we're emitting args in reverse, be sure to do so with
45407442d6faSDimitry Andric // pass_object_size, as well.
45417442d6faSDimitry Andric if (!LeftToRight)
45427442d6faSDimitry Andric std::swap(Args.back(), *(&Args.back() - 1));
45437442d6faSDimitry Andric };
45447442d6faSDimitry Andric
45459f4dbff6SDimitry Andric // Insert a stack save if we're going to need any inalloca args.
4546b60736ecSDimitry Andric if (hasInAllocaArgs(CGM, ExplicitCC, ArgTypes)) {
4547b60736ecSDimitry Andric assert(getTarget().getTriple().getArch() == llvm::Triple::x86 &&
4548b60736ecSDimitry Andric "inalloca only supported on x86");
45499f4dbff6SDimitry Andric Args.allocateArgumentMemory(*this);
45509f4dbff6SDimitry Andric }
45519f4dbff6SDimitry Andric
4552bab175ecSDimitry Andric // Evaluate each argument in the appropriate order.
4553bab175ecSDimitry Andric size_t CallArgsStart = Args.size();
4554bab175ecSDimitry Andric for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) {
4555bab175ecSDimitry Andric unsigned Idx = LeftToRight ? I : E - I - 1;
4556bab175ecSDimitry Andric CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx;
45577442d6faSDimitry Andric unsigned InitialArgSize = Args.size();
4558cf1b4019SDimitry Andric // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of
4559cf1b4019SDimitry Andric // the argument and parameter match or the objc method is parameterized.
4560cf1b4019SDimitry Andric assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) ||
4561cf1b4019SDimitry Andric getContext().hasSameUnqualifiedType((*Arg)->getType(),
4562cf1b4019SDimitry Andric ArgTypes[Idx]) ||
4563cf1b4019SDimitry Andric (isa<ObjCMethodDecl>(AC.getDecl()) &&
4564cf1b4019SDimitry Andric isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) &&
4565cf1b4019SDimitry Andric "Argument and parameter types don't match");
4566bab175ecSDimitry Andric EmitCallArg(Args, *Arg, ArgTypes[Idx]);
45677442d6faSDimitry Andric // In particular, we depend on it being the last arg in Args, and the
45687442d6faSDimitry Andric // objectsize bits depend on there only being one arg if !LeftToRight.
45697442d6faSDimitry Andric assert(InitialArgSize + 1 == Args.size() &&
45707442d6faSDimitry Andric "The code below depends on only adding one arg per EmitCallArg");
45717442d6faSDimitry Andric (void)InitialArgSize;
457248675466SDimitry Andric // Since pointer argument are never emitted as LValue, it is safe to emit
457348675466SDimitry Andric // non-null argument check for r-value only.
457448675466SDimitry Andric if (!Args.back().hasLValue()) {
457548675466SDimitry Andric RValue RVArg = Args.back().getKnownRValue();
45767442d6faSDimitry Andric EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC,
45777442d6faSDimitry Andric ParamsToSkip + Idx);
45787442d6faSDimitry Andric // @llvm.objectsize should never have side-effects and shouldn't need
45797442d6faSDimitry Andric // destruction/cleanups, so we can safely "emit" it after its arg,
45807442d6faSDimitry Andric // regardless of right-to-leftness
45817442d6faSDimitry Andric MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg);
4582bab175ecSDimitry Andric }
458348675466SDimitry Andric }
4584bab175ecSDimitry Andric
4585bab175ecSDimitry Andric if (!LeftToRight) {
45869f4dbff6SDimitry Andric // Un-reverse the arguments we just evaluated so they match up with the LLVM
45879f4dbff6SDimitry Andric // IR function.
45889f4dbff6SDimitry Andric std::reverse(Args.begin() + CallArgsStart, Args.end());
45899f4dbff6SDimitry Andric }
45909f4dbff6SDimitry Andric }
45919f4dbff6SDimitry Andric
45929f4dbff6SDimitry Andric namespace {
45939f4dbff6SDimitry Andric
459445b53394SDimitry Andric struct DestroyUnpassedArg final : EHScopeStack::Cleanup {
DestroyUnpassedArg__anon748148590f11::DestroyUnpassedArg459545b53394SDimitry Andric DestroyUnpassedArg(Address Addr, QualType Ty)
45969f4dbff6SDimitry Andric : Addr(Addr), Ty(Ty) {}
45979f4dbff6SDimitry Andric
459845b53394SDimitry Andric Address Addr;
45999f4dbff6SDimitry Andric QualType Ty;
46009f4dbff6SDimitry Andric
Emit__anon748148590f11::DestroyUnpassedArg46019f4dbff6SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
460248675466SDimitry Andric QualType::DestructionKind DtorKind = Ty.isDestructedType();
460348675466SDimitry Andric if (DtorKind == QualType::DK_cxx_destructor) {
46049f4dbff6SDimitry Andric const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
46059f4dbff6SDimitry Andric assert(!Dtor->isTrivial());
46069f4dbff6SDimitry Andric CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false,
460722989816SDimitry Andric /*Delegating=*/false, Addr, Ty);
460848675466SDimitry Andric } else {
460948675466SDimitry Andric CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty));
461048675466SDimitry Andric }
46119f4dbff6SDimitry Andric }
46129f4dbff6SDimitry Andric };
46139f4dbff6SDimitry Andric
46145e20cdd8SDimitry Andric struct DisableDebugLocationUpdates {
46155e20cdd8SDimitry Andric CodeGenFunction &CGF;
46165e20cdd8SDimitry Andric bool disabledDebugInfo;
DisableDebugLocationUpdates__anon748148590f11::DisableDebugLocationUpdates46175e20cdd8SDimitry Andric DisableDebugLocationUpdates(CodeGenFunction &CGF, const Expr *E) : CGF(CGF) {
46185e20cdd8SDimitry Andric if ((disabledDebugInfo = isa<CXXDefaultArgExpr>(E) && CGF.getDebugInfo()))
46195e20cdd8SDimitry Andric CGF.disableDebugInfo();
46205e20cdd8SDimitry Andric }
~DisableDebugLocationUpdates__anon748148590f11::DisableDebugLocationUpdates46215e20cdd8SDimitry Andric ~DisableDebugLocationUpdates() {
46225e20cdd8SDimitry Andric if (disabledDebugInfo)
46235e20cdd8SDimitry Andric CGF.enableDebugInfo();
46245e20cdd8SDimitry Andric }
46255e20cdd8SDimitry Andric };
46265e20cdd8SDimitry Andric
462745b53394SDimitry Andric } // end anonymous namespace
462845b53394SDimitry Andric
getRValue(CodeGenFunction & CGF) const462948675466SDimitry Andric RValue CallArg::getRValue(CodeGenFunction &CGF) const {
463048675466SDimitry Andric if (!HasLV)
463148675466SDimitry Andric return RV;
463248675466SDimitry Andric LValue Copy = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty), Ty);
463348675466SDimitry Andric CGF.EmitAggregateCopy(Copy, LV, Ty, AggValueSlot::DoesNotOverlap,
463448675466SDimitry Andric LV.isVolatile());
463548675466SDimitry Andric IsUsed = true;
4636ac9a064cSDimitry Andric return RValue::getAggregate(Copy.getAddress());
463748675466SDimitry Andric }
463848675466SDimitry Andric
copyInto(CodeGenFunction & CGF,Address Addr) const463948675466SDimitry Andric void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const {
464048675466SDimitry Andric LValue Dst = CGF.MakeAddrLValue(Addr, Ty);
464148675466SDimitry Andric if (!HasLV && RV.isScalar())
464222989816SDimitry Andric CGF.EmitStoreOfScalar(RV.getScalarVal(), Dst, /*isInit=*/true);
464348675466SDimitry Andric else if (!HasLV && RV.isComplex())
464448675466SDimitry Andric CGF.EmitStoreOfComplex(RV.getComplexVal(), Dst, /*init=*/true);
464548675466SDimitry Andric else {
4646ac9a064cSDimitry Andric auto Addr = HasLV ? LV.getAddress() : RV.getAggregateAddress();
464748675466SDimitry Andric LValue SrcLV = CGF.MakeAddrLValue(Addr, Ty);
464848675466SDimitry Andric // We assume that call args are never copied into subobjects.
464948675466SDimitry Andric CGF.EmitAggregateCopy(Dst, SrcLV, Ty, AggValueSlot::DoesNotOverlap,
465048675466SDimitry Andric HasLV ? LV.isVolatileQualified()
465148675466SDimitry Andric : RV.isVolatileQualified());
465248675466SDimitry Andric }
465348675466SDimitry Andric IsUsed = true;
465448675466SDimitry Andric }
465548675466SDimitry Andric
EmitCallArg(CallArgList & args,const Expr * E,QualType type)465601af97d3SDimitry Andric void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
465701af97d3SDimitry Andric QualType type) {
46585e20cdd8SDimitry Andric DisableDebugLocationUpdates Dis(*this, E);
4659180abc3dSDimitry Andric if (const ObjCIndirectCopyRestoreExpr *CRE
4660180abc3dSDimitry Andric = dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
466113cc256eSDimitry Andric assert(getLangOpts().ObjCAutoRefCount);
4662180abc3dSDimitry Andric return emitWritebackArg(*this, args, CRE);
4663180abc3dSDimitry Andric }
4664180abc3dSDimitry Andric
466536981b17SDimitry Andric assert(type->isReferenceType() == E->isGLValue() &&
466636981b17SDimitry Andric "reference binding to unmaterialized r-value!");
466736981b17SDimitry Andric
466836981b17SDimitry Andric if (E->isGLValue()) {
466936981b17SDimitry Andric assert(E->getObjectKind() == OK_Ordinary);
4670bfef3995SDimitry Andric return args.add(EmitReferenceBindingToExpr(E), type);
467136981b17SDimitry Andric }
467201af97d3SDimitry Andric
4673bfef3995SDimitry Andric bool HasAggregateEvalKind = hasAggregateEvaluationKind(type);
4674bfef3995SDimitry Andric
4675bfef3995SDimitry Andric // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
4676bfef3995SDimitry Andric // However, we still have to push an EH-only cleanup in case we unwind before
4677bfef3995SDimitry Andric // we make it to the call.
4678344a3780SDimitry Andric if (type->isRecordType() &&
4679519fc96cSDimitry Andric type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
46809f4dbff6SDimitry Andric // If we're using inalloca, use the argument memory. Otherwise, use a
46819f4dbff6SDimitry Andric // temporary.
468277fc4c14SDimitry Andric AggValueSlot Slot = args.isUsingInAlloca()
468377fc4c14SDimitry Andric ? createPlaceholderSlot(*this, type) : CreateAggTemp(type, "agg.tmp");
46849f4dbff6SDimitry Andric
4685ac9a064cSDimitry Andric bool DestroyedInCallee = true, NeedsCleanup = true;
468648675466SDimitry Andric if (const auto *RD = type->getAsCXXRecordDecl())
468748675466SDimitry Andric DestroyedInCallee = RD->hasNonTrivialDestructor();
468848675466SDimitry Andric else
4689ac9a064cSDimitry Andric NeedsCleanup = type.isDestructedType();
469048675466SDimitry Andric
46919f4dbff6SDimitry Andric if (DestroyedInCallee)
4692bfef3995SDimitry Andric Slot.setExternallyDestructed();
46939f4dbff6SDimitry Andric
4694bfef3995SDimitry Andric EmitAggExpr(E, Slot);
4695bfef3995SDimitry Andric RValue RV = Slot.asRValue();
4696bfef3995SDimitry Andric args.add(RV, type);
4697bfef3995SDimitry Andric
4698ac9a064cSDimitry Andric if (DestroyedInCallee && NeedsCleanup) {
46999f4dbff6SDimitry Andric // Create a no-op GEP between the placeholder and the cleanup so we can
47009f4dbff6SDimitry Andric // RAUW it successfully. It also serves as a marker of the first
47019f4dbff6SDimitry Andric // instruction where the cleanup is active.
4702ac9a064cSDimitry Andric pushFullExprCleanup<DestroyUnpassedArg>(NormalAndEHCleanup,
4703ac9a064cSDimitry Andric Slot.getAddress(), type);
4704bfef3995SDimitry Andric // This unreachable is a temporary marker which will be removed later.
4705ac9a064cSDimitry Andric llvm::Instruction *IsActive =
4706ac9a064cSDimitry Andric Builder.CreateFlagLoad(llvm::Constant::getNullValue(Int8PtrTy));
4707145449b1SDimitry Andric args.addArgCleanupDeactivation(EHStack.stable_begin(), IsActive);
4708bfef3995SDimitry Andric }
47099f4dbff6SDimitry Andric return;
4710bfef3995SDimitry Andric }
4711bfef3995SDimitry Andric
4712bfef3995SDimitry Andric if (HasAggregateEvalKind && isa<ImplicitCastExpr>(E) &&
4713ac9a064cSDimitry Andric cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue &&
4714ac9a064cSDimitry Andric !type->isArrayParameterType()) {
471529cafa66SDimitry Andric LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr());
471629cafa66SDimitry Andric assert(L.isSimple());
471748675466SDimitry Andric args.addUncopiedAggregate(L, type);
471829cafa66SDimitry Andric return;
471929cafa66SDimitry Andric }
472029cafa66SDimitry Andric
472101af97d3SDimitry Andric args.add(EmitAnyExprToTemp(E), type);
4722ec2b103cSEd Schouten }
4723ec2b103cSEd Schouten
getVarArgType(const Expr * Arg)472406d4ba38SDimitry Andric QualType CodeGenFunction::getVarArgType(const Expr *Arg) {
472506d4ba38SDimitry Andric // System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
472606d4ba38SDimitry Andric // implicitly widens null pointer constants that are arguments to varargs
472706d4ba38SDimitry Andric // functions to pointer-sized ints.
472806d4ba38SDimitry Andric if (!getTarget().getTriple().isOSWindows())
472906d4ba38SDimitry Andric return Arg->getType();
473006d4ba38SDimitry Andric
473106d4ba38SDimitry Andric if (Arg->getType()->isIntegerType() &&
473206d4ba38SDimitry Andric getContext().getTypeSize(Arg->getType()) <
4733e3b55780SDimitry Andric getContext().getTargetInfo().getPointerWidth(LangAS::Default) &&
473406d4ba38SDimitry Andric Arg->isNullPointerConstant(getContext(),
473506d4ba38SDimitry Andric Expr::NPC_ValueDependentIsNotNull)) {
473606d4ba38SDimitry Andric return getContext().getIntPtrType();
473706d4ba38SDimitry Andric }
473806d4ba38SDimitry Andric
473906d4ba38SDimitry Andric return Arg->getType();
474006d4ba38SDimitry Andric }
474106d4ba38SDimitry Andric
4742dbe13110SDimitry Andric // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
4743dbe13110SDimitry Andric // optimizer it can aggressively ignore unwind edges.
4744dbe13110SDimitry Andric void
AddObjCARCExceptionMetadata(llvm::Instruction * Inst)4745dbe13110SDimitry Andric CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) {
4746dbe13110SDimitry Andric if (CGM.getCodeGenOpts().OptimizationLevel != 0 &&
4747dbe13110SDimitry Andric !CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
4748dbe13110SDimitry Andric Inst->setMetadata("clang.arc.no_objc_arc_exceptions",
4749dbe13110SDimitry Andric CGM.getNoObjCARCExceptionsMetadata());
4750dbe13110SDimitry Andric }
4751dbe13110SDimitry Andric
4752809500fcSDimitry Andric /// Emits a call to the given no-arguments nounwind runtime function.
4753809500fcSDimitry Andric llvm::CallInst *
EmitNounwindRuntimeCall(llvm::FunctionCallee callee,const llvm::Twine & name)475422989816SDimitry Andric CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee,
4755809500fcSDimitry Andric const llvm::Twine &name) {
4756ac9a064cSDimitry Andric return EmitNounwindRuntimeCall(callee, ArrayRef<llvm::Value *>(), name);
4757809500fcSDimitry Andric }
4758809500fcSDimitry Andric
4759809500fcSDimitry Andric /// Emits a call to the given nounwind runtime function.
4760809500fcSDimitry Andric llvm::CallInst *
EmitNounwindRuntimeCall(llvm::FunctionCallee callee,ArrayRef<Address> args,const llvm::Twine & name)476122989816SDimitry Andric CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee,
4762ac9a064cSDimitry Andric ArrayRef<Address> args,
4763ac9a064cSDimitry Andric const llvm::Twine &name) {
4764ac9a064cSDimitry Andric SmallVector<llvm::Value *, 3> values;
4765ac9a064cSDimitry Andric for (auto arg : args)
4766ac9a064cSDimitry Andric values.push_back(arg.emitRawPointer(*this));
4767ac9a064cSDimitry Andric return EmitNounwindRuntimeCall(callee, values, name);
4768ac9a064cSDimitry Andric }
4769ac9a064cSDimitry Andric
4770ac9a064cSDimitry Andric llvm::CallInst *
EmitNounwindRuntimeCall(llvm::FunctionCallee callee,ArrayRef<llvm::Value * > args,const llvm::Twine & name)4771ac9a064cSDimitry Andric CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee,
4772809500fcSDimitry Andric ArrayRef<llvm::Value *> args,
4773809500fcSDimitry Andric const llvm::Twine &name) {
4774809500fcSDimitry Andric llvm::CallInst *call = EmitRuntimeCall(callee, args, name);
4775809500fcSDimitry Andric call->setDoesNotThrow();
4776809500fcSDimitry Andric return call;
4777809500fcSDimitry Andric }
4778809500fcSDimitry Andric
4779809500fcSDimitry Andric /// Emits a simple call (never an invoke) to the given no-arguments
4780809500fcSDimitry Andric /// runtime function.
EmitRuntimeCall(llvm::FunctionCallee callee,const llvm::Twine & name)478122989816SDimitry Andric llvm::CallInst *CodeGenFunction::EmitRuntimeCall(llvm::FunctionCallee callee,
4782809500fcSDimitry Andric const llvm::Twine &name) {
4783e3b55780SDimitry Andric return EmitRuntimeCall(callee, std::nullopt, name);
4784809500fcSDimitry Andric }
4785809500fcSDimitry Andric
478645b53394SDimitry Andric // Calls which may throw must have operand bundles indicating which funclet
478745b53394SDimitry Andric // they are nested within.
478848675466SDimitry Andric SmallVector<llvm::OperandBundleDef, 1>
getBundlesForFunclet(llvm::Value * Callee)478948675466SDimitry Andric CodeGenFunction::getBundlesForFunclet(llvm::Value *Callee) {
47902b6b257fSDimitry Andric // There is no need for a funclet operand bundle if we aren't inside a
47912b6b257fSDimitry Andric // funclet.
479245b53394SDimitry Andric if (!CurrentFuncletPad)
479308e8dd7bSDimitry Andric return (SmallVector<llvm::OperandBundleDef, 1>());
479445b53394SDimitry Andric
479508e8dd7bSDimitry Andric // Skip intrinsics which cannot throw (as long as they don't lower into
479608e8dd7bSDimitry Andric // regular function calls in the course of IR transformations).
479708e8dd7bSDimitry Andric if (auto *CalleeFn = dyn_cast<llvm::Function>(Callee->stripPointerCasts())) {
479808e8dd7bSDimitry Andric if (CalleeFn->isIntrinsic() && CalleeFn->doesNotThrow()) {
479908e8dd7bSDimitry Andric auto IID = CalleeFn->getIntrinsicID();
480008e8dd7bSDimitry Andric if (!llvm::IntrinsicInst::mayLowerToFunctionCall(IID))
480108e8dd7bSDimitry Andric return (SmallVector<llvm::OperandBundleDef, 1>());
480208e8dd7bSDimitry Andric }
480308e8dd7bSDimitry Andric }
480445b53394SDimitry Andric
480508e8dd7bSDimitry Andric SmallVector<llvm::OperandBundleDef, 1> BundleList;
480645b53394SDimitry Andric BundleList.emplace_back("funclet", CurrentFuncletPad);
480748675466SDimitry Andric return BundleList;
480845b53394SDimitry Andric }
480945b53394SDimitry Andric
48102b6b257fSDimitry Andric /// Emits a simple call (never an invoke) to the given runtime function.
EmitRuntimeCall(llvm::FunctionCallee callee,ArrayRef<llvm::Value * > args,const llvm::Twine & name)481122989816SDimitry Andric llvm::CallInst *CodeGenFunction::EmitRuntimeCall(llvm::FunctionCallee callee,
48122b6b257fSDimitry Andric ArrayRef<llvm::Value *> args,
48132b6b257fSDimitry Andric const llvm::Twine &name) {
481422989816SDimitry Andric llvm::CallInst *call = Builder.CreateCall(
481522989816SDimitry Andric callee, args, getBundlesForFunclet(callee.getCallee()), name);
48162b6b257fSDimitry Andric call->setCallingConv(getRuntimeCC());
4817ac9a064cSDimitry Andric
4818ac9a064cSDimitry Andric if (CGM.shouldEmitConvergenceTokens() && call->isConvergent())
4819ac9a064cSDimitry Andric return addControlledConvergenceToken(call);
48202b6b257fSDimitry Andric return call;
48212b6b257fSDimitry Andric }
48222b6b257fSDimitry Andric
4823809500fcSDimitry Andric /// Emits a call or invoke to the given noreturn runtime function.
EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee,ArrayRef<llvm::Value * > args)482422989816SDimitry Andric void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(
482522989816SDimitry Andric llvm::FunctionCallee callee, ArrayRef<llvm::Value *> args) {
482648675466SDimitry Andric SmallVector<llvm::OperandBundleDef, 1> BundleList =
482722989816SDimitry Andric getBundlesForFunclet(callee.getCallee());
482845b53394SDimitry Andric
4829809500fcSDimitry Andric if (getInvokeDest()) {
4830809500fcSDimitry Andric llvm::InvokeInst *invoke =
4831809500fcSDimitry Andric Builder.CreateInvoke(callee,
4832809500fcSDimitry Andric getUnreachableBlock(),
4833809500fcSDimitry Andric getInvokeDest(),
483445b53394SDimitry Andric args,
483545b53394SDimitry Andric BundleList);
4836809500fcSDimitry Andric invoke->setDoesNotReturn();
4837809500fcSDimitry Andric invoke->setCallingConv(getRuntimeCC());
4838809500fcSDimitry Andric } else {
483945b53394SDimitry Andric llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList);
4840809500fcSDimitry Andric call->setDoesNotReturn();
4841809500fcSDimitry Andric call->setCallingConv(getRuntimeCC());
4842809500fcSDimitry Andric Builder.CreateUnreachable();
4843809500fcSDimitry Andric }
4844809500fcSDimitry Andric }
4845809500fcSDimitry Andric
48462b6b257fSDimitry Andric /// Emits a call or invoke instruction to the given nullary runtime function.
484722989816SDimitry Andric llvm::CallBase *
EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee,const Twine & name)484822989816SDimitry Andric CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee,
4849809500fcSDimitry Andric const Twine &name) {
4850e3b55780SDimitry Andric return EmitRuntimeCallOrInvoke(callee, std::nullopt, name);
4851809500fcSDimitry Andric }
4852809500fcSDimitry Andric
4853809500fcSDimitry Andric /// Emits a call or invoke instruction to the given runtime function.
485422989816SDimitry Andric llvm::CallBase *
EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee,ArrayRef<llvm::Value * > args,const Twine & name)485522989816SDimitry Andric CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee,
4856809500fcSDimitry Andric ArrayRef<llvm::Value *> args,
4857809500fcSDimitry Andric const Twine &name) {
485822989816SDimitry Andric llvm::CallBase *call = EmitCallOrInvoke(callee, args, name);
485922989816SDimitry Andric call->setCallingConv(getRuntimeCC());
486022989816SDimitry Andric return call;
4861809500fcSDimitry Andric }
4862809500fcSDimitry Andric
48634ba67500SRoman Divacky /// Emits a call or invoke instruction to the given function, depending
48644ba67500SRoman Divacky /// on the current state of the EH stack.
EmitCallOrInvoke(llvm::FunctionCallee Callee,ArrayRef<llvm::Value * > Args,const Twine & Name)486522989816SDimitry Andric llvm::CallBase *CodeGenFunction::EmitCallOrInvoke(llvm::FunctionCallee Callee,
486636981b17SDimitry Andric ArrayRef<llvm::Value *> Args,
486736981b17SDimitry Andric const Twine &Name) {
48684ba67500SRoman Divacky llvm::BasicBlock *InvokeDest = getInvokeDest();
486948675466SDimitry Andric SmallVector<llvm::OperandBundleDef, 1> BundleList =
487022989816SDimitry Andric getBundlesForFunclet(Callee.getCallee());
48714ba67500SRoman Divacky
487222989816SDimitry Andric llvm::CallBase *Inst;
4873dbe13110SDimitry Andric if (!InvokeDest)
48742b6b257fSDimitry Andric Inst = Builder.CreateCall(Callee, Args, BundleList, Name);
4875dbe13110SDimitry Andric else {
48764ba67500SRoman Divacky llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont");
48772b6b257fSDimitry Andric Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, BundleList,
48782b6b257fSDimitry Andric Name);
48794ba67500SRoman Divacky EmitBlock(ContBB);
4880dbe13110SDimitry Andric }
4881dbe13110SDimitry Andric
4882dbe13110SDimitry Andric // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
4883dbe13110SDimitry Andric // optimizer it can aggressively ignore unwind edges.
4884dbe13110SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount)
4885dbe13110SDimitry Andric AddObjCARCExceptionMetadata(Inst);
4886dbe13110SDimitry Andric
488722989816SDimitry Andric return Inst;
48884ba67500SRoman Divacky }
48894ba67500SRoman Divacky
deferPlaceholderReplacement(llvm::Instruction * Old,llvm::Value * New)48909f4dbff6SDimitry Andric void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old,
48919f4dbff6SDimitry Andric llvm::Value *New) {
4892344a3780SDimitry Andric DeferredReplacements.push_back(
4893344a3780SDimitry Andric std::make_pair(llvm::WeakTrackingVH(Old), New));
48949f4dbff6SDimitry Andric }
4895180abc3dSDimitry Andric
4896cfca06d7SDimitry Andric namespace {
4897cfca06d7SDimitry Andric
4898cfca06d7SDimitry Andric /// Specify given \p NewAlign as the alignment of return value attribute. If
4899cfca06d7SDimitry Andric /// such attribute already exists, re-set it to the maximal one of two options.
4900e3b55780SDimitry Andric [[nodiscard]] llvm::AttributeList
maybeRaiseRetAlignmentAttribute(llvm::LLVMContext & Ctx,const llvm::AttributeList & Attrs,llvm::Align NewAlign)4901cfca06d7SDimitry Andric maybeRaiseRetAlignmentAttribute(llvm::LLVMContext &Ctx,
4902cfca06d7SDimitry Andric const llvm::AttributeList &Attrs,
4903cfca06d7SDimitry Andric llvm::Align NewAlign) {
4904cfca06d7SDimitry Andric llvm::Align CurAlign = Attrs.getRetAlignment().valueOrOne();
4905cfca06d7SDimitry Andric if (CurAlign >= NewAlign)
4906cfca06d7SDimitry Andric return Attrs;
4907cfca06d7SDimitry Andric llvm::Attribute AlignAttr = llvm::Attribute::getWithAlignment(Ctx, NewAlign);
4908c0981da4SDimitry Andric return Attrs.removeRetAttribute(Ctx, llvm::Attribute::AttrKind::Alignment)
4909c0981da4SDimitry Andric .addRetAttribute(Ctx, AlignAttr);
4910cfca06d7SDimitry Andric }
4911cfca06d7SDimitry Andric
4912cfca06d7SDimitry Andric template <typename AlignedAttrTy> class AbstractAssumeAlignedAttrEmitter {
4913cfca06d7SDimitry Andric protected:
4914cfca06d7SDimitry Andric CodeGenFunction &CGF;
4915cfca06d7SDimitry Andric
4916cfca06d7SDimitry Andric /// We do nothing if this is, or becomes, nullptr.
4917cfca06d7SDimitry Andric const AlignedAttrTy *AA = nullptr;
4918cfca06d7SDimitry Andric
4919cfca06d7SDimitry Andric llvm::Value *Alignment = nullptr; // May or may not be a constant.
4920cfca06d7SDimitry Andric llvm::ConstantInt *OffsetCI = nullptr; // Constant, hopefully zero.
4921cfca06d7SDimitry Andric
AbstractAssumeAlignedAttrEmitter(CodeGenFunction & CGF_,const Decl * FuncDecl)4922cfca06d7SDimitry Andric AbstractAssumeAlignedAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl)
4923cfca06d7SDimitry Andric : CGF(CGF_) {
4924cfca06d7SDimitry Andric if (!FuncDecl)
4925cfca06d7SDimitry Andric return;
4926cfca06d7SDimitry Andric AA = FuncDecl->getAttr<AlignedAttrTy>();
4927cfca06d7SDimitry Andric }
4928cfca06d7SDimitry Andric
4929cfca06d7SDimitry Andric public:
4930cfca06d7SDimitry Andric /// If we can, materialize the alignment as an attribute on return value.
4931e3b55780SDimitry Andric [[nodiscard]] llvm::AttributeList
TryEmitAsCallSiteAttribute(const llvm::AttributeList & Attrs)4932cfca06d7SDimitry Andric TryEmitAsCallSiteAttribute(const llvm::AttributeList &Attrs) {
4933cfca06d7SDimitry Andric if (!AA || OffsetCI || CGF.SanOpts.has(SanitizerKind::Alignment))
4934cfca06d7SDimitry Andric return Attrs;
4935cfca06d7SDimitry Andric const auto *AlignmentCI = dyn_cast<llvm::ConstantInt>(Alignment);
4936cfca06d7SDimitry Andric if (!AlignmentCI)
4937cfca06d7SDimitry Andric return Attrs;
4938cfca06d7SDimitry Andric // We may legitimately have non-power-of-2 alignment here.
4939cfca06d7SDimitry Andric // If so, this is UB land, emit it via `@llvm.assume` instead.
4940cfca06d7SDimitry Andric if (!AlignmentCI->getValue().isPowerOf2())
4941cfca06d7SDimitry Andric return Attrs;
4942cfca06d7SDimitry Andric llvm::AttributeList NewAttrs = maybeRaiseRetAlignmentAttribute(
4943cfca06d7SDimitry Andric CGF.getLLVMContext(), Attrs,
4944cfca06d7SDimitry Andric llvm::Align(
4945cfca06d7SDimitry Andric AlignmentCI->getLimitedValue(llvm::Value::MaximumAlignment)));
4946cfca06d7SDimitry Andric AA = nullptr; // We're done. Disallow doing anything else.
4947cfca06d7SDimitry Andric return NewAttrs;
4948cfca06d7SDimitry Andric }
4949cfca06d7SDimitry Andric
4950cfca06d7SDimitry Andric /// Emit alignment assumption.
4951cfca06d7SDimitry Andric /// This is a general fallback that we take if either there is an offset,
4952cfca06d7SDimitry Andric /// or the alignment is variable or we are sanitizing for alignment.
EmitAsAnAssumption(SourceLocation Loc,QualType RetTy,RValue & Ret)4953cfca06d7SDimitry Andric void EmitAsAnAssumption(SourceLocation Loc, QualType RetTy, RValue &Ret) {
4954cfca06d7SDimitry Andric if (!AA)
4955cfca06d7SDimitry Andric return;
4956cfca06d7SDimitry Andric CGF.emitAlignmentAssumption(Ret.getScalarVal(), RetTy, Loc,
4957cfca06d7SDimitry Andric AA->getLocation(), Alignment, OffsetCI);
4958cfca06d7SDimitry Andric AA = nullptr; // We're done. Disallow doing anything else.
4959cfca06d7SDimitry Andric }
4960cfca06d7SDimitry Andric };
4961cfca06d7SDimitry Andric
4962cfca06d7SDimitry Andric /// Helper data structure to emit `AssumeAlignedAttr`.
4963cfca06d7SDimitry Andric class AssumeAlignedAttrEmitter final
4964cfca06d7SDimitry Andric : public AbstractAssumeAlignedAttrEmitter<AssumeAlignedAttr> {
4965cfca06d7SDimitry Andric public:
AssumeAlignedAttrEmitter(CodeGenFunction & CGF_,const Decl * FuncDecl)4966cfca06d7SDimitry Andric AssumeAlignedAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl)
4967cfca06d7SDimitry Andric : AbstractAssumeAlignedAttrEmitter(CGF_, FuncDecl) {
4968cfca06d7SDimitry Andric if (!AA)
4969cfca06d7SDimitry Andric return;
4970cfca06d7SDimitry Andric // It is guaranteed that the alignment/offset are constants.
4971cfca06d7SDimitry Andric Alignment = cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AA->getAlignment()));
4972cfca06d7SDimitry Andric if (Expr *Offset = AA->getOffset()) {
4973cfca06d7SDimitry Andric OffsetCI = cast<llvm::ConstantInt>(CGF.EmitScalarExpr(Offset));
4974cfca06d7SDimitry Andric if (OffsetCI->isNullValue()) // Canonicalize zero offset to no offset.
4975cfca06d7SDimitry Andric OffsetCI = nullptr;
4976cfca06d7SDimitry Andric }
4977cfca06d7SDimitry Andric }
4978cfca06d7SDimitry Andric };
4979cfca06d7SDimitry Andric
4980cfca06d7SDimitry Andric /// Helper data structure to emit `AllocAlignAttr`.
4981cfca06d7SDimitry Andric class AllocAlignAttrEmitter final
4982cfca06d7SDimitry Andric : public AbstractAssumeAlignedAttrEmitter<AllocAlignAttr> {
4983cfca06d7SDimitry Andric public:
AllocAlignAttrEmitter(CodeGenFunction & CGF_,const Decl * FuncDecl,const CallArgList & CallArgs)4984cfca06d7SDimitry Andric AllocAlignAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl,
4985cfca06d7SDimitry Andric const CallArgList &CallArgs)
4986cfca06d7SDimitry Andric : AbstractAssumeAlignedAttrEmitter(CGF_, FuncDecl) {
4987cfca06d7SDimitry Andric if (!AA)
4988cfca06d7SDimitry Andric return;
4989cfca06d7SDimitry Andric // Alignment may or may not be a constant, and that is okay.
4990cfca06d7SDimitry Andric Alignment = CallArgs[AA->getParamIndex().getLLVMIndex()]
4991cfca06d7SDimitry Andric .getRValue(CGF)
4992cfca06d7SDimitry Andric .getScalarVal();
4993cfca06d7SDimitry Andric }
4994cfca06d7SDimitry Andric };
4995cfca06d7SDimitry Andric
4996cfca06d7SDimitry Andric } // namespace
4997cfca06d7SDimitry Andric
getMaxVectorWidth(const llvm::Type * Ty)4998145449b1SDimitry Andric static unsigned getMaxVectorWidth(const llvm::Type *Ty) {
4999145449b1SDimitry Andric if (auto *VT = dyn_cast<llvm::VectorType>(Ty))
5000e3b55780SDimitry Andric return VT->getPrimitiveSizeInBits().getKnownMinValue();
5001145449b1SDimitry Andric if (auto *AT = dyn_cast<llvm::ArrayType>(Ty))
5002145449b1SDimitry Andric return getMaxVectorWidth(AT->getElementType());
5003145449b1SDimitry Andric
5004145449b1SDimitry Andric unsigned MaxVectorWidth = 0;
5005145449b1SDimitry Andric if (auto *ST = dyn_cast<llvm::StructType>(Ty))
5006145449b1SDimitry Andric for (auto *I : ST->elements())
5007145449b1SDimitry Andric MaxVectorWidth = std::max(MaxVectorWidth, getMaxVectorWidth(I));
5008145449b1SDimitry Andric return MaxVectorWidth;
5009145449b1SDimitry Andric }
5010145449b1SDimitry Andric
EmitCall(const CGFunctionInfo & CallInfo,const CGCallee & Callee,ReturnValueSlot ReturnValue,const CallArgList & CallArgs,llvm::CallBase ** callOrInvoke,bool IsMustTail,SourceLocation Loc,bool IsVirtualFunctionPointerThunk)5011ec2b103cSEd Schouten RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
5012bab175ecSDimitry Andric const CGCallee &Callee,
5013abe15e55SRoman Divacky ReturnValueSlot ReturnValue,
5014ec2b103cSEd Schouten const CallArgList &CallArgs,
5015344a3780SDimitry Andric llvm::CallBase **callOrInvoke, bool IsMustTail,
5016ac9a064cSDimitry Andric SourceLocation Loc,
5017ac9a064cSDimitry Andric bool IsVirtualFunctionPointerThunk) {
5018ec2b103cSEd Schouten // FIXME: We no longer need the types from CallArgs; lift up and simplify.
5019ec2b103cSEd Schouten
502048675466SDimitry Andric assert(Callee.isOrdinary() || Callee.isVirtual());
5021bab175ecSDimitry Andric
5022ec2b103cSEd Schouten // Handle struct-return functions by passing a pointer to the
5023ec2b103cSEd Schouten // location that we would like to return into.
5024ec2b103cSEd Schouten QualType RetTy = CallInfo.getReturnType();
5025ec2b103cSEd Schouten const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
50267ef7bab7SEd Schouten
502722989816SDimitry Andric llvm::FunctionType *IRFuncTy = getTypes().GetFunctionType(CallInfo);
502822989816SDimitry Andric
502922989816SDimitry Andric const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl();
5030cfca06d7SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
503122989816SDimitry Andric // We can only guarantee that a function is called from the correct
503222989816SDimitry Andric // context/function based on the appropriate target attributes,
503322989816SDimitry Andric // so only check in the case where we have both always_inline and target
503422989816SDimitry Andric // since otherwise we could be making a conditional call after a check for
503522989816SDimitry Andric // the proper cpu features (and it won't cause code generation issues due to
503622989816SDimitry Andric // function based code generation).
503722989816SDimitry Andric if (TargetDecl->hasAttr<AlwaysInlineAttr>() &&
50387fa27ce4SDimitry Andric (TargetDecl->hasAttr<TargetAttr>() ||
50397fa27ce4SDimitry Andric (CurFuncDecl && CurFuncDecl->hasAttr<TargetAttr>())))
504022989816SDimitry Andric checkTargetFeatures(Loc, FD);
5041ac9a064cSDimitry Andric }
504222989816SDimitry Andric
5043cfca06d7SDimitry Andric // Some architectures (such as x86-64) have the ABI changed based on
5044cfca06d7SDimitry Andric // attribute-target/features. Give them a chance to diagnose.
5045cfca06d7SDimitry Andric CGM.getTargetCodeGenInfo().checkFunctionCallABI(
5046ac9a064cSDimitry Andric CGM, Loc, dyn_cast_or_null<FunctionDecl>(CurCodeDecl),
5047ac9a064cSDimitry Andric dyn_cast_or_null<FunctionDecl>(TargetDecl), CallArgs, RetTy);
5048cfca06d7SDimitry Andric
5049bab175ecSDimitry Andric // 1. Set up the arguments.
50507ef7bab7SEd Schouten
50519f4dbff6SDimitry Andric // If we're using inalloca, insert the allocation after the stack save.
50529f4dbff6SDimitry Andric // FIXME: Do this earlier rather than hacking it in here!
5053ac9a064cSDimitry Andric RawAddress ArgMemory = RawAddress::invalid();
50549f4dbff6SDimitry Andric if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) {
50557442d6faSDimitry Andric const llvm::DataLayout &DL = CGM.getDataLayout();
50569f4dbff6SDimitry Andric llvm::Instruction *IP = CallArgs.getStackBase();
50579f4dbff6SDimitry Andric llvm::AllocaInst *AI;
50589f4dbff6SDimitry Andric if (IP) {
50599f4dbff6SDimitry Andric IP = IP->getNextNode();
50607442d6faSDimitry Andric AI = new llvm::AllocaInst(ArgStruct, DL.getAllocaAddrSpace(),
50617442d6faSDimitry Andric "argmem", IP);
50629f4dbff6SDimitry Andric } else {
50639f4dbff6SDimitry Andric AI = CreateTempAlloca(ArgStruct, "argmem");
50649f4dbff6SDimitry Andric }
506545b53394SDimitry Andric auto Align = CallInfo.getArgStructAlignment();
5066519fc96cSDimitry Andric AI->setAlignment(Align.getAsAlign());
50679f4dbff6SDimitry Andric AI->setUsedWithInAlloca(true);
50689f4dbff6SDimitry Andric assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca());
5069ac9a064cSDimitry Andric ArgMemory = RawAddress(AI, ArgStruct, Align);
50709f4dbff6SDimitry Andric }
50719f4dbff6SDimitry Andric
507206d4ba38SDimitry Andric ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo);
507306d4ba38SDimitry Andric SmallVector<llvm::Value *, 16> IRCallArgs(IRFunctionArgs.totalIRArgs());
507406d4ba38SDimitry Andric
50757ef7bab7SEd Schouten // If the call returns a temporary with struct return, create a temporary
5076abe15e55SRoman Divacky // alloca to hold the result, unless one is given to us.
507745b53394SDimitry Andric Address SRetPtr = Address::invalid();
5078ac9a064cSDimitry Andric RawAddress SRetAlloca = RawAddress::invalid();
507948675466SDimitry Andric llvm::Value *UnusedReturnSizePtr = nullptr;
50802b6b257fSDimitry Andric if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
5081ac9a064cSDimitry Andric if (IsVirtualFunctionPointerThunk && RetAI.isIndirect()) {
5082ac9a064cSDimitry Andric SRetPtr = makeNaturalAddressForPointer(CurFn->arg_begin() +
5083ac9a064cSDimitry Andric IRFunctionArgs.getSRetArgNo(),
5084ac9a064cSDimitry Andric RetTy, CharUnits::fromQuantity(1));
5085ac9a064cSDimitry Andric } else if (!ReturnValue.isNull()) {
5086ac9a064cSDimitry Andric SRetPtr = ReturnValue.getAddress();
508745b53394SDimitry Andric } else {
508848675466SDimitry Andric SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca);
5089798321d8SDimitry Andric if (HaveInsertPoint() && ReturnValue.isUnused()) {
5090344a3780SDimitry Andric llvm::TypeSize size =
5091798321d8SDimitry Andric CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
509248675466SDimitry Andric UnusedReturnSizePtr = EmitLifetimeStart(size, SRetAlloca.getPointer());
5093798321d8SDimitry Andric }
5094798321d8SDimitry Andric }
509506d4ba38SDimitry Andric if (IRFunctionArgs.hasSRetArg()) {
5096ac9a064cSDimitry Andric IRCallArgs[IRFunctionArgs.getSRetArgNo()] =
5097ac9a064cSDimitry Andric getAsNaturalPointerTo(SRetPtr, RetTy);
50982b6b257fSDimitry Andric } else if (RetAI.isInAlloca()) {
509922989816SDimitry Andric Address Addr =
510022989816SDimitry Andric Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex());
5101ac9a064cSDimitry Andric Builder.CreateStore(getAsNaturalPointerTo(SRetPtr, RetTy), Addr);
51029f4dbff6SDimitry Andric }
5103abe15e55SRoman Divacky }
5104ec2b103cSEd Schouten
5105ac9a064cSDimitry Andric RawAddress swiftErrorTemp = RawAddress::invalid();
51062b6b257fSDimitry Andric Address swiftErrorArg = Address::invalid();
51072b6b257fSDimitry Andric
5108519fc96cSDimitry Andric // When passing arguments using temporary allocas, we need to add the
5109519fc96cSDimitry Andric // appropriate lifetime markers. This vector keeps track of all the lifetime
5110519fc96cSDimitry Andric // markers that need to be ended right after the call.
5111519fc96cSDimitry Andric SmallVector<CallLifetimeEnd, 2> CallLifetimeEndAfterCall;
5112519fc96cSDimitry Andric
5113bab175ecSDimitry Andric // Translate all of the arguments as necessary to match the IR lowering.
5114ec2b103cSEd Schouten assert(CallInfo.arg_size() == CallArgs.size() &&
5115ec2b103cSEd Schouten "Mismatch between function signature & arguments.");
511606d4ba38SDimitry Andric unsigned ArgNo = 0;
5117ec2b103cSEd Schouten CGFunctionInfo::const_arg_iterator info_it = CallInfo.arg_begin();
5118ec2b103cSEd Schouten for (CallArgList::const_iterator I = CallArgs.begin(), E = CallArgs.end();
511906d4ba38SDimitry Andric I != E; ++I, ++info_it, ++ArgNo) {
5120ec2b103cSEd Schouten const ABIArgInfo &ArgInfo = info_it->info;
5121ec2b103cSEd Schouten
512213cc256eSDimitry Andric // Insert a padding argument to ensure proper alignment.
512306d4ba38SDimitry Andric if (IRFunctionArgs.hasPaddingArg(ArgNo))
512406d4ba38SDimitry Andric IRCallArgs[IRFunctionArgs.getPaddingArgNo(ArgNo)] =
512506d4ba38SDimitry Andric llvm::UndefValue::get(ArgInfo.getPaddingType());
512606d4ba38SDimitry Andric
512706d4ba38SDimitry Andric unsigned FirstIRArg, NumIRArgs;
512806d4ba38SDimitry Andric std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
512913cc256eSDimitry Andric
5130e3b55780SDimitry Andric bool ArgHasMaybeUndefAttr =
5131e3b55780SDimitry Andric IsArgumentMaybeUndef(TargetDecl, CallInfo.getNumRequiredArgs(), ArgNo);
5132e3b55780SDimitry Andric
5133ec2b103cSEd Schouten switch (ArgInfo.getKind()) {
51349f4dbff6SDimitry Andric case ABIArgInfo::InAlloca: {
513506d4ba38SDimitry Andric assert(NumIRArgs == 0);
51369f4dbff6SDimitry Andric assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
513748675466SDimitry Andric if (I->isAggregate()) {
5138ac9a064cSDimitry Andric RawAddress Addr = I->hasLValue()
5139ac9a064cSDimitry Andric ? I->getKnownLValue().getAddress()
514048675466SDimitry Andric : I->getKnownRValue().getAggregateAddress();
51419f4dbff6SDimitry Andric llvm::Instruction *Placeholder =
514248675466SDimitry Andric cast<llvm::Instruction>(Addr.getPointer());
5143cfca06d7SDimitry Andric
5144cfca06d7SDimitry Andric if (!ArgInfo.getInAllocaIndirect()) {
5145cfca06d7SDimitry Andric // Replace the placeholder with the appropriate argument slot GEP.
51469f4dbff6SDimitry Andric CGBuilderTy::InsertPoint IP = Builder.saveIP();
51479f4dbff6SDimitry Andric Builder.SetInsertPoint(Placeholder);
5148cfca06d7SDimitry Andric Addr = Builder.CreateStructGEP(ArgMemory,
5149cfca06d7SDimitry Andric ArgInfo.getInAllocaFieldIndex());
51509f4dbff6SDimitry Andric Builder.restoreIP(IP);
5151cfca06d7SDimitry Andric } else {
5152cfca06d7SDimitry Andric // For indirect things such as overaligned structs, replace the
5153cfca06d7SDimitry Andric // placeholder with a regular aggregate temporary alloca. Store the
5154cfca06d7SDimitry Andric // address of this alloca into the struct.
5155cfca06d7SDimitry Andric Addr = CreateMemTemp(info_it->type, "inalloca.indirect.tmp");
5156cfca06d7SDimitry Andric Address ArgSlot = Builder.CreateStructGEP(
5157cfca06d7SDimitry Andric ArgMemory, ArgInfo.getInAllocaFieldIndex());
5158cfca06d7SDimitry Andric Builder.CreateStore(Addr.getPointer(), ArgSlot);
5159cfca06d7SDimitry Andric }
516045b53394SDimitry Andric deferPlaceholderReplacement(Placeholder, Addr.getPointer());
5161cfca06d7SDimitry Andric } else if (ArgInfo.getInAllocaIndirect()) {
5162cfca06d7SDimitry Andric // Make a temporary alloca and store the address of it into the argument
5163cfca06d7SDimitry Andric // struct.
5164ac9a064cSDimitry Andric RawAddress Addr = CreateMemTempWithoutCast(
5165cfca06d7SDimitry Andric I->Ty, getContext().getTypeAlignInChars(I->Ty),
5166cfca06d7SDimitry Andric "indirect-arg-temp");
5167cfca06d7SDimitry Andric I->copyInto(*this, Addr);
5168cfca06d7SDimitry Andric Address ArgSlot =
5169cfca06d7SDimitry Andric Builder.CreateStructGEP(ArgMemory, ArgInfo.getInAllocaFieldIndex());
5170cfca06d7SDimitry Andric Builder.CreateStore(Addr.getPointer(), ArgSlot);
51719f4dbff6SDimitry Andric } else {
51729f4dbff6SDimitry Andric // Store the RValue into the argument struct.
517322989816SDimitry Andric Address Addr =
517422989816SDimitry Andric Builder.CreateStructGEP(ArgMemory, ArgInfo.getInAllocaFieldIndex());
51757fa27ce4SDimitry Andric Addr = Addr.withElementType(ConvertTypeForMem(I->Ty));
517648675466SDimitry Andric I->copyInto(*this, Addr);
51779f4dbff6SDimitry Andric }
517806d4ba38SDimitry Andric break;
51799f4dbff6SDimitry Andric }
51809f4dbff6SDimitry Andric
5181b60736ecSDimitry Andric case ABIArgInfo::Indirect:
5182b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased: {
518306d4ba38SDimitry Andric assert(NumIRArgs == 1);
5184ac9a064cSDimitry Andric if (I->isAggregate()) {
5185180abc3dSDimitry Andric // We want to avoid creating an unnecessary temporary+copy here;
5186809500fcSDimitry Andric // however, we need one in three cases:
5187180abc3dSDimitry Andric // 1. If the argument is not byval, and we are required to copy the
5188180abc3dSDimitry Andric // source. (This case doesn't occur on any common architecture.)
5189180abc3dSDimitry Andric // 2. If the argument is byval, RV is not sufficiently aligned, and
5190180abc3dSDimitry Andric // we cannot force it to be sufficiently aligned.
519148675466SDimitry Andric // 3. If the argument is byval, but RV is not located in default
519248675466SDimitry Andric // or alloca address space.
519348675466SDimitry Andric Address Addr = I->hasLValue()
5194ac9a064cSDimitry Andric ? I->getKnownLValue().getAddress()
519548675466SDimitry Andric : I->getKnownRValue().getAggregateAddress();
519645b53394SDimitry Andric CharUnits Align = ArgInfo.getIndirectAlign();
519713cc256eSDimitry Andric const llvm::DataLayout *TD = &CGM.getDataLayout();
519848675466SDimitry Andric
519948675466SDimitry Andric assert((FirstIRArg >= IRFuncTy->getNumParams() ||
520048675466SDimitry Andric IRFuncTy->getParamType(FirstIRArg)->getPointerAddressSpace() ==
520148675466SDimitry Andric TD->getAllocaAddrSpace()) &&
520248675466SDimitry Andric "indirect argument must be in alloca address space");
520348675466SDimitry Andric
520448675466SDimitry Andric bool NeedCopy = false;
520548675466SDimitry Andric if (Addr.getAlignment() < Align &&
5206ac9a064cSDimitry Andric llvm::getOrEnforceKnownAlignment(Addr.emitRawPointer(*this),
5207ac9a064cSDimitry Andric Align.getAsAlign(),
5208ac9a064cSDimitry Andric *TD) < Align.getAsAlign()) {
520948675466SDimitry Andric NeedCopy = true;
521048675466SDimitry Andric } else if (I->hasLValue()) {
521148675466SDimitry Andric auto LV = I->getKnownLValue();
521248675466SDimitry Andric auto AS = LV.getAddressSpace();
5213676fbe81SDimitry Andric
5214b1c73532SDimitry Andric bool isByValOrRef =
5215b1c73532SDimitry Andric ArgInfo.isIndirectAliased() || ArgInfo.getIndirectByVal();
5216b1c73532SDimitry Andric
5217b1c73532SDimitry Andric if (!isByValOrRef ||
5218706b4fc4SDimitry Andric (LV.getAlignment() < getContext().getTypeAlignInChars(I->Ty))) {
5219676fbe81SDimitry Andric NeedCopy = true;
5220676fbe81SDimitry Andric }
5221676fbe81SDimitry Andric if (!getLangOpts().OpenCL) {
5222b1c73532SDimitry Andric if ((isByValOrRef &&
5223676fbe81SDimitry Andric (AS != LangAS::Default &&
5224676fbe81SDimitry Andric AS != CGM.getASTAllocaAddressSpace()))) {
522548675466SDimitry Andric NeedCopy = true;
522648675466SDimitry Andric }
522748675466SDimitry Andric }
5228676fbe81SDimitry Andric // For OpenCL even if RV is located in default or alloca address space
5229676fbe81SDimitry Andric // we don't want to perform address space cast for it.
5230b1c73532SDimitry Andric else if ((isByValOrRef &&
5231676fbe81SDimitry Andric Addr.getType()->getAddressSpace() != IRFuncTy->
5232676fbe81SDimitry Andric getParamType(FirstIRArg)->getPointerAddressSpace())) {
5233676fbe81SDimitry Andric NeedCopy = true;
5234676fbe81SDimitry Andric }
5235676fbe81SDimitry Andric }
5236676fbe81SDimitry Andric
5237ac9a064cSDimitry Andric if (!NeedCopy) {
5238ac9a064cSDimitry Andric // Skip the extra memcpy call.
5239ac9a064cSDimitry Andric llvm::Value *V = getAsNaturalPointerTo(Addr, I->Ty);
5240ac9a064cSDimitry Andric auto *T = llvm::PointerType::get(
5241ac9a064cSDimitry Andric CGM.getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace());
5242ac9a064cSDimitry Andric
5243ac9a064cSDimitry Andric llvm::Value *Val = getTargetHooks().performAddrSpaceCast(
5244ac9a064cSDimitry Andric *this, V, LangAS::Default, CGM.getASTAllocaAddressSpace(), T,
5245ac9a064cSDimitry Andric true);
5246e3b55780SDimitry Andric if (ArgHasMaybeUndefAttr)
5247ac9a064cSDimitry Andric Val = Builder.CreateFreeze(Val);
5248ac9a064cSDimitry Andric IRCallArgs[FirstIRArg] = Val;
5249ac9a064cSDimitry Andric break;
5250ac9a064cSDimitry Andric }
5251ac9a064cSDimitry Andric }
5252ac9a064cSDimitry Andric
5253ac9a064cSDimitry Andric // For non-aggregate args and aggregate args meeting conditions above
5254ac9a064cSDimitry Andric // we need to create an aligned temporary, and copy to it.
5255ac9a064cSDimitry Andric RawAddress AI = CreateMemTempWithoutCast(
5256ac9a064cSDimitry Andric I->Ty, ArgInfo.getIndirectAlign(), "byval-temp");
5257ac9a064cSDimitry Andric llvm::Value *Val = getAsNaturalPointerTo(AI, I->Ty);
5258ac9a064cSDimitry Andric if (ArgHasMaybeUndefAttr)
5259ac9a064cSDimitry Andric Val = Builder.CreateFreeze(Val);
5260e3b55780SDimitry Andric IRCallArgs[FirstIRArg] = Val;
5261519fc96cSDimitry Andric
5262519fc96cSDimitry Andric // Emit lifetime markers for the temporary alloca.
5263344a3780SDimitry Andric llvm::TypeSize ByvalTempElementSize =
5264519fc96cSDimitry Andric CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
5265519fc96cSDimitry Andric llvm::Value *LifetimeSize =
5266519fc96cSDimitry Andric EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
5267519fc96cSDimitry Andric
5268519fc96cSDimitry Andric // Add cleanup code to emit the end lifetime marker after the call.
5269519fc96cSDimitry Andric if (LifetimeSize) // In case we disabled lifetime markers.
5270519fc96cSDimitry Andric CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize);
5271519fc96cSDimitry Andric
5272519fc96cSDimitry Andric // Generate the copy.
527348675466SDimitry Andric I->copyInto(*this, AI);
5274ec2b103cSEd Schouten break;
5275ec2b103cSEd Schouten }
5276ec2b103cSEd Schouten
5277ec2b103cSEd Schouten case ABIArgInfo::Ignore:
527806d4ba38SDimitry Andric assert(NumIRArgs == 0);
5279ec2b103cSEd Schouten break;
5280ec2b103cSEd Schouten
52813d1dcd9bSDimitry Andric case ABIArgInfo::Extend:
52823d1dcd9bSDimitry Andric case ABIArgInfo::Direct: {
52833d1dcd9bSDimitry Andric if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
52843d1dcd9bSDimitry Andric ArgInfo.getCoerceToType() == ConvertType(info_it->type) &&
52853d1dcd9bSDimitry Andric ArgInfo.getDirectOffset() == 0) {
528606d4ba38SDimitry Andric assert(NumIRArgs == 1);
5287180abc3dSDimitry Andric llvm::Value *V;
528848675466SDimitry Andric if (!I->isAggregate())
528948675466SDimitry Andric V = I->getKnownRValue().getScalarVal();
52903d1dcd9bSDimitry Andric else
529148675466SDimitry Andric V = Builder.CreateLoad(
5292ac9a064cSDimitry Andric I->hasLValue() ? I->getKnownLValue().getAddress()
529348675466SDimitry Andric : I->getKnownRValue().getAggregateAddress());
5294180abc3dSDimitry Andric
52952b6b257fSDimitry Andric // Implement swifterror by copying into a new swifterror argument.
52962b6b257fSDimitry Andric // We'll write back in the normal path out of the call.
52972b6b257fSDimitry Andric if (CallInfo.getExtParameterInfo(ArgNo).getABI()
52982b6b257fSDimitry Andric == ParameterABI::SwiftErrorResult) {
52992b6b257fSDimitry Andric assert(!swiftErrorTemp.isValid() && "multiple swifterror args");
53002b6b257fSDimitry Andric
53012b6b257fSDimitry Andric QualType pointeeTy = I->Ty->getPointeeType();
5302ac9a064cSDimitry Andric swiftErrorArg = makeNaturalAddressForPointer(
5303ac9a064cSDimitry Andric V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy));
53042b6b257fSDimitry Andric
53052b6b257fSDimitry Andric swiftErrorTemp =
53062b6b257fSDimitry Andric CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp");
53072b6b257fSDimitry Andric V = swiftErrorTemp.getPointer();
53082b6b257fSDimitry Andric cast<llvm::AllocaInst>(V)->setSwiftError(true);
53092b6b257fSDimitry Andric
53102b6b257fSDimitry Andric llvm::Value *errorValue = Builder.CreateLoad(swiftErrorArg);
53112b6b257fSDimitry Andric Builder.CreateStore(errorValue, swiftErrorTemp);
53122b6b257fSDimitry Andric }
53132b6b257fSDimitry Andric
531406d4ba38SDimitry Andric // We might have to widen integers, but we should never truncate.
531506d4ba38SDimitry Andric if (ArgInfo.getCoerceToType() != V->getType() &&
531606d4ba38SDimitry Andric V->getType()->isIntegerTy())
531706d4ba38SDimitry Andric V = Builder.CreateZExt(V, ArgInfo.getCoerceToType());
531806d4ba38SDimitry Andric
5319180abc3dSDimitry Andric // If the argument doesn't match, perform a bitcast to coerce it. This
5320180abc3dSDimitry Andric // can happen due to trivial type mismatches.
532106d4ba38SDimitry Andric if (FirstIRArg < IRFuncTy->getNumParams() &&
532206d4ba38SDimitry Andric V->getType() != IRFuncTy->getParamType(FirstIRArg))
532306d4ba38SDimitry Andric V = Builder.CreateBitCast(V, IRFuncTy->getParamType(FirstIRArg));
53242b6b257fSDimitry Andric
5325e3b55780SDimitry Andric if (ArgHasMaybeUndefAttr)
5326e3b55780SDimitry Andric V = Builder.CreateFreeze(V);
532706d4ba38SDimitry Andric IRCallArgs[FirstIRArg] = V;
53283d1dcd9bSDimitry Andric break;
53293d1dcd9bSDimitry Andric }
53303d1dcd9bSDimitry Andric
5331ac9a064cSDimitry Andric llvm::StructType *STy =
5332ac9a064cSDimitry Andric dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
5333ac9a064cSDimitry Andric if (STy && ArgInfo.isDirect() && !ArgInfo.getCanBeFlattened()) {
5334ac9a064cSDimitry Andric llvm::Type *SrcTy = ConvertTypeForMem(I->Ty);
5335ac9a064cSDimitry Andric [[maybe_unused]] llvm::TypeSize SrcTypeSize =
5336ac9a064cSDimitry Andric CGM.getDataLayout().getTypeAllocSize(SrcTy);
5337ac9a064cSDimitry Andric [[maybe_unused]] llvm::TypeSize DstTypeSize =
5338ac9a064cSDimitry Andric CGM.getDataLayout().getTypeAllocSize(STy);
5339ac9a064cSDimitry Andric if (STy->containsHomogeneousScalableVectorTypes()) {
5340ac9a064cSDimitry Andric assert(SrcTypeSize == DstTypeSize &&
5341ac9a064cSDimitry Andric "Only allow non-fractional movement of structure with "
5342ac9a064cSDimitry Andric "homogeneous scalable vector type");
5343ac9a064cSDimitry Andric
5344ac9a064cSDimitry Andric IRCallArgs[FirstIRArg] = I->getKnownRValue().getScalarVal();
5345ac9a064cSDimitry Andric break;
5346ac9a064cSDimitry Andric }
5347ac9a064cSDimitry Andric }
5348ac9a064cSDimitry Andric
5349ec2b103cSEd Schouten // FIXME: Avoid the conversion through memory if possible.
535045b53394SDimitry Andric Address Src = Address::invalid();
535148675466SDimitry Andric if (!I->isAggregate()) {
535245b53394SDimitry Andric Src = CreateMemTemp(I->Ty, "coerce");
535348675466SDimitry Andric I->copyInto(*this, Src);
535451ece4aaSDimitry Andric } else {
5355ac9a064cSDimitry Andric Src = I->hasLValue() ? I->getKnownLValue().getAddress()
535648675466SDimitry Andric : I->getKnownRValue().getAggregateAddress();
535751ece4aaSDimitry Andric }
53584ba67500SRoman Divacky
53593d1dcd9bSDimitry Andric // If the value is offset in memory, apply the offset now.
536045b53394SDimitry Andric Src = emitAddressAtOffset(*this, Src, ArgInfo);
53613d1dcd9bSDimitry Andric
536206d4ba38SDimitry Andric // Fast-isel and the optimizer generally like scalar values better than
536306d4ba38SDimitry Andric // FCAs, so we flatten them if this is safe to do for this argument.
536406d4ba38SDimitry Andric if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) {
5365cfca06d7SDimitry Andric llvm::Type *SrcTy = Src.getElementType();
5366b1c73532SDimitry Andric llvm::TypeSize SrcTypeSize =
5367b1c73532SDimitry Andric CGM.getDataLayout().getTypeAllocSize(SrcTy);
5368b1c73532SDimitry Andric llvm::TypeSize DstTypeSize = CGM.getDataLayout().getTypeAllocSize(STy);
5369b1c73532SDimitry Andric if (SrcTypeSize.isScalable()) {
5370b1c73532SDimitry Andric assert(STy->containsHomogeneousScalableVectorTypes() &&
5371b1c73532SDimitry Andric "ABI only supports structure with homogeneous scalable vector "
5372b1c73532SDimitry Andric "type");
5373b1c73532SDimitry Andric assert(SrcTypeSize == DstTypeSize &&
5374b1c73532SDimitry Andric "Only allow non-fractional movement of structure with "
5375b1c73532SDimitry Andric "homogeneous scalable vector type");
5376b1c73532SDimitry Andric assert(NumIRArgs == STy->getNumElements());
5377b1c73532SDimitry Andric
5378b1c73532SDimitry Andric llvm::Value *StoredStructValue =
5379b1c73532SDimitry Andric Builder.CreateLoad(Src, Src.getName() + ".tuple");
5380b1c73532SDimitry Andric for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
5381b1c73532SDimitry Andric llvm::Value *Extract = Builder.CreateExtractValue(
5382b1c73532SDimitry Andric StoredStructValue, i, Src.getName() + ".extract" + Twine(i));
5383b1c73532SDimitry Andric IRCallArgs[FirstIRArg + i] = Extract;
5384b1c73532SDimitry Andric }
5385b1c73532SDimitry Andric } else {
5386b1c73532SDimitry Andric uint64_t SrcSize = SrcTypeSize.getFixedValue();
5387b1c73532SDimitry Andric uint64_t DstSize = DstTypeSize.getFixedValue();
538813cc256eSDimitry Andric
538913cc256eSDimitry Andric // If the source type is smaller than the destination type of the
539013cc256eSDimitry Andric // coerce-to logic, copy the source value into a temp alloca the size
539113cc256eSDimitry Andric // of the destination type to allow loading all of it. The bits past
539213cc256eSDimitry Andric // the source value are left undef.
539313cc256eSDimitry Andric if (SrcSize < DstSize) {
5394b1c73532SDimitry Andric Address TempAlloca = CreateTempAlloca(STy, Src.getAlignment(),
539545b53394SDimitry Andric Src.getName() + ".coerce");
539645b53394SDimitry Andric Builder.CreateMemCpy(TempAlloca, Src, SrcSize);
539745b53394SDimitry Andric Src = TempAlloca;
539813cc256eSDimitry Andric } else {
53997fa27ce4SDimitry Andric Src = Src.withElementType(STy);
540013cc256eSDimitry Andric }
540113cc256eSDimitry Andric
540206d4ba38SDimitry Andric assert(NumIRArgs == STy->getNumElements());
54034ba67500SRoman Divacky for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
540422989816SDimitry Andric Address EltPtr = Builder.CreateStructGEP(Src, i);
540545b53394SDimitry Andric llvm::Value *LI = Builder.CreateLoad(EltPtr);
5406e3b55780SDimitry Andric if (ArgHasMaybeUndefAttr)
5407e3b55780SDimitry Andric LI = Builder.CreateFreeze(LI);
540806d4ba38SDimitry Andric IRCallArgs[FirstIRArg + i] = LI;
54094ba67500SRoman Divacky }
5410b1c73532SDimitry Andric }
54114ba67500SRoman Divacky } else {
54124ba67500SRoman Divacky // In the simple case, just pass the coerced loaded value.
541306d4ba38SDimitry Andric assert(NumIRArgs == 1);
5414cfca06d7SDimitry Andric llvm::Value *Load =
541545b53394SDimitry Andric CreateCoercedLoad(Src, ArgInfo.getCoerceToType(), *this);
5416cfca06d7SDimitry Andric
5417cfca06d7SDimitry Andric if (CallInfo.isCmseNSCall()) {
5418cfca06d7SDimitry Andric // For certain parameter types, clear padding bits, as they may reveal
5419cfca06d7SDimitry Andric // sensitive information.
5420cfca06d7SDimitry Andric // Small struct/union types are passed as integer arrays.
5421cfca06d7SDimitry Andric auto *ATy = dyn_cast<llvm::ArrayType>(Load->getType());
5422cfca06d7SDimitry Andric if (ATy != nullptr && isa<RecordType>(I->Ty.getCanonicalType()))
5423cfca06d7SDimitry Andric Load = EmitCMSEClearRecord(Load, ATy, I->Ty);
5424cfca06d7SDimitry Andric }
5425e3b55780SDimitry Andric
5426e3b55780SDimitry Andric if (ArgHasMaybeUndefAttr)
5427e3b55780SDimitry Andric Load = Builder.CreateFreeze(Load);
5428cfca06d7SDimitry Andric IRCallArgs[FirstIRArg] = Load;
54294ba67500SRoman Divacky }
54304ba67500SRoman Divacky
5431ec2b103cSEd Schouten break;
5432ec2b103cSEd Schouten }
5433ec2b103cSEd Schouten
54342b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand: {
54352b6b257fSDimitry Andric auto coercionType = ArgInfo.getCoerceAndExpandType();
54362b6b257fSDimitry Andric auto layout = CGM.getDataLayout().getStructLayout(coercionType);
54372b6b257fSDimitry Andric
54382b6b257fSDimitry Andric llvm::Value *tempSize = nullptr;
54392b6b257fSDimitry Andric Address addr = Address::invalid();
5440ac9a064cSDimitry Andric RawAddress AllocaAddr = RawAddress::invalid();
544148675466SDimitry Andric if (I->isAggregate()) {
5442ac9a064cSDimitry Andric addr = I->hasLValue() ? I->getKnownLValue().getAddress()
544348675466SDimitry Andric : I->getKnownRValue().getAggregateAddress();
544448675466SDimitry Andric
54452b6b257fSDimitry Andric } else {
544648675466SDimitry Andric RValue RV = I->getKnownRValue();
54472b6b257fSDimitry Andric assert(RV.isScalar()); // complex should always just be direct
54482b6b257fSDimitry Andric
54492b6b257fSDimitry Andric llvm::Type *scalarType = RV.getScalarVal()->getType();
54502b6b257fSDimitry Andric auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
5451e3b55780SDimitry Andric auto scalarAlign = CGM.getDataLayout().getPrefTypeAlign(scalarType);
54522b6b257fSDimitry Andric
54532b6b257fSDimitry Andric // Materialize to a temporary.
5454e3b55780SDimitry Andric addr = CreateTempAlloca(
5455e3b55780SDimitry Andric RV.getScalarVal()->getType(),
5456e3b55780SDimitry Andric CharUnits::fromQuantity(std::max(layout->getAlignment(), scalarAlign)),
545748675466SDimitry Andric "tmp",
545848675466SDimitry Andric /*ArraySize=*/nullptr, &AllocaAddr);
545948675466SDimitry Andric tempSize = EmitLifetimeStart(scalarSize, AllocaAddr.getPointer());
54602b6b257fSDimitry Andric
54612b6b257fSDimitry Andric Builder.CreateStore(RV.getScalarVal(), addr);
54622b6b257fSDimitry Andric }
54632b6b257fSDimitry Andric
54647fa27ce4SDimitry Andric addr = addr.withElementType(coercionType);
54652b6b257fSDimitry Andric
54662b6b257fSDimitry Andric unsigned IRArgPos = FirstIRArg;
54672b6b257fSDimitry Andric for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
54682b6b257fSDimitry Andric llvm::Type *eltType = coercionType->getElementType(i);
54692b6b257fSDimitry Andric if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue;
547022989816SDimitry Andric Address eltAddr = Builder.CreateStructGEP(addr, i);
54712b6b257fSDimitry Andric llvm::Value *elt = Builder.CreateLoad(eltAddr);
5472e3b55780SDimitry Andric if (ArgHasMaybeUndefAttr)
5473e3b55780SDimitry Andric elt = Builder.CreateFreeze(elt);
54742b6b257fSDimitry Andric IRCallArgs[IRArgPos++] = elt;
54752b6b257fSDimitry Andric }
54762b6b257fSDimitry Andric assert(IRArgPos == FirstIRArg + NumIRArgs);
54772b6b257fSDimitry Andric
54782b6b257fSDimitry Andric if (tempSize) {
547948675466SDimitry Andric EmitLifetimeEnd(tempSize, AllocaAddr.getPointer());
54802b6b257fSDimitry Andric }
54812b6b257fSDimitry Andric
54822b6b257fSDimitry Andric break;
54832b6b257fSDimitry Andric }
54842b6b257fSDimitry Andric
5485b60736ecSDimitry Andric case ABIArgInfo::Expand: {
548606d4ba38SDimitry Andric unsigned IRArgPos = FirstIRArg;
548748675466SDimitry Andric ExpandTypeToArgs(I->Ty, *I, IRFuncTy, IRCallArgs, IRArgPos);
548806d4ba38SDimitry Andric assert(IRArgPos == FirstIRArg + NumIRArgs);
5489ec2b103cSEd Schouten break;
5490ec2b103cSEd Schouten }
5491ec2b103cSEd Schouten }
5492b60736ecSDimitry Andric }
5493ec2b103cSEd Schouten
549448675466SDimitry Andric const CGCallee &ConcreteCallee = Callee.prepareConcreteCallee(*this);
549548675466SDimitry Andric llvm::Value *CalleePtr = ConcreteCallee.getFunctionPointer();
5496bab175ecSDimitry Andric
5497bab175ecSDimitry Andric // If we're using inalloca, set up that argument.
549845b53394SDimitry Andric if (ArgMemory.isValid()) {
549945b53394SDimitry Andric llvm::Value *Arg = ArgMemory.getPointer();
550006d4ba38SDimitry Andric assert(IRFunctionArgs.hasInallocaArg());
550106d4ba38SDimitry Andric IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg;
55029f4dbff6SDimitry Andric }
55039f4dbff6SDimitry Andric
5504bab175ecSDimitry Andric // 2. Prepare the function pointer.
5505bab175ecSDimitry Andric
5506bab175ecSDimitry Andric // If the callee is a bitcast of a non-variadic function to have a
5507bab175ecSDimitry Andric // variadic function pointer type, check to see if we can remove the
5508bab175ecSDimitry Andric // bitcast. This comes up with unprototyped functions.
5509bab175ecSDimitry Andric //
5510bab175ecSDimitry Andric // This makes the IR nicer, but more importantly it ensures that we
5511bab175ecSDimitry Andric // can inline the function at -O0 if it is marked always_inline.
551222989816SDimitry Andric auto simplifyVariadicCallee = [](llvm::FunctionType *CalleeFT,
551322989816SDimitry Andric llvm::Value *Ptr) -> llvm::Function * {
5514bab175ecSDimitry Andric if (!CalleeFT->isVarArg())
551522989816SDimitry Andric return nullptr;
5516bab175ecSDimitry Andric
551722989816SDimitry Andric // Get underlying value if it's a bitcast
551822989816SDimitry Andric if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr)) {
551922989816SDimitry Andric if (CE->getOpcode() == llvm::Instruction::BitCast)
552022989816SDimitry Andric Ptr = CE->getOperand(0);
552122989816SDimitry Andric }
5522bab175ecSDimitry Andric
552322989816SDimitry Andric llvm::Function *OrigFn = dyn_cast<llvm::Function>(Ptr);
5524bab175ecSDimitry Andric if (!OrigFn)
552522989816SDimitry Andric return nullptr;
5526bab175ecSDimitry Andric
5527bab175ecSDimitry Andric llvm::FunctionType *OrigFT = OrigFn->getFunctionType();
5528bab175ecSDimitry Andric
5529bab175ecSDimitry Andric // If the original type is variadic, or if any of the component types
5530bab175ecSDimitry Andric // disagree, we cannot remove the cast.
5531bab175ecSDimitry Andric if (OrigFT->isVarArg() ||
5532bab175ecSDimitry Andric OrigFT->getNumParams() != CalleeFT->getNumParams() ||
5533bab175ecSDimitry Andric OrigFT->getReturnType() != CalleeFT->getReturnType())
553422989816SDimitry Andric return nullptr;
5535bab175ecSDimitry Andric
5536bab175ecSDimitry Andric for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i)
5537bab175ecSDimitry Andric if (OrigFT->getParamType(i) != CalleeFT->getParamType(i))
553822989816SDimitry Andric return nullptr;
5539bab175ecSDimitry Andric
5540bab175ecSDimitry Andric return OrigFn;
5541bab175ecSDimitry Andric };
554222989816SDimitry Andric
554322989816SDimitry Andric if (llvm::Function *OrigFn = simplifyVariadicCallee(IRFuncTy, CalleePtr)) {
554422989816SDimitry Andric CalleePtr = OrigFn;
554522989816SDimitry Andric IRFuncTy = OrigFn->getFunctionType();
554622989816SDimitry Andric }
5547bab175ecSDimitry Andric
5548bab175ecSDimitry Andric // 3. Perform the actual call.
5549bab175ecSDimitry Andric
5550bab175ecSDimitry Andric // Deactivate any cleanups that we're supposed to do immediately before
5551bab175ecSDimitry Andric // the call.
5552bfef3995SDimitry Andric if (!CallArgs.getCleanupsToDeactivate().empty())
5553bfef3995SDimitry Andric deactivateArgCleanupsBeforeCall(*this, CallArgs);
5554bfef3995SDimitry Andric
5555bab175ecSDimitry Andric // Assert that the arguments we computed match up. The IR verifier
5556bab175ecSDimitry Andric // will catch this, but this is a common enough source of problems
5557bab175ecSDimitry Andric // during IRGen changes that it's way better for debugging to catch
5558bab175ecSDimitry Andric // it ourselves here.
5559bab175ecSDimitry Andric #ifndef NDEBUG
556006d4ba38SDimitry Andric assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg());
556106d4ba38SDimitry Andric for (unsigned i = 0; i < IRCallArgs.size(); ++i) {
556206d4ba38SDimitry Andric // Inalloca argument can have different type.
556306d4ba38SDimitry Andric if (IRFunctionArgs.hasInallocaArg() &&
556406d4ba38SDimitry Andric i == IRFunctionArgs.getInallocaArgNo())
556506d4ba38SDimitry Andric continue;
556606d4ba38SDimitry Andric if (i < IRFuncTy->getNumParams())
556706d4ba38SDimitry Andric assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i));
556806d4ba38SDimitry Andric }
5569bab175ecSDimitry Andric #endif
557006d4ba38SDimitry Andric
5571676fbe81SDimitry Andric // Update the largest vector width if any arguments have vector types.
5572145449b1SDimitry Andric for (unsigned i = 0; i < IRCallArgs.size(); ++i)
5573145449b1SDimitry Andric LargestVectorWidth = std::max(LargestVectorWidth,
5574145449b1SDimitry Andric getMaxVectorWidth(IRCallArgs[i]->getType()));
5575676fbe81SDimitry Andric
5576bab175ecSDimitry Andric // Compute the calling convention and attributes.
55774c8b2481SRoman Divacky unsigned CallingConv;
5578583e75ccSDimitry Andric llvm::AttributeList Attrs;
5579bab175ecSDimitry Andric CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo,
5580583e75ccSDimitry Andric Callee.getAbstractInfo(), Attrs, CallingConv,
5581344a3780SDimitry Andric /*AttrOnCallSite=*/true,
5582344a3780SDimitry Andric /*IsThunk=*/false);
5583ec2b103cSEd Schouten
5584ac9a064cSDimitry Andric if (CallingConv == llvm::CallingConv::X86_VectorCall &&
5585ac9a064cSDimitry Andric getTarget().getTriple().isWindowsArm64EC()) {
5586ac9a064cSDimitry Andric CGM.Error(Loc, "__vectorcall calling convention is not currently "
5587ac9a064cSDimitry Andric "supported");
5588ac9a064cSDimitry Andric }
5589ac9a064cSDimitry Andric
5590b1c73532SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) {
5591b60736ecSDimitry Andric if (FD->hasAttr<StrictFPAttr>())
5592706b4fc4SDimitry Andric // All calls within a strictfp function are marked strictfp
5593c0981da4SDimitry Andric Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::StrictFP);
5594706b4fc4SDimitry Andric
5595b1c73532SDimitry Andric // If -ffast-math is enabled and the function is guarded by an
5596b1c73532SDimitry Andric // '__attribute__((optnone)) adjust the memory attribute so the BE emits the
5597b1c73532SDimitry Andric // library call instead of the intrinsic.
5598b1c73532SDimitry Andric if (FD->hasAttr<OptimizeNoneAttr>() && getLangOpts().FastMath)
5599b1c73532SDimitry Andric CGM.AdjustMemoryAttribute(CalleePtr->getName(), Callee.getAbstractInfo(),
5600b1c73532SDimitry Andric Attrs);
5601b1c73532SDimitry Andric }
5602cfca06d7SDimitry Andric // Add call-site nomerge attribute if exists.
5603cfca06d7SDimitry Andric if (InNoMergeAttributedStmt)
5604c0981da4SDimitry Andric Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoMerge);
5605cfca06d7SDimitry Andric
5606145449b1SDimitry Andric // Add call-site noinline attribute if exists.
5607145449b1SDimitry Andric if (InNoInlineAttributedStmt)
5608145449b1SDimitry Andric Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoInline);
5609145449b1SDimitry Andric
5610145449b1SDimitry Andric // Add call-site always_inline attribute if exists.
5611145449b1SDimitry Andric if (InAlwaysInlineAttributedStmt)
5612145449b1SDimitry Andric Attrs =
5613145449b1SDimitry Andric Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline);
5614145449b1SDimitry Andric
5615bab175ecSDimitry Andric // Apply some call-site-specific attributes.
5616bab175ecSDimitry Andric // TODO: work this into building the attribute set.
5617bab175ecSDimitry Andric
5618bab175ecSDimitry Andric // Apply always_inline to all calls within flatten functions.
5619bab175ecSDimitry Andric // FIXME: should this really take priority over __try, below?
5620bab175ecSDimitry Andric if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
5621145449b1SDimitry Andric !InNoInlineAttributedStmt &&
562222989816SDimitry Andric !(TargetDecl && TargetDecl->hasAttr<NoInlineAttr>())) {
5623bab175ecSDimitry Andric Attrs =
5624c0981da4SDimitry Andric Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::AlwaysInline);
5625bab175ecSDimitry Andric }
5626bab175ecSDimitry Andric
5627bab175ecSDimitry Andric // Disable inlining inside SEH __try blocks.
5628bab175ecSDimitry Andric if (isSEHTryScope()) {
5629c0981da4SDimitry Andric Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::NoInline);
5630bab175ecSDimitry Andric }
5631bab175ecSDimitry Andric
5632bab175ecSDimitry Andric // Decide whether to use a call or an invoke.
563345b53394SDimitry Andric bool CannotThrow;
563445b53394SDimitry Andric if (currentFunctionUsesSEHTry()) {
5635bab175ecSDimitry Andric // SEH cares about asynchronous exceptions, so everything can "throw."
563645b53394SDimitry Andric CannotThrow = false;
563745b53394SDimitry Andric } else if (isCleanupPadScope() &&
563845b53394SDimitry Andric EHPersonality::get(*this).isMSVCXXPersonality()) {
563945b53394SDimitry Andric // The MSVC++ personality will implicitly terminate the program if an
5640bab175ecSDimitry Andric // exception is thrown during a cleanup outside of a try/catch.
5641bab175ecSDimitry Andric // We don't need to model anything in IR to get this behavior.
564245b53394SDimitry Andric CannotThrow = true;
564345b53394SDimitry Andric } else {
5644bab175ecSDimitry Andric // Otherwise, nounwind call sites will never throw.
5645c0981da4SDimitry Andric CannotThrow = Attrs.hasFnAttr(llvm::Attribute::NoUnwind);
5646b60736ecSDimitry Andric
5647b60736ecSDimitry Andric if (auto *FPtr = dyn_cast<llvm::Function>(CalleePtr))
5648b60736ecSDimitry Andric if (FPtr->hasFnAttribute(llvm::Attribute::NoUnwind))
5649b60736ecSDimitry Andric CannotThrow = true;
565045b53394SDimitry Andric }
565148675466SDimitry Andric
565248675466SDimitry Andric // If we made a temporary, be sure to clean up after ourselves. Note that we
565348675466SDimitry Andric // can't depend on being inside of an ExprWithCleanups, so we need to manually
565448675466SDimitry Andric // pop this cleanup later on. Being eager about this is OK, since this
565548675466SDimitry Andric // temporary is 'invisible' outside of the callee.
565648675466SDimitry Andric if (UnusedReturnSizePtr)
565748675466SDimitry Andric pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca,
565848675466SDimitry Andric UnusedReturnSizePtr);
565948675466SDimitry Andric
566045b53394SDimitry Andric llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
566145b53394SDimitry Andric
566248675466SDimitry Andric SmallVector<llvm::OperandBundleDef, 1> BundleList =
566348675466SDimitry Andric getBundlesForFunclet(CalleePtr);
56644ba67500SRoman Divacky
5665e3b55780SDimitry Andric if (SanOpts.has(SanitizerKind::KCFI) &&
5666e3b55780SDimitry Andric !isa_and_nonnull<FunctionDecl>(TargetDecl))
5667e3b55780SDimitry Andric EmitKCFIOperandBundle(ConcreteCallee, BundleList);
5668e3b55780SDimitry Andric
5669ac9a064cSDimitry Andric // Add the pointer-authentication bundle.
5670ac9a064cSDimitry Andric EmitPointerAuthOperandBundle(ConcreteCallee.getPointerAuthInfo(), BundleList);
5671ac9a064cSDimitry Andric
5672706b4fc4SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
5673b60736ecSDimitry Andric if (FD->hasAttr<StrictFPAttr>())
5674706b4fc4SDimitry Andric // All calls within a strictfp function are marked strictfp
5675c0981da4SDimitry Andric Attrs = Attrs.addFnAttribute(getLLVMContext(), llvm::Attribute::StrictFP);
5676706b4fc4SDimitry Andric
5677cfca06d7SDimitry Andric AssumeAlignedAttrEmitter AssumeAlignedAttrEmitter(*this, TargetDecl);
5678cfca06d7SDimitry Andric Attrs = AssumeAlignedAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
5679cfca06d7SDimitry Andric
5680cfca06d7SDimitry Andric AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs);
5681cfca06d7SDimitry Andric Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs);
5682cfca06d7SDimitry Andric
5683bab175ecSDimitry Andric // Emit the actual call/invoke instruction.
568422989816SDimitry Andric llvm::CallBase *CI;
56854ba67500SRoman Divacky if (!InvokeDest) {
568622989816SDimitry Andric CI = Builder.CreateCall(IRFuncTy, CalleePtr, IRCallArgs, BundleList);
5687ec2b103cSEd Schouten } else {
5688ec2b103cSEd Schouten llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
568922989816SDimitry Andric CI = Builder.CreateInvoke(IRFuncTy, CalleePtr, Cont, InvokeDest, IRCallArgs,
569045b53394SDimitry Andric BundleList);
5691ec2b103cSEd Schouten EmitBlock(Cont);
5692ec2b103cSEd Schouten }
5693b1c73532SDimitry Andric if (CI->getCalledFunction() && CI->getCalledFunction()->hasName() &&
5694312c0ed1SDimitry Andric CI->getCalledFunction()->getName().starts_with("_Z4sqrt")) {
5695b1c73532SDimitry Andric SetSqrtFPAccuracy(CI);
5696b1c73532SDimitry Andric }
56974ba67500SRoman Divacky if (callOrInvoke)
5698bab175ecSDimitry Andric *callOrInvoke = CI;
5699ec2b103cSEd Schouten
5700706b4fc4SDimitry Andric // If this is within a function that has the guard(nocf) attribute and is an
5701706b4fc4SDimitry Andric // indirect call, add the "guard_nocf" attribute to this call to indicate that
5702706b4fc4SDimitry Andric // Control Flow Guard checks should not be added, even if the call is inlined.
5703706b4fc4SDimitry Andric if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) {
5704706b4fc4SDimitry Andric if (const auto *A = FD->getAttr<CFGuardAttr>()) {
5705706b4fc4SDimitry Andric if (A->getGuard() == CFGuardAttr::GuardArg::nocf && !CI->getCalledFunction())
5706c0981da4SDimitry Andric Attrs = Attrs.addFnAttribute(getLLVMContext(), "guard_nocf");
5707706b4fc4SDimitry Andric }
5708706b4fc4SDimitry Andric }
5709706b4fc4SDimitry Andric
5710bab175ecSDimitry Andric // Apply the attributes and calling convention.
571122989816SDimitry Andric CI->setAttributes(Attrs);
571222989816SDimitry Andric CI->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
5713ec2b103cSEd Schouten
5714bab175ecSDimitry Andric // Apply various metadata.
5715bab175ecSDimitry Andric
5716bab175ecSDimitry Andric if (!CI->getType()->isVoidTy())
5717bab175ecSDimitry Andric CI->setName("call");
5718bab175ecSDimitry Andric
5719ac9a064cSDimitry Andric if (CGM.shouldEmitConvergenceTokens() && CI->isConvergent())
5720ac9a064cSDimitry Andric CI = addControlledConvergenceToken(CI);
5721ac9a064cSDimitry Andric
5722676fbe81SDimitry Andric // Update largest vector width from the return type.
5723cfca06d7SDimitry Andric LargestVectorWidth =
5724145449b1SDimitry Andric std::max(LargestVectorWidth, getMaxVectorWidth(CI->getType()));
5725676fbe81SDimitry Andric
57262b6b257fSDimitry Andric // Insert instrumentation or attach profile metadata at indirect call sites.
57272b6b257fSDimitry Andric // For more details, see the comment before the definition of
57282b6b257fSDimitry Andric // IPVK_IndirectCallTarget in InstrProfData.inc.
572922989816SDimitry Andric if (!CI->getCalledFunction())
57302b6b257fSDimitry Andric PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget,
5731bab175ecSDimitry Andric CI, CalleePtr);
57322b6b257fSDimitry Andric
5733dbe13110SDimitry Andric // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
5734dbe13110SDimitry Andric // optimizer it can aggressively ignore unwind edges.
5735dbe13110SDimitry Andric if (CGM.getLangOpts().ObjCAutoRefCount)
5736bab175ecSDimitry Andric AddObjCARCExceptionMetadata(CI);
5737bab175ecSDimitry Andric
5738344a3780SDimitry Andric // Set tail call kind if necessary.
5739bab175ecSDimitry Andric if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
5740bab175ecSDimitry Andric if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
5741bab175ecSDimitry Andric Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
5742ac9a064cSDimitry Andric else if (IsMustTail) {
5743ac9a064cSDimitry Andric if (getTarget().getTriple().isPPC()) {
5744ac9a064cSDimitry Andric if (getTarget().getTriple().isOSAIX())
5745ac9a064cSDimitry Andric CGM.getDiags().Report(Loc, diag::err_aix_musttail_unsupported);
5746ac9a064cSDimitry Andric else if (!getTarget().hasFeature("pcrelative-memops")) {
5747ac9a064cSDimitry Andric if (getTarget().hasFeature("longcall"))
5748ac9a064cSDimitry Andric CGM.getDiags().Report(Loc, diag::err_ppc_impossible_musttail) << 0;
5749ac9a064cSDimitry Andric else if (Call->isIndirectCall())
5750ac9a064cSDimitry Andric CGM.getDiags().Report(Loc, diag::err_ppc_impossible_musttail) << 1;
5751ac9a064cSDimitry Andric else if (isa_and_nonnull<FunctionDecl>(TargetDecl)) {
5752ac9a064cSDimitry Andric if (!cast<FunctionDecl>(TargetDecl)->isDefined())
5753ac9a064cSDimitry Andric // The undefined callee may be a forward declaration. Without
5754ac9a064cSDimitry Andric // knowning all symbols in the module, we won't know the symbol is
5755ac9a064cSDimitry Andric // defined or not. Collect all these symbols for later diagnosing.
5756ac9a064cSDimitry Andric CGM.addUndefinedGlobalForTailCall(
5757ac9a064cSDimitry Andric {cast<FunctionDecl>(TargetDecl), Loc});
5758ac9a064cSDimitry Andric else {
5759ac9a064cSDimitry Andric llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(
5760ac9a064cSDimitry Andric GlobalDecl(cast<FunctionDecl>(TargetDecl)));
5761ac9a064cSDimitry Andric if (llvm::GlobalValue::isWeakForLinker(Linkage) ||
5762ac9a064cSDimitry Andric llvm::GlobalValue::isDiscardableIfUnused(Linkage))
5763ac9a064cSDimitry Andric CGM.getDiags().Report(Loc, diag::err_ppc_impossible_musttail)
5764ac9a064cSDimitry Andric << 2;
5765ac9a064cSDimitry Andric }
5766ac9a064cSDimitry Andric }
5767ac9a064cSDimitry Andric }
5768ac9a064cSDimitry Andric }
5769344a3780SDimitry Andric Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
5770bab175ecSDimitry Andric }
5771ac9a064cSDimitry Andric }
5772bab175ecSDimitry Andric
577322989816SDimitry Andric // Add metadata for calls to MSAllocator functions
577422989816SDimitry Andric if (getDebugInfo() && TargetDecl &&
577522989816SDimitry Andric TargetDecl->hasAttr<MSAllocatorAttr>())
5776cfca06d7SDimitry Andric getDebugInfo()->addHeapAllocSiteMetadata(CI, RetTy->getPointeeType(), Loc);
577722989816SDimitry Andric
5778c0981da4SDimitry Andric // Add metadata if calling an __attribute__((error(""))) or warning fn.
5779c0981da4SDimitry Andric if (TargetDecl && TargetDecl->hasAttr<ErrorAttr>()) {
5780c0981da4SDimitry Andric llvm::ConstantInt *Line =
5781ac9a064cSDimitry Andric llvm::ConstantInt::get(Int64Ty, Loc.getRawEncoding());
5782c0981da4SDimitry Andric llvm::ConstantAsMetadata *MD = llvm::ConstantAsMetadata::get(Line);
5783c0981da4SDimitry Andric llvm::MDTuple *MDT = llvm::MDNode::get(getLLVMContext(), {MD});
5784c0981da4SDimitry Andric CI->setMetadata("srcloc", MDT);
5785c0981da4SDimitry Andric }
5786c0981da4SDimitry Andric
5787bab175ecSDimitry Andric // 4. Finish the call.
5788dbe13110SDimitry Andric
5789ec2b103cSEd Schouten // If the call doesn't return, finish the basic block and clear the
5790bab175ecSDimitry Andric // insertion point; this allows the rest of IRGen to discard
5791ec2b103cSEd Schouten // unreachable code.
579222989816SDimitry Andric if (CI->doesNotReturn()) {
579348675466SDimitry Andric if (UnusedReturnSizePtr)
579448675466SDimitry Andric PopCleanupBlock();
5795798321d8SDimitry Andric
57966252156dSDimitry Andric // Strip away the noreturn attribute to better diagnose unreachable UB.
57976252156dSDimitry Andric if (SanOpts.has(SanitizerKind::Unreachable)) {
579822989816SDimitry Andric // Also remove from function since CallBase::hasFnAttr additionally checks
579922989816SDimitry Andric // attributes of the called function.
580022989816SDimitry Andric if (auto *F = CI->getCalledFunction())
58016252156dSDimitry Andric F->removeFnAttr(llvm::Attribute::NoReturn);
5802c0981da4SDimitry Andric CI->removeFnAttr(llvm::Attribute::NoReturn);
580322989816SDimitry Andric
580422989816SDimitry Andric // Avoid incompatibility with ASan which relies on the `noreturn`
580522989816SDimitry Andric // attribute to insert handler calls.
580622989816SDimitry Andric if (SanOpts.hasOneOf(SanitizerKind::Address |
580722989816SDimitry Andric SanitizerKind::KernelAddress)) {
580822989816SDimitry Andric SanitizerScope SanScope(this);
580922989816SDimitry Andric llvm::IRBuilder<>::InsertPointGuard IPGuard(Builder);
581022989816SDimitry Andric Builder.SetInsertPoint(CI);
581122989816SDimitry Andric auto *FnType = llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
581222989816SDimitry Andric llvm::FunctionCallee Fn =
581322989816SDimitry Andric CGM.CreateRuntimeFunction(FnType, "__asan_handle_no_return");
581422989816SDimitry Andric EmitNounwindRuntimeCall(Fn);
581522989816SDimitry Andric }
58166252156dSDimitry Andric }
58176252156dSDimitry Andric
58186252156dSDimitry Andric EmitUnreachable(Loc);
5819ec2b103cSEd Schouten Builder.ClearInsertionPoint();
5820ec2b103cSEd Schouten
5821ec2b103cSEd Schouten // FIXME: For now, emit a dummy basic block because expr emitters in
5822ec2b103cSEd Schouten // generally are not ready to handle emitting expressions at unreachable
5823ec2b103cSEd Schouten // points.
5824ec2b103cSEd Schouten EnsureInsertPoint();
5825ec2b103cSEd Schouten
5826ec2b103cSEd Schouten // Return a reasonable RValue.
5827ec2b103cSEd Schouten return GetUndefRValue(RetTy);
5828ec2b103cSEd Schouten }
5829ec2b103cSEd Schouten
5830344a3780SDimitry Andric // If this is a musttail call, return immediately. We do not branch to the
5831344a3780SDimitry Andric // epilogue in this case.
5832344a3780SDimitry Andric if (IsMustTail) {
5833344a3780SDimitry Andric for (auto it = EHStack.find(CurrentCleanupScopeDepth); it != EHStack.end();
5834344a3780SDimitry Andric ++it) {
5835344a3780SDimitry Andric EHCleanupScope *Cleanup = dyn_cast<EHCleanupScope>(&*it);
5836344a3780SDimitry Andric if (!(Cleanup && Cleanup->getCleanup()->isRedundantBeforeReturn()))
5837344a3780SDimitry Andric CGM.ErrorUnsupported(MustTailCall, "tail call skipping over cleanups");
5838344a3780SDimitry Andric }
5839344a3780SDimitry Andric if (CI->getType()->isVoidTy())
5840344a3780SDimitry Andric Builder.CreateRetVoid();
5841344a3780SDimitry Andric else
5842344a3780SDimitry Andric Builder.CreateRet(CI);
5843344a3780SDimitry Andric Builder.ClearInsertionPoint();
5844344a3780SDimitry Andric EnsureInsertPoint();
5845344a3780SDimitry Andric return GetUndefRValue(RetTy);
5846344a3780SDimitry Andric }
5847344a3780SDimitry Andric
58482b6b257fSDimitry Andric // Perform the swifterror writeback.
58492b6b257fSDimitry Andric if (swiftErrorTemp.isValid()) {
58502b6b257fSDimitry Andric llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp);
58512b6b257fSDimitry Andric Builder.CreateStore(errorResult, swiftErrorArg);
58522b6b257fSDimitry Andric }
58532b6b257fSDimitry Andric
5854bab175ecSDimitry Andric // Emit any call-associated writebacks immediately. Arguably this
5855bab175ecSDimitry Andric // should happen after any return-value munging.
5856180abc3dSDimitry Andric if (CallArgs.hasWritebacks())
5857180abc3dSDimitry Andric emitWritebacks(*this, CallArgs);
5858180abc3dSDimitry Andric
58599f4dbff6SDimitry Andric // The stack cleanup for inalloca arguments has to run out of the normal
58609f4dbff6SDimitry Andric // lexical order, so deactivate it and run it manually here.
58619f4dbff6SDimitry Andric CallArgs.freeArgumentMemory(*this);
58629f4dbff6SDimitry Andric
5863bab175ecSDimitry Andric // Extract the return value.
5864ac9a064cSDimitry Andric RValue Ret;
5865ac9a064cSDimitry Andric
5866ac9a064cSDimitry Andric // If the current function is a virtual function pointer thunk, avoid copying
5867ac9a064cSDimitry Andric // the return value of the musttail call to a temporary.
5868ac9a064cSDimitry Andric if (IsVirtualFunctionPointerThunk) {
5869ac9a064cSDimitry Andric Ret = RValue::get(CI);
5870ac9a064cSDimitry Andric } else {
5871ac9a064cSDimitry Andric Ret = [&] {
5872ec2b103cSEd Schouten switch (RetAI.getKind()) {
58732b6b257fSDimitry Andric case ABIArgInfo::CoerceAndExpand: {
58742b6b257fSDimitry Andric auto coercionType = RetAI.getCoerceAndExpandType();
58752b6b257fSDimitry Andric
58767fa27ce4SDimitry Andric Address addr = SRetPtr.withElementType(coercionType);
58772b6b257fSDimitry Andric
58782b6b257fSDimitry Andric assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType());
58792b6b257fSDimitry Andric bool requiresExtract = isa<llvm::StructType>(CI->getType());
58802b6b257fSDimitry Andric
58812b6b257fSDimitry Andric unsigned unpaddedIndex = 0;
58822b6b257fSDimitry Andric for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
58832b6b257fSDimitry Andric llvm::Type *eltType = coercionType->getElementType(i);
5884ac9a064cSDimitry Andric if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType))
5885ac9a064cSDimitry Andric continue;
588622989816SDimitry Andric Address eltAddr = Builder.CreateStructGEP(addr, i);
58872b6b257fSDimitry Andric llvm::Value *elt = CI;
58882b6b257fSDimitry Andric if (requiresExtract)
58892b6b257fSDimitry Andric elt = Builder.CreateExtractValue(elt, unpaddedIndex++);
58902b6b257fSDimitry Andric else
58912b6b257fSDimitry Andric assert(unpaddedIndex == 0);
58922b6b257fSDimitry Andric Builder.CreateStore(elt, eltAddr);
58932b6b257fSDimitry Andric }
5894e3b55780SDimitry Andric [[fallthrough]];
58952b6b257fSDimitry Andric }
58962b6b257fSDimitry Andric
58979f4dbff6SDimitry Andric case ABIArgInfo::InAlloca:
5898798321d8SDimitry Andric case ABIArgInfo::Indirect: {
5899798321d8SDimitry Andric RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
590048675466SDimitry Andric if (UnusedReturnSizePtr)
590148675466SDimitry Andric PopCleanupBlock();
5902798321d8SDimitry Andric return ret;
5903798321d8SDimitry Andric }
59043d1dcd9bSDimitry Andric
59053d1dcd9bSDimitry Andric case ABIArgInfo::Ignore:
59063d1dcd9bSDimitry Andric // If we are ignoring an argument that had a result, make sure to
59073d1dcd9bSDimitry Andric // construct the appropriate return value for our caller.
59083d1dcd9bSDimitry Andric return GetUndefRValue(RetTy);
5909ec2b103cSEd Schouten
591070b4596dSEd Schouten case ABIArgInfo::Extend:
59113d1dcd9bSDimitry Andric case ABIArgInfo::Direct: {
5912180abc3dSDimitry Andric llvm::Type *RetIRTy = ConvertType(RetTy);
5913ac9a064cSDimitry Andric if (RetAI.getCoerceToType() == RetIRTy &&
5914ac9a064cSDimitry Andric RetAI.getDirectOffset() == 0) {
5915809500fcSDimitry Andric switch (getEvaluationKind(RetTy)) {
5916809500fcSDimitry Andric case TEK_Complex: {
5917ec2b103cSEd Schouten llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
5918ec2b103cSEd Schouten llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
5919ec2b103cSEd Schouten return RValue::getComplex(std::make_pair(Real, Imag));
5920ec2b103cSEd Schouten }
59211de139fdSDimitry Andric case TEK_Aggregate:
59221de139fdSDimitry Andric break;
5923809500fcSDimitry Andric case TEK_Scalar: {
5924ac9a064cSDimitry Andric // If the argument doesn't match, perform a bitcast to coerce it.
5925ac9a064cSDimitry Andric // This can happen due to trivial type mismatches.
5926180abc3dSDimitry Andric llvm::Value *V = CI;
5927180abc3dSDimitry Andric if (V->getType() != RetIRTy)
5928180abc3dSDimitry Andric V = Builder.CreateBitCast(V, RetIRTy);
5929180abc3dSDimitry Andric return RValue::get(V);
59303d1dcd9bSDimitry Andric }
5931809500fcSDimitry Andric }
5932809500fcSDimitry Andric }
5933ec2b103cSEd Schouten
59347fa27ce4SDimitry Andric // If coercing a fixed vector from a scalable vector for ABI
59357fa27ce4SDimitry Andric // compatibility, and the types match, use the llvm.vector.extract
59367fa27ce4SDimitry Andric // intrinsic to perform the conversion.
5937ac9a064cSDimitry Andric if (auto *FixedDstTy = dyn_cast<llvm::FixedVectorType>(RetIRTy)) {
59387fa27ce4SDimitry Andric llvm::Value *V = CI;
5939ac9a064cSDimitry Andric if (auto *ScalableSrcTy =
5940ac9a064cSDimitry Andric dyn_cast<llvm::ScalableVectorType>(V->getType())) {
5941ac9a064cSDimitry Andric if (FixedDstTy->getElementType() ==
5942ac9a064cSDimitry Andric ScalableSrcTy->getElementType()) {
59437fa27ce4SDimitry Andric llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int64Ty);
5944ac9a064cSDimitry Andric V = Builder.CreateExtractVector(FixedDstTy, V, Zero,
5945ac9a064cSDimitry Andric "cast.fixed");
59467fa27ce4SDimitry Andric return RValue::get(V);
59477fa27ce4SDimitry Andric }
59487fa27ce4SDimitry Andric }
59497fa27ce4SDimitry Andric }
59507fa27ce4SDimitry Andric
595145b53394SDimitry Andric Address DestPtr = ReturnValue.getValue();
5952abe15e55SRoman Divacky bool DestIsVolatile = ReturnValue.isVolatile();
59531de139fdSDimitry Andric uint64_t DestSize =
59541de139fdSDimitry Andric getContext().getTypeInfoDataSizeInChars(RetTy).Width.getQuantity();
5955abe15e55SRoman Divacky
595645b53394SDimitry Andric if (!DestPtr.isValid()) {
5957ecb7e5c8SRoman Divacky DestPtr = CreateMemTemp(RetTy, "coerce");
5958abe15e55SRoman Divacky DestIsVolatile = false;
59591de139fdSDimitry Andric DestSize = getContext().getTypeSizeInChars(RetTy).getQuantity();
5960abe15e55SRoman Divacky }
5961abe15e55SRoman Divacky
5962b1c73532SDimitry Andric // An empty record can overlap other data (if declared with
5963b1c73532SDimitry Andric // no_unique_address); omit the store for such types - as there is no
5964b1c73532SDimitry Andric // actual data to store.
5965b1c73532SDimitry Andric if (!isEmptyRecord(getContext(), RetTy, true)) {
59663d1dcd9bSDimitry Andric // If the value is offset in memory, apply the offset now.
596745b53394SDimitry Andric Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI);
59681de139fdSDimitry Andric CreateCoercedStore(
59691de139fdSDimitry Andric CI, StorePtr,
59701de139fdSDimitry Andric llvm::TypeSize::getFixed(DestSize - RetAI.getDirectOffset()),
59711de139fdSDimitry Andric DestIsVolatile);
5972b1c73532SDimitry Andric }
59733d1dcd9bSDimitry Andric
5974bfef3995SDimitry Andric return convertTempToRValue(DestPtr, RetTy, SourceLocation());
5975ec2b103cSEd Schouten }
5976ec2b103cSEd Schouten
5977ec2b103cSEd Schouten case ABIArgInfo::Expand:
5978b60736ecSDimitry Andric case ABIArgInfo::IndirectAliased:
597936981b17SDimitry Andric llvm_unreachable("Invalid ABI kind for return argument");
5980ec2b103cSEd Schouten }
5981ec2b103cSEd Schouten
598236981b17SDimitry Andric llvm_unreachable("Unhandled ABIArgInfo::Kind");
598306d4ba38SDimitry Andric }();
5984ac9a064cSDimitry Andric }
598506d4ba38SDimitry Andric
5986bab175ecSDimitry Andric // Emit the assume_aligned check on the return value.
598706d4ba38SDimitry Andric if (Ret.isScalar() && TargetDecl) {
5988cfca06d7SDimitry Andric AssumeAlignedAttrEmitter.EmitAsAnAssumption(Loc, RetTy, Ret);
5989cfca06d7SDimitry Andric AllocAlignAttrEmitter.EmitAsAnAssumption(Loc, RetTy, Ret);
599006d4ba38SDimitry Andric }
599106d4ba38SDimitry Andric
5992519fc96cSDimitry Andric // Explicitly call CallLifetimeEnd::Emit just to re-use the code even though
5993519fc96cSDimitry Andric // we can't use the full cleanup mechanism.
5994519fc96cSDimitry Andric for (CallLifetimeEnd &LifetimeEnd : CallLifetimeEndAfterCall)
5995519fc96cSDimitry Andric LifetimeEnd.Emit(*this, /*Flags=*/{});
5996519fc96cSDimitry Andric
5997cfca06d7SDimitry Andric if (!ReturnValue.isExternallyDestructed() &&
5998cfca06d7SDimitry Andric RetTy.isDestructedType() == QualType::DK_nontrivial_c_struct)
5999cfca06d7SDimitry Andric pushDestroy(QualType::DK_nontrivial_c_struct, Ret.getAggregateAddress(),
6000cfca06d7SDimitry Andric RetTy);
6001cfca06d7SDimitry Andric
600206d4ba38SDimitry Andric return Ret;
6003ec2b103cSEd Schouten }
6004ec2b103cSEd Schouten
prepareConcreteCallee(CodeGenFunction & CGF) const600548675466SDimitry Andric CGCallee CGCallee::prepareConcreteCallee(CodeGenFunction &CGF) const {
600648675466SDimitry Andric if (isVirtual()) {
600748675466SDimitry Andric const CallExpr *CE = getVirtualCallExpr();
600848675466SDimitry Andric return CGF.CGM.getCXXABI().getVirtualFunctionPointer(
600922989816SDimitry Andric CGF, getVirtualMethodDecl(), getThisAddress(), getVirtualFunctionType(),
6010676fbe81SDimitry Andric CE ? CE->getBeginLoc() : SourceLocation());
601148675466SDimitry Andric }
601248675466SDimitry Andric
601348675466SDimitry Andric return *this;
601448675466SDimitry Andric }
601548675466SDimitry Andric
6016ec2b103cSEd Schouten /* VarArg handling */
6017ec2b103cSEd Schouten
EmitVAArg(VAArgExpr * VE,Address & VAListAddr,AggValueSlot Slot)6018ac9a064cSDimitry Andric RValue CodeGenFunction::EmitVAArg(VAArgExpr *VE, Address &VAListAddr,
6019ac9a064cSDimitry Andric AggValueSlot Slot) {
6020ac9a064cSDimitry Andric VAListAddr = VE->isMicrosoftABI() ? EmitMSVAListRef(VE->getSubExpr())
602145b53394SDimitry Andric : EmitVAListRef(VE->getSubExpr());
602245b53394SDimitry Andric QualType Ty = VE->getType();
602345b53394SDimitry Andric if (VE->isMicrosoftABI())
6024e6b73279SDimitry Andric return CGM.getABIInfo().EmitMSVAArg(*this, VAListAddr, Ty, Slot);
6025e6b73279SDimitry Andric return CGM.getABIInfo().EmitVAArg(*this, VAListAddr, Ty, Slot);
6026ec2b103cSEd Schouten }
6027