/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | LLVM_DUMP_METHOD void ABIArgInfo::dump() const { |
29 | 0 | raw_ostream &OS = llvm::errs(); |
30 | 0 | OS << "(ABIArgInfo Kind="; |
31 | 0 | switch (TheKind) { |
32 | 0 | case Direct: |
33 | 0 | OS << "Direct Type="; |
34 | 0 | if (llvm::Type *Ty = getCoerceToType()) |
35 | 0 | Ty->print(OS); |
36 | 0 | else |
37 | 0 | OS << "null"; |
38 | 0 | break; |
39 | 0 | case Extend: |
40 | 0 | OS << "Extend"; |
41 | 0 | break; |
42 | 0 | case Ignore: |
43 | 0 | OS << "Ignore"; |
44 | 0 | break; |
45 | 0 | case InAlloca: |
46 | 0 | OS << "InAlloca Offset=" << getInAllocaFieldIndex(); |
47 | 0 | break; |
48 | 0 | case Indirect: |
49 | 0 | OS << "Indirect Align=" << getIndirectAlign().getQuantity() |
50 | 0 | << " ByVal=" << getIndirectByVal() |
51 | 0 | << " Realign=" << getIndirectRealign(); |
52 | 0 | break; |
53 | 0 | case IndirectAliased: |
54 | 0 | OS << "Indirect Align=" << getIndirectAlign().getQuantity() |
55 | 0 | << " AadrSpace=" << getIndirectAddrSpace() |
56 | 0 | << " Realign=" << getIndirectRealign(); |
57 | 0 | break; |
58 | 0 | case Expand: |
59 | 0 | OS << "Expand"; |
60 | 0 | break; |
61 | 0 | case CoerceAndExpand: |
62 | 0 | OS << "CoerceAndExpand Type="; |
63 | 0 | getCoerceAndExpandType()->print(OS); |
64 | 0 | break; |
65 | 0 | } |
66 | 0 | OS << ")\n"; |
67 | 0 | } |
68 | | |
69 | | TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info) |
70 | 46 | : Info(std::move(Info)) {} |
71 | | |
72 | 46 | 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 | 0 | 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 | 0 | return 32; |
84 | 0 | } |
85 | | |
86 | | bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args, |
87 | 0 | 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 | 0 | return false; |
93 | 0 | } |
94 | | |
95 | | void |
96 | | TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib, |
97 | 0 | 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 | 0 | Opt = "-l"; |
102 | 0 | Opt += Lib; |
103 | 0 | } |
104 | | |
105 | 0 | 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 | 0 | return llvm::CallingConv::SPIR_KERNEL; |
117 | 0 | } |
118 | | |
119 | | llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM, |
120 | 0 | llvm::PointerType *T, QualType QT) const { |
121 | 0 | return llvm::ConstantPointerNull::get(T); |
122 | 0 | } |
123 | | |
124 | | LangAS TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM, |
125 | 0 | const VarDecl *D) const { |
126 | 0 | assert(!CGM.getLangOpts().OpenCL && |
127 | 0 | !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) && |
128 | 0 | "Address space agnostic languages only"); |
129 | 0 | return D ? D->getType().getAddressSpace() : LangAS::Default; |
130 | 0 | } |
131 | | |
132 | | llvm::Value *TargetCodeGenInfo::performAddrSpaceCast( |
133 | | CodeGen::CodeGenFunction &CGF, llvm::Value *Src, LangAS SrcAddr, |
134 | 0 | 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 | 0 | if (auto *C = dyn_cast<llvm::Constant>(Src)) |
138 | 0 | return performAddrSpaceCast(CGF.CGM, C, SrcAddr, DestAddr, DestTy); |
139 | | // Try to preserve the source's name to make IR more readable. |
140 | 0 | return CGF.Builder.CreateAddrSpaceCast( |
141 | 0 | Src, DestTy, Src->hasName() ? Src->getName() + ".ascast" : ""); |
142 | 0 | } |
143 | | |
144 | | llvm::Constant * |
145 | | TargetCodeGenInfo::performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *Src, |
146 | | LangAS SrcAddr, LangAS DestAddr, |
147 | 0 | 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 | 0 | return llvm::ConstantExpr::getPointerCast(Src, DestTy); |
151 | 0 | } |
152 | | |
153 | | llvm::SyncScope::ID |
154 | | TargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts, |
155 | | SyncScope Scope, |
156 | | llvm::AtomicOrdering Ordering, |
157 | 0 | llvm::LLVMContext &Ctx) const { |
158 | 0 | return Ctx.getOrInsertSyncScopeID(""); /* default sync scope */ |
159 | 0 | } |
160 | | |
161 | | void TargetCodeGenInfo::addStackProbeTargetAttributes( |
162 | 0 | const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const { |
163 | 0 | if (llvm::Function *Fn = dyn_cast_or_null<llvm::Function>(GV)) { |
164 | 0 | if (CGM.getCodeGenOpts().StackProbeSize != 4096) |
165 | 0 | Fn->addFnAttr("stack-probe-size", |
166 | 0 | llvm::utostr(CGM.getCodeGenOpts().StackProbeSize)); |
167 | 0 | if (CGM.getCodeGenOpts().NoStackArgProbe) |
168 | 0 | Fn->addFnAttr("no-stack-arg-probe"); |
169 | 0 | } |
170 | 0 | } |
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 | 0 | CodeGenFunction &CGF, llvm::Function *Invoke, llvm::Type *BlockTy) const { |
179 | 0 | auto *InvokeFT = Invoke->getFunctionType(); |
180 | 0 | auto &C = CGF.getLLVMContext(); |
181 | 0 | std::string Name = Invoke->getName().str() + "_kernel"; |
182 | 0 | auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C), |
183 | 0 | InvokeFT->params(), false); |
184 | 0 | auto *F = llvm::Function::Create(FT, llvm::GlobalValue::ExternalLinkage, Name, |
185 | 0 | &CGF.CGM.getModule()); |
186 | 0 | llvm::CallingConv::ID KernelCC = |
187 | 0 | CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel); |
188 | 0 | F->setCallingConv(KernelCC); |
189 | |
|
190 | 0 | llvm::AttrBuilder KernelAttrs(C); |
191 | | |
192 | | // FIXME: This is missing setTargetAttributes |
193 | 0 | CGF.CGM.addDefaultFunctionDefinitionAttributes(KernelAttrs); |
194 | 0 | F->addFnAttrs(KernelAttrs); |
195 | |
|
196 | 0 | auto IP = CGF.Builder.saveIP(); |
197 | 0 | auto *BB = llvm::BasicBlock::Create(C, "entry", F); |
198 | 0 | auto &Builder = CGF.Builder; |
199 | 0 | Builder.SetInsertPoint(BB); |
200 | 0 | llvm::SmallVector<llvm::Value *, 2> Args(llvm::make_pointer_range(F->args())); |
201 | 0 | llvm::CallInst *Call = Builder.CreateCall(Invoke, Args); |
202 | 0 | Call->setCallingConv(Invoke->getCallingConv()); |
203 | |
|
204 | 0 | Builder.CreateRetVoid(); |
205 | 0 | Builder.restoreIP(IP); |
206 | 0 | return F; |
207 | 0 | } |
208 | | |
209 | | namespace { |
210 | | class DefaultTargetCodeGenInfo : public TargetCodeGenInfo { |
211 | | public: |
212 | | DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) |
213 | 0 | : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {} |
214 | | }; |
215 | | } // namespace |
216 | | |
217 | | std::unique_ptr<TargetCodeGenInfo> |
218 | 0 | CodeGen::createDefaultTargetCodeGenInfo(CodeGenModule &CGM) { |
219 | 0 | return std::make_unique<DefaultTargetCodeGenInfo>(CGM.getTypes()); |
220 | 0 | } |