1 //===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // These classes wrap the information about a call or function
10 // definition used to handle ABI compliancy.
12 //===----------------------------------------------------------------------===//
14 #include "TargetInfo.h"
16 #include "ABIInfoImpl.h"
17 #include "CodeGenFunction.h"
18 #include "clang/Basic/CodeGenOptions.h"
19 #include "clang/CodeGen/CGFunctionInfo.h"
20 #include "llvm/ADT/StringExtras.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/Type.h"
24 #include "llvm/Support/raw_ostream.h"
26 using namespace clang
;
27 using namespace CodeGen
;
29 LLVM_DUMP_METHOD
void ABIArgInfo::dump() const {
30 raw_ostream
&OS
= llvm::errs();
31 OS
<< "(ABIArgInfo Kind=";
35 if (llvm::Type
*Ty
= getCoerceToType())
47 OS
<< "InAlloca Offset=" << getInAllocaFieldIndex();
50 OS
<< "Indirect Align=" << getIndirectAlign().getQuantity()
51 << " ByVal=" << getIndirectByVal()
52 << " Realign=" << getIndirectRealign();
55 OS
<< "Indirect Align=" << getIndirectAlign().getQuantity()
56 << " AadrSpace=" << getIndirectAddrSpace()
57 << " Realign=" << getIndirectRealign();
63 OS
<< "CoerceAndExpand Type=";
64 getCoerceAndExpandType()->print(OS
);
70 TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr
<ABIInfo
> Info
)
71 : Info(std::move(Info
)) {}
73 TargetCodeGenInfo::~TargetCodeGenInfo() = default;
75 // If someone can figure out a general rule for this, that would be great.
76 // It's probably just doomed to be platform-dependent, though.
77 unsigned TargetCodeGenInfo::getSizeOfUnwindException() const {
79 // x86-64 FreeBSD, Linux, Darwin
80 // x86-32 FreeBSD, Linux, Darwin
82 // ARM Darwin (*not* EABI)
87 bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList
&args
,
88 const FunctionNoProtoType
*fnType
) const {
89 // The following conventions are known to require this to be false:
92 // For everything else, we just prefer false unless we opt out.
97 TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib
,
98 llvm::SmallString
<24> &Opt
) const {
99 // This assumes the user is passing a library name like "rt" instead of a
100 // filename like "librt.a/so", and that they don't care whether it's static or
106 unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const {
107 // OpenCL kernels are called via an explicit runtime API with arguments
108 // set with clSetKernelArg(), not as normal sub-functions.
109 // Return SPIR_KERNEL by default as the kernel calling convention to
110 // ensure the fingerprint is fixed such way that each OpenCL argument
111 // gets one matching argument in the produced kernel function argument
112 // list to enable feasible implementation of clSetKernelArg() with
113 // aggregates etc. In case we would use the default C calling conv here,
114 // clSetKernelArg() might break depending on the target-specific
115 // conventions; different targets might split structs passed as values
116 // to multiple function arguments etc.
117 return llvm::CallingConv::SPIR_KERNEL
;
120 llvm::Constant
*TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule
&CGM
,
121 llvm::PointerType
*T
, QualType QT
) const {
122 return llvm::ConstantPointerNull::get(T
);
125 LangAS
TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule
&CGM
,
126 const VarDecl
*D
) const {
127 assert(!CGM
.getLangOpts().OpenCL
&&
128 !(CGM
.getLangOpts().CUDA
&& CGM
.getLangOpts().CUDAIsDevice
) &&
129 "Address space agnostic languages only");
130 return D
? D
->getType().getAddressSpace() : LangAS::Default
;
133 llvm::Value
*TargetCodeGenInfo::performAddrSpaceCast(
134 CodeGen::CodeGenFunction
&CGF
, llvm::Value
*Src
, LangAS SrcAddr
,
135 LangAS DestAddr
, llvm::Type
*DestTy
, bool isNonNull
) const {
136 // Since target may map different address spaces in AST to the same address
137 // space, an address space conversion may end up as a bitcast.
138 if (auto *C
= dyn_cast
<llvm::Constant
>(Src
))
139 return performAddrSpaceCast(CGF
.CGM
, C
, SrcAddr
, DestAddr
, DestTy
);
140 // Try to preserve the source's name to make IR more readable.
141 return CGF
.Builder
.CreateAddrSpaceCast(
142 Src
, DestTy
, Src
->hasName() ? Src
->getName() + ".ascast" : "");
146 TargetCodeGenInfo::performAddrSpaceCast(CodeGenModule
&CGM
, llvm::Constant
*Src
,
147 LangAS SrcAddr
, LangAS DestAddr
,
148 llvm::Type
*DestTy
) const {
149 // Since target may map different address spaces in AST to the same address
150 // space, an address space conversion may end up as a bitcast.
151 return llvm::ConstantExpr::getPointerCast(Src
, DestTy
);
155 TargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions
&LangOpts
,
157 llvm::AtomicOrdering Ordering
,
158 llvm::LLVMContext
&Ctx
) const {
159 return Ctx
.getOrInsertSyncScopeID(""); /* default sync scope */
162 void TargetCodeGenInfo::addStackProbeTargetAttributes(
163 const Decl
*D
, llvm::GlobalValue
*GV
, CodeGen::CodeGenModule
&CGM
) const {
164 if (llvm::Function
*Fn
= dyn_cast_or_null
<llvm::Function
>(GV
)) {
165 if (CGM
.getCodeGenOpts().StackProbeSize
!= 4096)
166 Fn
->addFnAttr("stack-probe-size",
167 llvm::utostr(CGM
.getCodeGenOpts().StackProbeSize
));
168 if (CGM
.getCodeGenOpts().NoStackArgProbe
)
169 Fn
->addFnAttr("no-stack-arg-probe");
173 /// Create an OpenCL kernel for an enqueued block.
175 /// The kernel has the same function type as the block invoke function. Its
176 /// name is the name of the block invoke function postfixed with "_kernel".
177 /// It simply calls the block invoke function then returns.
178 llvm::Value
*TargetCodeGenInfo::createEnqueuedBlockKernel(
179 CodeGenFunction
&CGF
, llvm::Function
*Invoke
, llvm::Type
*BlockTy
) const {
180 auto *InvokeFT
= Invoke
->getFunctionType();
181 auto &C
= CGF
.getLLVMContext();
182 std::string Name
= Invoke
->getName().str() + "_kernel";
183 auto *FT
= llvm::FunctionType::get(llvm::Type::getVoidTy(C
),
184 InvokeFT
->params(), false);
185 auto *F
= llvm::Function::Create(FT
, llvm::GlobalValue::ExternalLinkage
, Name
,
186 &CGF
.CGM
.getModule());
187 llvm::CallingConv::ID KernelCC
=
188 CGF
.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel
);
189 F
->setCallingConv(KernelCC
);
191 llvm::AttrBuilder
KernelAttrs(C
);
193 // FIXME: This is missing setTargetAttributes
194 CGF
.CGM
.addDefaultFunctionDefinitionAttributes(KernelAttrs
);
195 F
->addFnAttrs(KernelAttrs
);
197 auto IP
= CGF
.Builder
.saveIP();
198 auto *BB
= llvm::BasicBlock::Create(C
, "entry", F
);
199 auto &Builder
= CGF
.Builder
;
200 Builder
.SetInsertPoint(BB
);
201 llvm::SmallVector
<llvm::Value
*, 2> Args(llvm::make_pointer_range(F
->args()));
202 llvm::CallInst
*Call
= Builder
.CreateCall(Invoke
, Args
);
203 Call
->setCallingConv(Invoke
->getCallingConv());
205 Builder
.CreateRetVoid();
206 Builder
.restoreIP(IP
);
210 void TargetCodeGenInfo::setBranchProtectionFnAttributes(
211 const TargetInfo::BranchProtectionInfo
&BPI
, llvm::Function
&F
) {
212 // Called on already created and initialized function where attributes already
213 // set from command line attributes but some might need to be removed as the
214 // actual BPI is different.
215 if (BPI
.SignReturnAddr
!= LangOptions::SignReturnAddressScopeKind::None
) {
216 F
.addFnAttr("sign-return-address", BPI
.getSignReturnAddrStr());
217 F
.addFnAttr("sign-return-address-key", BPI
.getSignKeyStr());
219 if (F
.hasFnAttribute("sign-return-address"))
220 F
.removeFnAttr("sign-return-address");
221 if (F
.hasFnAttribute("sign-return-address-key"))
222 F
.removeFnAttr("sign-return-address-key");
225 auto AddRemoveAttributeAsSet
= [&](bool Set
, const StringRef
&ModAttr
) {
227 F
.addFnAttr(ModAttr
);
228 else if (F
.hasFnAttribute(ModAttr
))
229 F
.removeFnAttr(ModAttr
);
232 AddRemoveAttributeAsSet(BPI
.BranchTargetEnforcement
,
233 "branch-target-enforcement");
234 AddRemoveAttributeAsSet(BPI
.BranchProtectionPAuthLR
,
235 "branch-protection-pauth-lr");
236 AddRemoveAttributeAsSet(BPI
.GuardedControlStack
, "guarded-control-stack");
239 void TargetCodeGenInfo::initBranchProtectionFnAttributes(
240 const TargetInfo::BranchProtectionInfo
&BPI
, llvm::AttrBuilder
&FuncAttrs
) {
241 // Only used for initializing attributes in the AttrBuilder, which will not
242 // contain any of these attributes so no need to remove anything.
243 if (BPI
.SignReturnAddr
!= LangOptions::SignReturnAddressScopeKind::None
) {
244 FuncAttrs
.addAttribute("sign-return-address", BPI
.getSignReturnAddrStr());
245 FuncAttrs
.addAttribute("sign-return-address-key", BPI
.getSignKeyStr());
247 if (BPI
.BranchTargetEnforcement
)
248 FuncAttrs
.addAttribute("branch-target-enforcement");
249 if (BPI
.BranchProtectionPAuthLR
)
250 FuncAttrs
.addAttribute("branch-protection-pauth-lr");
251 if (BPI
.GuardedControlStack
)
252 FuncAttrs
.addAttribute("guarded-control-stack");
256 class DefaultTargetCodeGenInfo
: public TargetCodeGenInfo
{
258 DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes
&CGT
)
259 : TargetCodeGenInfo(std::make_unique
<DefaultABIInfo
>(CGT
)) {}
263 std::unique_ptr
<TargetCodeGenInfo
>
264 CodeGen::createDefaultTargetCodeGenInfo(CodeGenModule
&CGM
) {
265 return std::make_unique
<DefaultTargetCodeGenInfo
>(CGM
.getTypes());