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/Type.h" |
23 | #include "llvm/Support/raw_ostream.h" |
24 | |
25 | using namespace clang; |
26 | using namespace CodeGen; |
27 | |
28 | LLVM_DUMP_METHOD void ABIArgInfo::dump() const { |
29 | raw_ostream &OS = llvm::errs(); |
30 | OS << "(ABIArgInfo Kind=" ; |
31 | switch (TheKind) { |
32 | case Direct: |
33 | OS << "Direct Type=" ; |
34 | if (llvm::Type *Ty = getCoerceToType()) |
35 | Ty->print(O&: OS); |
36 | else |
37 | OS << "null" ; |
38 | break; |
39 | case Extend: |
40 | OS << "Extend" ; |
41 | break; |
42 | case Ignore: |
43 | OS << "Ignore" ; |
44 | break; |
45 | case InAlloca: |
46 | OS << "InAlloca Offset=" << getInAllocaFieldIndex(); |
47 | break; |
48 | case Indirect: |
49 | OS << "Indirect Align=" << getIndirectAlign().getQuantity() |
50 | << " ByVal=" << getIndirectByVal() |
51 | << " Realign=" << getIndirectRealign(); |
52 | break; |
53 | case IndirectAliased: |
54 | OS << "Indirect Align=" << getIndirectAlign().getQuantity() |
55 | << " AadrSpace=" << getIndirectAddrSpace() |
56 | << " Realign=" << getIndirectRealign(); |
57 | break; |
58 | case Expand: |
59 | OS << "Expand" ; |
60 | break; |
61 | case CoerceAndExpand: |
62 | OS << "CoerceAndExpand Type=" ; |
63 | getCoerceAndExpandType()->print(O&: OS); |
64 | break; |
65 | } |
66 | OS << ")\n" ; |
67 | } |
68 | |
69 | TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info) |
70 | : Info(std::move(Info)) {} |
71 | |
72 | TargetCodeGenInfo::~TargetCodeGenInfo() = default; |
73 | |
74 | // If someone can figure out a general rule for this, that would be great. |
75 | // It's probably just doomed to be platform-dependent, though. |
76 | unsigned TargetCodeGenInfo::getSizeOfUnwindException() const { |
77 | // Verified for: |
78 | // x86-64 FreeBSD, Linux, Darwin |
79 | // x86-32 FreeBSD, Linux, Darwin |
80 | // PowerPC Linux |
81 | // ARM Darwin (*not* EABI) |
82 | // AArch64 Linux |
83 | return 32; |
84 | } |
85 | |
86 | bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args, |
87 | const FunctionNoProtoType *fnType) const { |
88 | // The following conventions are known to require this to be false: |
89 | // x86_stdcall |
90 | // MIPS |
91 | // For everything else, we just prefer false unless we opt out. |
92 | return false; |
93 | } |
94 | |
95 | void |
96 | TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib, |
97 | llvm::SmallString<24> &Opt) const { |
98 | // This assumes the user is passing a library name like "rt" instead of a |
99 | // filename like "librt.a/so", and that they don't care whether it's static or |
100 | // dynamic. |
101 | Opt = "-l" ; |
102 | Opt += Lib; |
103 | } |
104 | |
105 | unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const { |
106 | // OpenCL kernels are called via an explicit runtime API with arguments |
107 | // set with clSetKernelArg(), not as normal sub-functions. |
108 | // Return SPIR_KERNEL by default as the kernel calling convention to |
109 | // ensure the fingerprint is fixed such way that each OpenCL argument |
110 | // gets one matching argument in the produced kernel function argument |
111 | // list to enable feasible implementation of clSetKernelArg() with |
112 | // aggregates etc. In case we would use the default C calling conv here, |
113 | // clSetKernelArg() might break depending on the target-specific |
114 | // conventions; different targets might split structs passed as values |
115 | // to multiple function arguments etc. |
116 | return llvm::CallingConv::SPIR_KERNEL; |
117 | } |
118 | |
119 | llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM, |
120 | llvm::PointerType *T, QualType QT) const { |
121 | return llvm::ConstantPointerNull::get(T); |
122 | } |
123 | |
124 | LangAS TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, |
125 | const VarDecl *D) const { |
126 | assert(!CGM.getLangOpts().OpenCL && |
127 | !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) && |
128 | "Address space agnostic languages only" ); |
129 | return D ? D->getType().getAddressSpace() : LangAS::Default; |
130 | } |
131 | |
132 | llvm::Value *TargetCodeGenInfo::performAddrSpaceCast( |
133 | CodeGen::CodeGenFunction &CGF, llvm::Value *Src, LangAS SrcAddr, |
134 | LangAS DestAddr, llvm::Type *DestTy, bool isNonNull) const { |
135 | // Since target may map different address spaces in AST to the same address |
136 | // space, an address space conversion may end up as a bitcast. |
137 | if (auto *C = dyn_cast<llvm::Constant>(Val: Src)) |
138 | return performAddrSpaceCast(CGM&: CGF.CGM, V: C, SrcAddr, DestAddr, DestTy); |
139 | // Try to preserve the source's name to make IR more readable. |
140 | return CGF.Builder.CreateAddrSpaceCast( |
141 | V: Src, DestTy, Name: Src->hasName() ? Src->getName() + ".ascast" : "" ); |
142 | } |
143 | |
144 | llvm::Constant * |
145 | TargetCodeGenInfo::performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *Src, |
146 | LangAS SrcAddr, LangAS DestAddr, |
147 | llvm::Type *DestTy) const { |
148 | // Since target may map different address spaces in AST to the same address |
149 | // space, an address space conversion may end up as a bitcast. |
150 | return llvm::ConstantExpr::getPointerCast(C: Src, Ty: DestTy); |
151 | } |
152 | |
153 | llvm::SyncScope::ID |
154 | TargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts, |
155 | SyncScope Scope, |
156 | llvm::AtomicOrdering Ordering, |
157 | llvm::LLVMContext &Ctx) const { |
158 | return Ctx.getOrInsertSyncScopeID(SSN: "" ); /* default sync scope */ |
159 | } |
160 | |
161 | void TargetCodeGenInfo::addStackProbeTargetAttributes( |
162 | const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { |
163 | if (llvm::Function *Fn = dyn_cast_or_null<llvm::Function>(Val: GV)) { |
164 | if (CGM.getCodeGenOpts().StackProbeSize != 4096) |
165 | Fn->addFnAttr(Kind: "stack-probe-size" , |
166 | Val: llvm::utostr(X: CGM.getCodeGenOpts().StackProbeSize)); |
167 | if (CGM.getCodeGenOpts().NoStackArgProbe) |
168 | Fn->addFnAttr(Kind: "no-stack-arg-probe" ); |
169 | } |
170 | } |
171 | |
172 | /// Create an OpenCL kernel for an enqueued block. |
173 | /// |
174 | /// The kernel has the same function type as the block invoke function. Its |
175 | /// name is the name of the block invoke function postfixed with "_kernel". |
176 | /// It simply calls the block invoke function then returns. |
177 | llvm::Value *TargetCodeGenInfo::createEnqueuedBlockKernel( |
178 | CodeGenFunction &CGF, llvm::Function *Invoke, llvm::Type *BlockTy) const { |
179 | auto *InvokeFT = Invoke->getFunctionType(); |
180 | auto &C = CGF.getLLVMContext(); |
181 | std::string Name = Invoke->getName().str() + "_kernel" ; |
182 | auto *FT = llvm::FunctionType::get(Result: llvm::Type::getVoidTy(C), |
183 | Params: InvokeFT->params(), isVarArg: false); |
184 | auto *F = llvm::Function::Create(Ty: FT, Linkage: llvm::GlobalValue::ExternalLinkage, N: Name, |
185 | M: &CGF.CGM.getModule()); |
186 | llvm::CallingConv::ID KernelCC = |
187 | CGF.getTypes().ClangCallConvToLLVMCallConv(CC: CallingConv::CC_OpenCLKernel); |
188 | F->setCallingConv(KernelCC); |
189 | |
190 | llvm::AttrBuilder KernelAttrs(C); |
191 | |
192 | // FIXME: This is missing setTargetAttributes |
193 | CGF.CGM.addDefaultFunctionDefinitionAttributes(attrs&: KernelAttrs); |
194 | F->addFnAttrs(Attrs: KernelAttrs); |
195 | |
196 | auto IP = CGF.Builder.saveIP(); |
197 | auto *BB = llvm::BasicBlock::Create(Context&: C, Name: "entry" , Parent: F); |
198 | auto &Builder = CGF.Builder; |
199 | Builder.SetInsertPoint(BB); |
200 | llvm::SmallVector<llvm::Value *, 2> Args(llvm::make_pointer_range(Range: F->args())); |
201 | llvm::CallInst *Call = Builder.CreateCall(Callee: Invoke, Args); |
202 | Call->setCallingConv(Invoke->getCallingConv()); |
203 | |
204 | Builder.CreateRetVoid(); |
205 | Builder.restoreIP(IP); |
206 | return F; |
207 | } |
208 | |
209 | namespace { |
210 | class DefaultTargetCodeGenInfo : public TargetCodeGenInfo { |
211 | public: |
212 | DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) |
213 | : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(args&: CGT)) {} |
214 | }; |
215 | } // namespace |
216 | |
217 | std::unique_ptr<TargetCodeGenInfo> |
218 | CodeGen::createDefaultTargetCodeGenInfo(CodeGenModule &CGM) { |
219 | return std::make_unique<DefaultTargetCodeGenInfo>(args&: CGM.getTypes()); |
220 | } |
221 | |