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 if (getABIInfo().getContext().getLangOpts().OpenCL) {
117 // Device kernels are called via an explicit runtime API with arguments,
118 // such as set with clSetKernelArg() for OpenCL, not as normal
119 // sub-functions. Return SPIR_KERNEL by default as the kernel calling
120 // convention to ensure the fingerprint is fixed such way that each kernel
121 // argument gets one matching argument in the produced kernel function
122 // argument list to enable feasible implementation of clSetKernelArg() with
123 // aggregates etc. In case we would use the default C calling conv here,
124 // clSetKernelArg() might break depending on the target-specific
125 // conventions; different targets might split structs passed as values
126 // to multiple function arguments etc.
127 return llvm::CallingConv::SPIR_KERNEL;
128 }
129 llvm_unreachable("Unknown kernel calling convention");
130}
131
133 const FunctionType *&FT) const {
134 FT = getABIInfo().getContext().adjustFunctionType(
135 FT, FT->getExtInfo().withCallingConv(CC_C));
136}
137
139 llvm::PointerType *T, QualType QT) const {
140 return llvm::ConstantPointerNull::get(T);
141}
142
144 const VarDecl *D) const {
145 assert(!CGM.getLangOpts().OpenCL &&
146 !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) &&
147 "Address space agnostic languages only");
148 return D ? D->getType().getAddressSpace() : LangAS::Default;
149}
150
151StringRef
154 llvm::AtomicOrdering Ordering) const {
155 return ""; /* default sync scope */
156}
157
158llvm::SyncScope::ID
161 llvm::AtomicOrdering Ordering,
162 llvm::LLVMContext &Ctx) const {
163 return Ctx.getOrInsertSyncScopeID(
164 getLLVMSyncScopeStr(LangOpts, Scope, Ordering));
165}
166
168 const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
169 if (llvm::Function *Fn = dyn_cast_or_null<llvm::Function>(GV)) {
170 if (CGM.getCodeGenOpts().StackProbeSize != 4096)
171 Fn->addFnAttr("stack-probe-size",
172 llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
173 if (CGM.getCodeGenOpts().NoStackArgProbe)
174 Fn->addFnAttr("no-stack-arg-probe");
175 }
176}
177
178/// Create an OpenCL kernel for an enqueued block.
179///
180/// The kernel has the same function type as the block invoke function. Its
181/// name is the name of the block invoke function postfixed with "_kernel".
182/// It simply calls the block invoke function then returns.
184 CodeGenFunction &CGF, llvm::Function *Invoke, llvm::Type *BlockTy) const {
185 auto *InvokeFT = Invoke->getFunctionType();
186 auto &C = CGF.getLLVMContext();
187 std::string Name = Invoke->getName().str() + "_kernel";
188 auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C),
189 InvokeFT->params(), false);
190 auto *F = llvm::Function::Create(FT, llvm::GlobalValue::ExternalLinkage, Name,
191 &CGF.CGM.getModule());
192 llvm::CallingConv::ID KernelCC =
194 F->setCallingConv(KernelCC);
195
196 llvm::AttrBuilder KernelAttrs(C);
197
198 // FIXME: This is missing setTargetAttributes
200 F->addFnAttrs(KernelAttrs);
201
202 auto IP = CGF.Builder.saveIP();
203 auto *BB = llvm::BasicBlock::Create(C, "entry", F);
204 auto &Builder = CGF.Builder;
205 Builder.SetInsertPoint(BB);
206 llvm::SmallVector<llvm::Value *, 2> Args(llvm::make_pointer_range(F->args()));
207 llvm::CallInst *Call = Builder.CreateCall(Invoke, Args);
208 Call->setCallingConv(Invoke->getCallingConv());
209
210 Builder.CreateRetVoid();
211 Builder.restoreIP(IP);
212 return F;
213}
214
216 const TargetInfo::BranchProtectionInfo &BPI, llvm::Function &F) {
217 // Called on already created and initialized function where attributes already
218 // set from command line attributes but some might need to be removed as the
219 // actual BPI is different.
221 F.addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
222 F.addFnAttr("sign-return-address-key", BPI.getSignKeyStr());
223 } else {
224 if (F.hasFnAttribute("sign-return-address"))
225 F.removeFnAttr("sign-return-address");
226 if (F.hasFnAttribute("sign-return-address-key"))
227 F.removeFnAttr("sign-return-address-key");
228 }
229
230 auto AddRemoveAttributeAsSet = [&](bool Set, const StringRef &ModAttr) {
231 if (Set)
232 F.addFnAttr(ModAttr);
233 else if (F.hasFnAttribute(ModAttr))
234 F.removeFnAttr(ModAttr);
235 };
236
237 AddRemoveAttributeAsSet(BPI.BranchTargetEnforcement,
238 "branch-target-enforcement");
239 AddRemoveAttributeAsSet(BPI.BranchProtectionPAuthLR,
240 "branch-protection-pauth-lr");
241 AddRemoveAttributeAsSet(BPI.GuardedControlStack, "guarded-control-stack");
242}
243
245 const TargetInfo::BranchProtectionInfo &BPI, llvm::AttrBuilder &FuncAttrs) {
246 // Only used for initializing attributes in the AttrBuilder, which will not
247 // contain any of these attributes so no need to remove anything.
249 FuncAttrs.addAttribute("sign-return-address", BPI.getSignReturnAddrStr());
250 FuncAttrs.addAttribute("sign-return-address-key", BPI.getSignKeyStr());
251 }
253 FuncAttrs.addAttribute("branch-target-enforcement");
255 FuncAttrs.addAttribute("branch-protection-pauth-lr");
256 if (BPI.GuardedControlStack)
257 FuncAttrs.addAttribute("guarded-control-stack");
258}
259
261 const PointerAuthOptions &Opts, llvm::Function &F) {
262 auto UpdateAttr = [&F](bool AttrShouldExist, StringRef AttrName) {
263 if (AttrShouldExist && !F.hasFnAttribute(AttrName))
264 F.addFnAttr(AttrName);
265 if (!AttrShouldExist && F.hasFnAttribute(AttrName))
266 F.removeFnAttr(AttrName);
267 };
268 UpdateAttr(Opts.ReturnAddresses, "ptrauth-returns");
269 UpdateAttr((bool)Opts.FunctionPointers, "ptrauth-calls");
270 UpdateAttr(Opts.AuthTraps, "ptrauth-auth-traps");
271 UpdateAttr(Opts.IndirectGotos, "ptrauth-indirect-gotos");
272 UpdateAttr(Opts.AArch64JumpTableHardening, "aarch64-jump-table-hardening");
273}
274
276 const PointerAuthOptions &Opts, llvm::AttrBuilder &FuncAttrs) {
277 if (Opts.ReturnAddresses)
278 FuncAttrs.addAttribute("ptrauth-returns");
279 if (Opts.FunctionPointers)
280 FuncAttrs.addAttribute("ptrauth-calls");
281 if (Opts.AuthTraps)
282 FuncAttrs.addAttribute("ptrauth-auth-traps");
283 if (Opts.IndirectGotos)
284 FuncAttrs.addAttribute("ptrauth-indirect-gotos");
286 FuncAttrs.addAttribute("aarch64-jump-table-hardening");
287}
288
289namespace {
290class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
291public:
292 DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
293 : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
294};
295} // namespace
296
297std::unique_ptr<TargetCodeGenInfo>
299 return std::make_unique<DefaultTargetCodeGenInfo>(CGM.getTypes());
300}
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:2309
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:4854
ExtInfo withCallingConv(CallingConv cc) const
Definition TypeBase.h:4695
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4472
ExtInfo getExtInfo() const
Definition TypeBase.h:4828
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:8475
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?