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" |
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" |
25 | |
26 | using namespace clang; |
27 | using namespace CodeGen; |
28 | |
29 | LLVM_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(O&: 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(O&: OS); |
65 | break; |
66 | } |
67 | OS << ")\n" ; |
68 | } |
69 | |
70 | TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info) |
71 | : Info(std::move(Info)) {} |
72 | |
73 | TargetCodeGenInfo::~TargetCodeGenInfo() = default; |
74 | |
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 { |
78 | // Verified for: |
79 | // x86-64 FreeBSD, Linux, Darwin |
80 | // x86-32 FreeBSD, Linux, Darwin |
81 | // PowerPC Linux |
82 | // ARM Darwin (*not* EABI) |
83 | // AArch64 Linux |
84 | return 32; |
85 | } |
86 | |
87 | bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args, |
88 | const FunctionNoProtoType *fnType) const { |
89 | // The following conventions are known to require this to be false: |
90 | // x86_stdcall |
91 | // MIPS |
92 | // For everything else, we just prefer false unless we opt out. |
93 | return false; |
94 | } |
95 | |
96 | void |
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 |
101 | // dynamic. |
102 | Opt = "-l" ; |
103 | Opt += Lib; |
104 | } |
105 | |
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; |
118 | } |
119 | |
120 | llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM, |
121 | llvm::PointerType *T, QualType QT) const { |
122 | return llvm::ConstantPointerNull::get(T); |
123 | } |
124 | |
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; |
131 | } |
132 | |
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>(Val: Src)) |
139 | return performAddrSpaceCast(CGM&: CGF.CGM, V: C, SrcAddr, DestAddr, DestTy); |
140 | // Try to preserve the source's name to make IR more readable. |
141 | return CGF.Builder.CreateAddrSpaceCast( |
142 | V: Src, DestTy, Name: Src->hasName() ? Src->getName() + ".ascast" : "" ); |
143 | } |
144 | |
145 | llvm::Constant * |
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(C: Src, Ty: DestTy); |
152 | } |
153 | |
154 | llvm::SyncScope::ID |
155 | TargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts, |
156 | SyncScope Scope, |
157 | llvm::AtomicOrdering Ordering, |
158 | llvm::LLVMContext &Ctx) const { |
159 | return Ctx.getOrInsertSyncScopeID(SSN: "" ); /* default sync scope */ |
160 | } |
161 | |
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>(Val: GV)) { |
165 | if (CGM.getCodeGenOpts().StackProbeSize != 4096) |
166 | Fn->addFnAttr(Kind: "stack-probe-size" , |
167 | Val: llvm::utostr(X: CGM.getCodeGenOpts().StackProbeSize)); |
168 | if (CGM.getCodeGenOpts().NoStackArgProbe) |
169 | Fn->addFnAttr(Kind: "no-stack-arg-probe" ); |
170 | } |
171 | } |
172 | |
173 | /// Create an OpenCL kernel for an enqueued block. |
174 | /// |
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(Result: llvm::Type::getVoidTy(C), |
184 | Params: InvokeFT->params(), isVarArg: false); |
185 | auto *F = llvm::Function::Create(Ty: FT, Linkage: llvm::GlobalValue::ExternalLinkage, N: Name, |
186 | M: &CGF.CGM.getModule()); |
187 | llvm::CallingConv::ID KernelCC = |
188 | CGF.getTypes().ClangCallConvToLLVMCallConv(CC: CallingConv::CC_OpenCLKernel); |
189 | F->setCallingConv(KernelCC); |
190 | |
191 | llvm::AttrBuilder KernelAttrs(C); |
192 | |
193 | // FIXME: This is missing setTargetAttributes |
194 | CGF.CGM.addDefaultFunctionDefinitionAttributes(attrs&: KernelAttrs); |
195 | F->addFnAttrs(Attrs: KernelAttrs); |
196 | |
197 | auto IP = CGF.Builder.saveIP(); |
198 | auto *BB = llvm::BasicBlock::Create(Context&: C, Name: "entry" , Parent: F); |
199 | auto &Builder = CGF.Builder; |
200 | Builder.SetInsertPoint(BB); |
201 | llvm::SmallVector<llvm::Value *, 2> Args(llvm::make_pointer_range(Range: F->args())); |
202 | llvm::CallInst *Call = Builder.CreateCall(Callee: Invoke, Args); |
203 | Call->setCallingConv(Invoke->getCallingConv()); |
204 | |
205 | Builder.CreateRetVoid(); |
206 | Builder.restoreIP(IP); |
207 | return F; |
208 | } |
209 | |
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(Kind: "sign-return-address" , Val: BPI.getSignReturnAddrStr()); |
217 | F.addFnAttr(Kind: "sign-return-address-key" , Val: BPI.getSignKeyStr()); |
218 | } else { |
219 | if (F.hasFnAttribute(Kind: "sign-return-address" )) |
220 | F.removeFnAttr(Kind: "sign-return-address" ); |
221 | if (F.hasFnAttribute(Kind: "sign-return-address-key" )) |
222 | F.removeFnAttr(Kind: "sign-return-address-key" ); |
223 | } |
224 | |
225 | auto AddRemoveAttributeAsSet = [&](bool Set, const StringRef &ModAttr) { |
226 | if (Set) |
227 | F.addFnAttr(Kind: ModAttr); |
228 | else if (F.hasFnAttribute(Kind: ModAttr)) |
229 | F.removeFnAttr(Kind: ModAttr); |
230 | }; |
231 | |
232 | AddRemoveAttributeAsSet(BPI.BranchTargetEnforcement, |
233 | "branch-target-enforcement" ); |
234 | AddRemoveAttributeAsSet(BPI.BranchProtectionPAuthLR, |
235 | "branch-protection-pauth-lr" ); |
236 | AddRemoveAttributeAsSet(BPI.GuardedControlStack, "guarded-control-stack" ); |
237 | } |
238 | |
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(A: "sign-return-address" , V: BPI.getSignReturnAddrStr()); |
245 | FuncAttrs.addAttribute(A: "sign-return-address-key" , V: BPI.getSignKeyStr()); |
246 | } |
247 | if (BPI.BranchTargetEnforcement) |
248 | FuncAttrs.addAttribute(A: "branch-target-enforcement" ); |
249 | if (BPI.BranchProtectionPAuthLR) |
250 | FuncAttrs.addAttribute(A: "branch-protection-pauth-lr" ); |
251 | if (BPI.GuardedControlStack) |
252 | FuncAttrs.addAttribute(A: "guarded-control-stack" ); |
253 | } |
254 | |
255 | namespace { |
256 | class DefaultTargetCodeGenInfo : public TargetCodeGenInfo { |
257 | public: |
258 | DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) |
259 | : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(args&: CGT)) {} |
260 | }; |
261 | } // namespace |
262 | |
263 | std::unique_ptr<TargetCodeGenInfo> |
264 | CodeGen::createDefaultTargetCodeGenInfo(CodeGenModule &CGM) { |
265 | return std::make_unique<DefaultTargetCodeGenInfo>(args&: CGM.getTypes()); |
266 | } |
267 | |