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
25using namespace clang;
26using namespace CodeGen;
27
28LLVM_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
69TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info)
70 : Info(std::move(Info)) {}
71
72TargetCodeGenInfo::~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.
76unsigned 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
86bool 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
95void
96TargetCodeGenInfo::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
105unsigned 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
119llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
120 llvm::PointerType *T, QualType QT) const {
121 return llvm::ConstantPointerNull::get(T);
122}
123
124LangAS 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
132llvm::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
144llvm::Constant *
145TargetCodeGenInfo::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
153llvm::SyncScope::ID
154TargetCodeGenInfo::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
161void 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.
177llvm::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
209namespace {
210class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
211public:
212 DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
213 : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(args&: CGT)) {}
214};
215} // namespace
216
217std::unique_ptr<TargetCodeGenInfo>
218CodeGen::createDefaultTargetCodeGenInfo(CodeGenModule &CGM) {
219 return std::make_unique<DefaultTargetCodeGenInfo>(args&: CGM.getTypes());
220}
221

source code of clang/lib/CodeGen/TargetInfo.cpp