clang 23.0.0git
TargetInfo.cpp
Go to the documentation of this file.
1//===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// These classes wrap the information about a call or function
10// definition used to handle ABI compliancy.
11//
12//===----------------------------------------------------------------------===//
13
14#include "TargetInfo.h"
15#include "ABIInfo.h"
16#include "ABIInfoImpl.h"
17#include "CodeGenFunction.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"
25
26using namespace clang;
27using namespace CodeGen;
28
29LLVM_DUMP_METHOD void ABIArgInfo::dump() const {
30 raw_ostream &OS = llvm::errs();
31 OS << "(ABIArgInfo Kind=";
32 switch (TheKind) {
33 case Direct:
34 OS << "Direct Type=";
35 if (llvm::Type *Ty = getCoerceToType())
36 Ty->print(OS);
37 else
38 OS << "null";
39 break;
40 case Extend:
41 OS << "Extend";
42 break;
43 case Ignore:
44 OS << "Ignore";
45 break;
46 case InAlloca:
47 OS << "InAlloca Offset=" << getInAllocaFieldIndex();
48 break;
49 case Indirect:
50 OS << "Indirect Align=" << getIndirectAlign().getQuantity()
51 << " ByVal=" << getIndirectByVal()
52 << " Realign=" << getIndirectRealign();
53 break;
54 case IndirectAliased:
55 OS << "Indirect Align=" << getIndirectAlign().getQuantity()
56 << " AadrSpace=" << getIndirectAddrSpace()
57 << " Realign=" << getIndirectRealign();
58 break;
59 case Expand:
60 OS << "Expand";
61 break;
62 case CoerceAndExpand:
63 OS << "CoerceAndExpand Type=";
64 getCoerceAndExpandType()->print(OS);
65 break;
66 case TargetSpecific:
67 OS << "TargetSpecific Type=";
68 if (llvm::Type *Ty = getCoerceToType())
69 Ty->print(OS);
70 else
71 OS << "null";
72 break;
73 }
74 OS << ")\n";
75}
76
77TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info)
78 : Info(std::move(Info)) {}
79
81
82// If someone can figure out a general rule for this, that would be great.
83// It's probably just doomed to be platform-dependent, though.
85 if (getABIInfo().getCodeGenOpts().hasSEHExceptions())
86 return getABIInfo().getDataLayout().getPointerSizeInBits() > 32 ? 64 : 48;
87 // Verified for:
88 // x86-64 FreeBSD, Linux, Darwin
89 // x86-32 FreeBSD, Linux, Darwin
90 // PowerPC Linux
91 // ARM Darwin (*not* EABI)
92 // AArch64 Linux
93 return 32;
94}
95
97 const FunctionNoProtoType *fnType) const {
98 // The following conventions are known to require this to be false:
99 // x86_stdcall
100 // MIPS
101 // For everything else, we just prefer false unless we opt out.
102 return false;
103}
104
105void
107 llvm::SmallString<24> &Opt) const {
108 // This assumes the user is passing a library name like "rt" instead of a
109 // filename like "librt.a/so", and that they don't care whether it's static or
110 // dynamic.
111 Opt = "-l";
112 Opt += Lib;
113}
114
116 // Device kernels are called via an explicit runtime API with arguments,
117 // such as set with clSetKernelArg() for OpenCL, not as normal
118 // sub-functions. This uses a modified version of the C calling convention
119 // which simplifies the treatment of non-scalar types. (The rule adjustment
120 // hapens in CodeGenTypes::arrangeLLVMFunctionInfo.)
121 //
122 // Outside of OpenCL, kernels currently do not exist for CPU targets.
123 assert(getABIInfo().getContext().getLangOpts().OpenCL &&
124 "Kernel calling convention only defined for OpenCL");
125 return llvm::CallingConv::C;
126}
127
129 const FunctionType *&FT) const {
130 FT = getABIInfo().getContext().adjustFunctionType(
131 FT, FT->getExtInfo().withCallingConv(CC_C));
132}
133
135 llvm::PointerType *T, QualType QT) const {
136 return llvm::ConstantPointerNull::get(T);
137}
138
140 const VarDecl *D) const {
141 assert(!CGM.getLangOpts().OpenCL &&
142 !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) &&
143 "Address space agnostic languages only");
144 return D ? D->getType().getAddressSpace() : LangAS::Default;
145}
146
147StringRef
150 llvm::AtomicOrdering Ordering) const {
151 return ""; /* default sync scope */
152}
153
154llvm::SyncScope::ID
157 llvm::AtomicOrdering Ordering,
158 llvm::LLVMContext &Ctx) const {
159 return Ctx.getOrInsertSyncScopeID(
160 getLLVMSyncScopeStr(LangOpts, Scope, Ordering));
161}
162
164 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
165 if (llvm::Function *Fn = dyn_cast_or_null<llvm::Function>(GV)) {
166 if (CGM.getCodeGenOpts().StackProbeSize != 4096)
167 Fn->addFnAttr("stack-probe-size",
168 llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
169 if (CGM.getCodeGenOpts().NoStackArgProbe)
170 Fn->addFnAttr("no-stack-arg-probe");
171 }
172}
173
174/// Create an OpenCL kernel for an enqueued block.
175///
176/// The kernel has the same function type as the block invoke function. Its
177/// name is the name of the block invoke function postfixed with "_kernel".
178/// It simply calls the block invoke function then returns.
180 CodeGenFunction &CGF, llvm::Function *Invoke, llvm::Type *BlockTy) const {
181 auto *InvokeFT = Invoke->getFunctionType();
182 auto &C = CGF.getLLVMContext();
183 std::string Name = Invoke->getName().str() + "_kernel";
184 auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C),
185 InvokeFT->params(), false);
186 auto *F = llvm::Function::Create(FT, llvm::GlobalValue::ExternalLinkage, Name,
187 &CGF.CGM.getModule());
188 llvm::CallingConv::ID KernelCC =
190 F->setCallingConv(KernelCC);
191
192 llvm::AttrBuilder KernelAttrs(C);
193
194 // FIXME: This is missing setTargetAttributes
196 F->addFnAttrs(KernelAttrs);
197
198 auto IP = CGF.Builder.saveIP();
199 auto *BB = llvm::BasicBlock::Create(C, "entry", F);
200 auto &Builder = CGF.Builder;
201 Builder.SetInsertPoint(BB);
202 llvm::SmallVector<llvm::Value *, 2> Args(llvm::make_pointer_range(F->args()));
203 llvm::CallInst *Call = Builder.CreateCall(Invoke, Args);
204 Call->setCallingConv(Invoke->getCallingConv());
205
206 Builder.CreateRetVoid();
207 Builder.restoreIP(IP);
208 return F;
209}
210
212 const TargetInfo::BranchProtectionInfo &BPI, llvm::Function &F) {
213 // Called on already created and initialized function where attributes already
214 // set from command line attributes but some might need to be removed as the
215 // actual BPI is different.
217 F.addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
218 F.addFnAttr("sign-return-address-key", BPI.getSignKeyStr());
219 } else {
220 if (F.hasFnAttribute("sign-return-address"))
221 F.removeFnAttr("sign-return-address");
222 if (F.hasFnAttribute("sign-return-address-key"))
223 F.removeFnAttr("sign-return-address-key");
224 }
225
226 auto AddRemoveAttributeAsSet = [&](bool Set, const StringRef &ModAttr) {
227 if (Set)
228 F.addFnAttr(ModAttr);
229 else if (F.hasFnAttribute(ModAttr))
230 F.removeFnAttr(ModAttr);
231 };
232
233 AddRemoveAttributeAsSet(BPI.BranchTargetEnforcement,
234 "branch-target-enforcement");
235 AddRemoveAttributeAsSet(BPI.BranchProtectionPAuthLR,
236 "branch-protection-pauth-lr");
237 AddRemoveAttributeAsSet(BPI.GuardedControlStack, "guarded-control-stack");
238}
239
241 const TargetInfo::BranchProtectionInfo &BPI, llvm::AttrBuilder &FuncAttrs) {
242 // Only used for initializing attributes in the AttrBuilder, which will not
243 // contain any of these attributes so no need to remove anything.
245 FuncAttrs.addAttribute("sign-return-address", BPI.getSignReturnAddrStr());
246 FuncAttrs.addAttribute("sign-return-address-key", BPI.getSignKeyStr());
247 }
249 FuncAttrs.addAttribute("branch-target-enforcement");
251 FuncAttrs.addAttribute("branch-protection-pauth-lr");
252 if (BPI.GuardedControlStack)
253 FuncAttrs.addAttribute("guarded-control-stack");
254}
255
257 const PointerAuthOptions &Opts, llvm::Function &F) {
258 auto UpdateAttr = [&F](bool AttrShouldExist, StringRef AttrName) {
259 if (AttrShouldExist && !F.hasFnAttribute(AttrName))
260 F.addFnAttr(AttrName);
261 if (!AttrShouldExist && F.hasFnAttribute(AttrName))
262 F.removeFnAttr(AttrName);
263 };
264 UpdateAttr(Opts.ReturnAddresses, "ptrauth-returns");
265 UpdateAttr((bool)Opts.FunctionPointers, "ptrauth-calls");
266 UpdateAttr(Opts.AuthTraps, "ptrauth-auth-traps");
267 UpdateAttr(Opts.IndirectGotos, "ptrauth-indirect-gotos");
268 UpdateAttr(Opts.AArch64JumpTableHardening, "aarch64-jump-table-hardening");
269}
270
272 const PointerAuthOptions &Opts, llvm::AttrBuilder &FuncAttrs) {
273 if (Opts.ReturnAddresses)
274 FuncAttrs.addAttribute("ptrauth-returns");
275 if (Opts.FunctionPointers)
276 FuncAttrs.addAttribute("ptrauth-calls");
277 if (Opts.AuthTraps)
278 FuncAttrs.addAttribute("ptrauth-auth-traps");
279 if (Opts.IndirectGotos)
280 FuncAttrs.addAttribute("ptrauth-indirect-gotos");
282 FuncAttrs.addAttribute("aarch64-jump-table-hardening");
283}
284
285namespace {
286class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
287public:
288 DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
289 : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
290};
291} // namespace
292
293std::unique_ptr<TargetCodeGenInfo>
295 return std::make_unique<DefaultTargetCodeGenInfo>(CGM.getTypes());
296}
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
unsigned getInAllocaFieldIndex() const
llvm::StructType * getCoerceAndExpandType() const
unsigned getIndirectAddrSpace() const
@ Extend
Extend - Valid only for integer argument types.
@ Ignore
Ignore - Ignore the argument (treat as void).
@ IndirectAliased
IndirectAliased - Similar to Indirect, but the pointer may be to an object that is otherwise referenc...
@ Expand
Expand - Only valid for aggregate argument types.
@ TargetSpecific
TargetSpecific - Some argument types are passed as target specific types such as RISC-V's tuple type,...
@ InAlloca
InAlloca - Pass the argument directly using the LLVM inalloca attribute.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
@ CoerceAndExpand
CoerceAndExpand - Only valid for aggregate argument types.
@ Direct
Direct - Pass the argument directly using the normal converted LLVM type, or by coercing to another s...
llvm::Type * getCoerceToType() const
CharUnits getIndirectAlign() const
CallArgList - Type for representing both the value and type of arguments in a call.
Definition CGCall.h:274
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
CodeGenTypes & getTypes() const
llvm::LLVMContext & getLLVMContext()
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
const LangOptions & getLangOpts() const
const CodeGenOptions & getCodeGenOpts() const
void addDefaultFunctionDefinitionAttributes(llvm::AttrBuilder &attrs)
Like the overload taking a Function &, but intended specifically for frontends that want to build on ...
Definition CGCall.cpp:2311
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
unsigned ClangCallConvToLLVMCallConv(CallingConv CC)
Convert clang calling convention to LLVM callilng convention.
Definition CGCall.cpp:55
DefaultABIInfo - The default implementation for ABI specific details.
Definition ABIInfoImpl.h:21
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition TargetInfo.h:49
virtual unsigned getDeviceKernelCallingConv() const
Get LLVM calling convention for device kernels.
virtual unsigned getSizeOfUnwindException() const
Determines the size of struct _Unwind_Exception on this platform, in 8-bit units.
virtual void setOCLKernelStubCallingConvention(const FunctionType *&FT) const
virtual void getDependentLibraryOption(llvm::StringRef Lib, llvm::SmallString< 24 > &Opt) const
Gets the linker options necessary to link a dependent library on this platform.
virtual StringRef getLLVMSyncScopeStr(const LangOptions &LangOpts, SyncScope Scope, llvm::AtomicOrdering Ordering) const
Get the syncscope used in LLVM IR as a string.
llvm::SyncScope::ID getLLVMSyncScopeID(const LangOptions &LangOpts, SyncScope Scope, llvm::AtomicOrdering Ordering, llvm::LLVMContext &Ctx) const
Get the syncscope used in LLVM IR as a SyncScope ID.
static void setBranchProtectionFnAttributes(const TargetInfo::BranchProtectionInfo &BPI, llvm::Function &F)
static void initPointerAuthFnAttributes(const PointerAuthOptions &Opts, llvm::AttrBuilder &FuncAttrs)
static void setPointerAuthFnAttributes(const PointerAuthOptions &Opts, llvm::Function &F)
virtual LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, const VarDecl *D) const
Get target favored AST address space of a global variable for languages other than OpenCL and CUDA.
void addStackProbeTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const
virtual llvm::Constant * getNullPointer(const CodeGen::CodeGenModule &CGM, llvm::PointerType *T, QualType QT) const
Get target specific null pointer.
static void initBranchProtectionFnAttributes(const TargetInfo::BranchProtectionInfo &BPI, llvm::AttrBuilder &FuncAttrs)
TargetCodeGenInfo(std::unique_ptr< ABIInfo > Info)
virtual llvm::Value * createEnqueuedBlockKernel(CodeGenFunction &CGF, llvm::Function *BlockInvokeFunc, llvm::Type *BlockTy) const
Create an OpenCL kernel for an enqueued block.
virtual bool isNoProtoCallVariadic(const CodeGen::CallArgList &args, const FunctionNoProtoType *fnType) const
Determine whether a call to an unprototyped functions under the given calling convention should use t...
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4935
ExtInfo withCallingConv(CallingConv cc) const
Definition TypeBase.h:4776
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4553
ExtInfo getExtInfo() const
Definition TypeBase.h:4909
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A (possibly-)qualified type.
Definition TypeBase.h:937
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8557
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
LangOptions::SignReturnAddressScopeKind SignReturnAddr
const char * getSignReturnAddrStr() const
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Definition CGValue.h:146
std::unique_ptr< TargetCodeGenInfo > createDefaultTargetCodeGenInfo(CodeGenModule &CGM)
The JSON file list parser is used to communicate input to InstallAPI.
LangAS
Defines the address space values used by the address space qualifier of QualType.
SyncScope
Defines sync scope values used internally by clang.
Definition SyncScope.h:42
@ CC_DeviceKernel
Definition Specifiers.h:292
bool ReturnAddresses
Should return addresses be authenticated?
bool AArch64JumpTableHardening
Use hardened lowering for jump-table dispatch?
PointerAuthSchema FunctionPointers
The ABI for C function pointers.
bool AuthTraps
Do authentication failures cause a trap?
bool IndirectGotos
Do indirect goto label addresses need to be authenticated?