Coverage Report

Created: 2024-01-17 10:31

/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
}