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(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(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>(Src))
138    return performAddrSpaceCast(CGF.CGM, C, SrcAddr, DestAddr, DestTy);
139  // Try to preserve the source's name to make IR more readable.
140  return CGF.Builder.CreateAddrSpaceCast(
141      Src, DestTy, 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(Src, 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(""); /* 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>(GV)) {
164    if (CGM.getCodeGenOpts().StackProbeSize != 4096)
165      Fn->addFnAttr("stack-probe-size",
166                    llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
167    if (CGM.getCodeGenOpts().NoStackArgProbe)
168      Fn->addFnAttr("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(llvm::Type::getVoidTy(C),
183                                     InvokeFT->params(), false);
184  auto *F = llvm::Function::Create(FT, llvm::GlobalValue::ExternalLinkage, Name,
185                                   &CGF.CGM.getModule());
186  llvm::CallingConv::ID KernelCC =
187      CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel);
188  F->setCallingConv(KernelCC);
189
190  llvm::AttrBuilder KernelAttrs(C);
191
192  // FIXME: This is missing setTargetAttributes
193  CGF.CGM.addDefaultFunctionDefinitionAttributes(KernelAttrs);
194  F->addFnAttrs(KernelAttrs);
195
196  auto IP = CGF.Builder.saveIP();
197  auto *BB = llvm::BasicBlock::Create(C, "entry", F);
198  auto &Builder = CGF.Builder;
199  Builder.SetInsertPoint(BB);
200  llvm::SmallVector<llvm::Value *, 2> Args(llvm::make_pointer_range(F->args()));
201  llvm::CallInst *Call = Builder.CreateCall(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>(CGT)) {}
214};
215} // namespace
216
217std::unique_ptr<TargetCodeGenInfo>
218CodeGen::createDefaultTargetCodeGenInfo(CodeGenModule &CGM) {
219  return std::make_unique<DefaultTargetCodeGenInfo>(CGM.getTypes());
220}
221