xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric //===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // These classes wrap the information about a call or function
100b57cec5SDimitry Andric // definition used to handle ABI compliancy.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "TargetInfo.h"
150b57cec5SDimitry Andric #include "ABIInfo.h"
1606c3fb27SDimitry Andric #include "ABIInfoImpl.h"
170b57cec5SDimitry Andric #include "CodeGenFunction.h"
180b57cec5SDimitry Andric #include "clang/Basic/CodeGenOptions.h"
190b57cec5SDimitry Andric #include "clang/CodeGen/CGFunctionInfo.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
220fca6ea1SDimitry Andric #include "llvm/IR/Function.h"
230b57cec5SDimitry Andric #include "llvm/IR/Type.h"
240b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace clang;
270b57cec5SDimitry Andric using namespace CodeGen;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric LLVM_DUMP_METHOD void ABIArgInfo::dump() const {
300b57cec5SDimitry Andric   raw_ostream &OS = llvm::errs();
310b57cec5SDimitry Andric   OS << "(ABIArgInfo Kind=";
320b57cec5SDimitry Andric   switch (TheKind) {
330b57cec5SDimitry Andric   case Direct:
340b57cec5SDimitry Andric     OS << "Direct Type=";
350b57cec5SDimitry Andric     if (llvm::Type *Ty = getCoerceToType())
360b57cec5SDimitry Andric       Ty->print(OS);
370b57cec5SDimitry Andric     else
380b57cec5SDimitry Andric       OS << "null";
390b57cec5SDimitry Andric     break;
400b57cec5SDimitry Andric   case Extend:
410b57cec5SDimitry Andric     OS << "Extend";
420b57cec5SDimitry Andric     break;
430b57cec5SDimitry Andric   case Ignore:
440b57cec5SDimitry Andric     OS << "Ignore";
450b57cec5SDimitry Andric     break;
460b57cec5SDimitry Andric   case InAlloca:
470b57cec5SDimitry Andric     OS << "InAlloca Offset=" << getInAllocaFieldIndex();
480b57cec5SDimitry Andric     break;
490b57cec5SDimitry Andric   case Indirect:
500b57cec5SDimitry Andric     OS << "Indirect Align=" << getIndirectAlign().getQuantity()
510b57cec5SDimitry Andric        << " ByVal=" << getIndirectByVal()
520b57cec5SDimitry Andric        << " Realign=" << getIndirectRealign();
530b57cec5SDimitry Andric     break;
54e8d8bef9SDimitry Andric   case IndirectAliased:
55e8d8bef9SDimitry Andric     OS << "Indirect Align=" << getIndirectAlign().getQuantity()
56e8d8bef9SDimitry Andric        << " AadrSpace=" << getIndirectAddrSpace()
57e8d8bef9SDimitry Andric        << " Realign=" << getIndirectRealign();
58e8d8bef9SDimitry Andric     break;
590b57cec5SDimitry Andric   case Expand:
600b57cec5SDimitry Andric     OS << "Expand";
610b57cec5SDimitry Andric     break;
620b57cec5SDimitry Andric   case CoerceAndExpand:
630b57cec5SDimitry Andric     OS << "CoerceAndExpand Type=";
640b57cec5SDimitry Andric     getCoerceAndExpandType()->print(OS);
650b57cec5SDimitry Andric     break;
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric   OS << ")\n";
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
70fcaf7f86SDimitry Andric TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info)
71fcaf7f86SDimitry Andric     : Info(std::move(Info)) {}
72fcaf7f86SDimitry Andric 
735ffd83dbSDimitry Andric TargetCodeGenInfo::~TargetCodeGenInfo() = default;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric // If someone can figure out a general rule for this, that would be great.
760b57cec5SDimitry Andric // It's probably just doomed to be platform-dependent, though.
770b57cec5SDimitry Andric unsigned TargetCodeGenInfo::getSizeOfUnwindException() const {
780b57cec5SDimitry Andric   // Verified for:
790b57cec5SDimitry Andric   //   x86-64     FreeBSD, Linux, Darwin
800b57cec5SDimitry Andric   //   x86-32     FreeBSD, Linux, Darwin
8106c3fb27SDimitry Andric   //   PowerPC    Linux
820b57cec5SDimitry Andric   //   ARM        Darwin (*not* EABI)
830b57cec5SDimitry Andric   //   AArch64    Linux
840b57cec5SDimitry Andric   return 32;
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric bool TargetCodeGenInfo::isNoProtoCallVariadic(const CallArgList &args,
880b57cec5SDimitry Andric                                      const FunctionNoProtoType *fnType) const {
890b57cec5SDimitry Andric   // The following conventions are known to require this to be false:
900b57cec5SDimitry Andric   //   x86_stdcall
910b57cec5SDimitry Andric   //   MIPS
920b57cec5SDimitry Andric   // For everything else, we just prefer false unless we opt out.
930b57cec5SDimitry Andric   return false;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric void
970b57cec5SDimitry Andric TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib,
980b57cec5SDimitry Andric                                              llvm::SmallString<24> &Opt) const {
990b57cec5SDimitry Andric   // This assumes the user is passing a library name like "rt" instead of a
1000b57cec5SDimitry Andric   // filename like "librt.a/so", and that they don't care whether it's static or
1010b57cec5SDimitry Andric   // dynamic.
1020b57cec5SDimitry Andric   Opt = "-l";
1030b57cec5SDimitry Andric   Opt += Lib;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const {
1070b57cec5SDimitry Andric   // OpenCL kernels are called via an explicit runtime API with arguments
1080b57cec5SDimitry Andric   // set with clSetKernelArg(), not as normal sub-functions.
1090b57cec5SDimitry Andric   // Return SPIR_KERNEL by default as the kernel calling convention to
1100b57cec5SDimitry Andric   // ensure the fingerprint is fixed such way that each OpenCL argument
1110b57cec5SDimitry Andric   // gets one matching argument in the produced kernel function argument
1120b57cec5SDimitry Andric   // list to enable feasible implementation of clSetKernelArg() with
1130b57cec5SDimitry Andric   // aggregates etc. In case we would use the default C calling conv here,
1140b57cec5SDimitry Andric   // clSetKernelArg() might break depending on the target-specific
1150b57cec5SDimitry Andric   // conventions; different targets might split structs passed as values
1160b57cec5SDimitry Andric   // to multiple function arguments etc.
1170b57cec5SDimitry Andric   return llvm::CallingConv::SPIR_KERNEL;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
1210b57cec5SDimitry Andric     llvm::PointerType *T, QualType QT) const {
1220b57cec5SDimitry Andric   return llvm::ConstantPointerNull::get(T);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric LangAS TargetCodeGenInfo::getGlobalVarAddressSpace(CodeGenModule &CGM,
1260b57cec5SDimitry Andric                                                    const VarDecl *D) const {
1270b57cec5SDimitry Andric   assert(!CGM.getLangOpts().OpenCL &&
1280b57cec5SDimitry Andric          !(CGM.getLangOpts().CUDA && CGM.getLangOpts().CUDAIsDevice) &&
1290b57cec5SDimitry Andric          "Address space agnostic languages only");
1300b57cec5SDimitry Andric   return D ? D->getType().getAddressSpace() : LangAS::Default;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric llvm::Value *TargetCodeGenInfo::performAddrSpaceCast(
1340b57cec5SDimitry Andric     CodeGen::CodeGenFunction &CGF, llvm::Value *Src, LangAS SrcAddr,
1350b57cec5SDimitry Andric     LangAS DestAddr, llvm::Type *DestTy, bool isNonNull) const {
1360b57cec5SDimitry Andric   // Since target may map different address spaces in AST to the same address
1370b57cec5SDimitry Andric   // space, an address space conversion may end up as a bitcast.
1380b57cec5SDimitry Andric   if (auto *C = dyn_cast<llvm::Constant>(Src))
1390b57cec5SDimitry Andric     return performAddrSpaceCast(CGF.CGM, C, SrcAddr, DestAddr, DestTy);
1400b57cec5SDimitry Andric   // Try to preserve the source's name to make IR more readable.
1415f757f3fSDimitry Andric   return CGF.Builder.CreateAddrSpaceCast(
1420b57cec5SDimitry Andric       Src, DestTy, Src->hasName() ? Src->getName() + ".ascast" : "");
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric llvm::Constant *
1460b57cec5SDimitry Andric TargetCodeGenInfo::performAddrSpaceCast(CodeGenModule &CGM, llvm::Constant *Src,
1470b57cec5SDimitry Andric                                         LangAS SrcAddr, LangAS DestAddr,
1480b57cec5SDimitry Andric                                         llvm::Type *DestTy) const {
1490b57cec5SDimitry Andric   // Since target may map different address spaces in AST to the same address
1500b57cec5SDimitry Andric   // space, an address space conversion may end up as a bitcast.
1510b57cec5SDimitry Andric   return llvm::ConstantExpr::getPointerCast(Src, DestTy);
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric llvm::SyncScope::ID
1550b57cec5SDimitry Andric TargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts,
1560b57cec5SDimitry Andric                                       SyncScope Scope,
1570b57cec5SDimitry Andric                                       llvm::AtomicOrdering Ordering,
1580b57cec5SDimitry Andric                                       llvm::LLVMContext &Ctx) const {
1590b57cec5SDimitry Andric   return Ctx.getOrInsertSyncScopeID(""); /* default sync scope */
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
16206c3fb27SDimitry Andric void TargetCodeGenInfo::addStackProbeTargetAttributes(
1630b57cec5SDimitry Andric     const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const {
1640b57cec5SDimitry Andric   if (llvm::Function *Fn = dyn_cast_or_null<llvm::Function>(GV)) {
1650b57cec5SDimitry Andric     if (CGM.getCodeGenOpts().StackProbeSize != 4096)
1660b57cec5SDimitry Andric       Fn->addFnAttr("stack-probe-size",
1670b57cec5SDimitry Andric                     llvm::utostr(CGM.getCodeGenOpts().StackProbeSize));
1680b57cec5SDimitry Andric     if (CGM.getCodeGenOpts().NoStackArgProbe)
1690b57cec5SDimitry Andric       Fn->addFnAttr("no-stack-arg-probe");
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric /// Create an OpenCL kernel for an enqueued block.
1740b57cec5SDimitry Andric ///
1750b57cec5SDimitry Andric /// The kernel has the same function type as the block invoke function. Its
1760b57cec5SDimitry Andric /// name is the name of the block invoke function postfixed with "_kernel".
1770b57cec5SDimitry Andric /// It simply calls the block invoke function then returns.
17806c3fb27SDimitry Andric llvm::Value *TargetCodeGenInfo::createEnqueuedBlockKernel(
17906c3fb27SDimitry Andric     CodeGenFunction &CGF, llvm::Function *Invoke, llvm::Type *BlockTy) const {
1800b57cec5SDimitry Andric   auto *InvokeFT = Invoke->getFunctionType();
1810b57cec5SDimitry Andric   auto &C = CGF.getLLVMContext();
1820b57cec5SDimitry Andric   std::string Name = Invoke->getName().str() + "_kernel";
18381ad6265SDimitry Andric   auto *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(C),
18481ad6265SDimitry Andric                                      InvokeFT->params(), false);
18504eeddc0SDimitry Andric   auto *F = llvm::Function::Create(FT, llvm::GlobalValue::ExternalLinkage, Name,
1860b57cec5SDimitry Andric                                    &CGF.CGM.getModule());
18706c3fb27SDimitry Andric   llvm::CallingConv::ID KernelCC =
18806c3fb27SDimitry Andric       CGF.getTypes().ClangCallConvToLLVMCallConv(CallingConv::CC_OpenCLKernel);
18906c3fb27SDimitry Andric   F->setCallingConv(KernelCC);
19006c3fb27SDimitry Andric 
19106c3fb27SDimitry Andric   llvm::AttrBuilder KernelAttrs(C);
19206c3fb27SDimitry Andric 
19306c3fb27SDimitry Andric   // FIXME: This is missing setTargetAttributes
19406c3fb27SDimitry Andric   CGF.CGM.addDefaultFunctionDefinitionAttributes(KernelAttrs);
19506c3fb27SDimitry Andric   F->addFnAttrs(KernelAttrs);
19606c3fb27SDimitry Andric 
1970b57cec5SDimitry Andric   auto IP = CGF.Builder.saveIP();
1980b57cec5SDimitry Andric   auto *BB = llvm::BasicBlock::Create(C, "entry", F);
1990b57cec5SDimitry Andric   auto &Builder = CGF.Builder;
2000b57cec5SDimitry Andric   Builder.SetInsertPoint(BB);
20181ad6265SDimitry Andric   llvm::SmallVector<llvm::Value *, 2> Args(llvm::make_pointer_range(F->args()));
20206c3fb27SDimitry Andric   llvm::CallInst *Call = Builder.CreateCall(Invoke, Args);
20306c3fb27SDimitry Andric   Call->setCallingConv(Invoke->getCallingConv());
20406c3fb27SDimitry Andric 
2050b57cec5SDimitry Andric   Builder.CreateRetVoid();
2060b57cec5SDimitry Andric   Builder.restoreIP(IP);
2070b57cec5SDimitry Andric   return F;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100fca6ea1SDimitry Andric void TargetCodeGenInfo::setBranchProtectionFnAttributes(
2110fca6ea1SDimitry Andric     const TargetInfo::BranchProtectionInfo &BPI, llvm::Function &F) {
212*62987288SDimitry Andric   // Called on already created and initialized function where attributes already
213*62987288SDimitry Andric   // set from command line attributes but some might need to be removed as the
214*62987288SDimitry Andric   // actual BPI is different.
215*62987288SDimitry Andric   if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
216*62987288SDimitry Andric     F.addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
217*62987288SDimitry Andric     F.addFnAttr("sign-return-address-key", BPI.getSignKeyStr());
218*62987288SDimitry Andric   } else {
219*62987288SDimitry Andric     if (F.hasFnAttribute("sign-return-address"))
220*62987288SDimitry Andric       F.removeFnAttr("sign-return-address");
221*62987288SDimitry Andric     if (F.hasFnAttribute("sign-return-address-key"))
222*62987288SDimitry Andric       F.removeFnAttr("sign-return-address-key");
2230fca6ea1SDimitry Andric   }
2240fca6ea1SDimitry Andric 
225*62987288SDimitry Andric   auto AddRemoveAttributeAsSet = [&](bool Set, const StringRef &ModAttr) {
226*62987288SDimitry Andric     if (Set)
227*62987288SDimitry Andric       F.addFnAttr(ModAttr);
228*62987288SDimitry Andric     else if (F.hasFnAttribute(ModAttr))
229*62987288SDimitry Andric       F.removeFnAttr(ModAttr);
230*62987288SDimitry Andric   };
231*62987288SDimitry Andric 
232*62987288SDimitry Andric   AddRemoveAttributeAsSet(BPI.BranchTargetEnforcement,
233*62987288SDimitry Andric                           "branch-target-enforcement");
234*62987288SDimitry Andric   AddRemoveAttributeAsSet(BPI.BranchProtectionPAuthLR,
235*62987288SDimitry Andric                           "branch-protection-pauth-lr");
236*62987288SDimitry Andric   AddRemoveAttributeAsSet(BPI.GuardedControlStack, "guarded-control-stack");
237*62987288SDimitry Andric }
238*62987288SDimitry Andric 
239*62987288SDimitry Andric void TargetCodeGenInfo::initBranchProtectionFnAttributes(
2400fca6ea1SDimitry Andric     const TargetInfo::BranchProtectionInfo &BPI, llvm::AttrBuilder &FuncAttrs) {
241*62987288SDimitry Andric   // Only used for initializing attributes in the AttrBuilder, which will not
242*62987288SDimitry Andric   // contain any of these attributes so no need to remove anything.
2430fca6ea1SDimitry Andric   if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
2440fca6ea1SDimitry Andric     FuncAttrs.addAttribute("sign-return-address", BPI.getSignReturnAddrStr());
2450fca6ea1SDimitry Andric     FuncAttrs.addAttribute("sign-return-address-key", BPI.getSignKeyStr());
2460fca6ea1SDimitry Andric   }
2470fca6ea1SDimitry Andric   if (BPI.BranchTargetEnforcement)
2480fca6ea1SDimitry Andric     FuncAttrs.addAttribute("branch-target-enforcement");
2490fca6ea1SDimitry Andric   if (BPI.BranchProtectionPAuthLR)
2500fca6ea1SDimitry Andric     FuncAttrs.addAttribute("branch-protection-pauth-lr");
2510fca6ea1SDimitry Andric   if (BPI.GuardedControlStack)
2520fca6ea1SDimitry Andric     FuncAttrs.addAttribute("guarded-control-stack");
2530fca6ea1SDimitry Andric }
2540fca6ea1SDimitry Andric 
25506c3fb27SDimitry Andric namespace {
25606c3fb27SDimitry Andric class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
25706c3fb27SDimitry Andric public:
25806c3fb27SDimitry Andric   DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
25906c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
26006c3fb27SDimitry Andric };
26106c3fb27SDimitry Andric } // namespace
2620b57cec5SDimitry Andric 
26306c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
26406c3fb27SDimitry Andric CodeGen::createDefaultTargetCodeGenInfo(CodeGenModule &CGM) {
26506c3fb27SDimitry Andric   return std::make_unique<DefaultTargetCodeGenInfo>(CGM.getTypes());
2660b57cec5SDimitry Andric }
267