barannikov88 created this revision.
Herald added a project: All.
barannikov88 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147962

Files:
  clang/lib/CodeGen/ABIInfoImpl.h
  clang/lib/CodeGen/CMakeLists.txt
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/CodeGen/Targets/ARC.cpp
  clang/lib/CodeGen/Targets/ARC.h
  clang/lib/CodeGen/Targets/CSKY.cpp
  clang/lib/CodeGen/Targets/CSKY.h
  clang/lib/CodeGen/Targets/M68k.cpp
  clang/lib/CodeGen/Targets/M68k.h
  clang/lib/CodeGen/Targets/SPIR.cpp
  clang/lib/CodeGen/Targets/SPIR.h

Index: clang/lib/CodeGen/Targets/SPIR.h
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/SPIR.h
@@ -0,0 +1,37 @@
+//===- SPIR.h ---------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_CODEGEN_TARGETS_SPIR_H
+#define CLANG_LIB_CODEGEN_TARGETS_SPIR_H
+
+#include "TargetInfo.h"
+
+namespace clang::CodeGen {
+
+class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  explicit CommonSPIRTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT);
+  explicit CommonSPIRTargetCodeGenInfo(std::unique_ptr<ABIInfo> ABIInfo);
+
+  LangAS getASTAllocaAddressSpace() const override;
+
+  unsigned getOpenCLKernelCallingConv() const override;
+
+  llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override;
+};
+
+class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo {
+public:
+  explicit SPIRVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT);
+
+  void setCUDAKernelCallingConvention(const FunctionType *&FT) const override;
+};
+
+} // namespace clang::CodeGen
+
+#endif // CLANG_LIB_CODEGEN_TARGETS_SPIR_H
Index: clang/lib/CodeGen/Targets/SPIR.cpp
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/SPIR.cpp
@@ -0,0 +1,201 @@
+//===- SPIR.cpp -----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Base ABI and target codegen info implementation common between SPIR and
+// SPIR-V.
+//===----------------------------------------------------------------------===//
+
+#include "SPIR.h"
+#include "ABIInfoImpl.h"
+
+using namespace clang;
+using namespace clang::CodeGen;
+
+//===----------------------------------------------------------------------===//
+
+namespace {
+class CommonSPIRABIInfo : public DefaultABIInfo {
+public:
+  explicit CommonSPIRABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {
+    setCCs();
+  }
+
+private:
+  void setCCs();
+};
+
+class SPIRVABIInfo : public CommonSPIRABIInfo {
+public:
+  explicit SPIRVABIInfo(CodeGenTypes &CGT) : CommonSPIRABIInfo(CGT) {}
+
+  void computeInfo(CGFunctionInfo &FI) const override;
+
+private:
+  ABIArgInfo classifyKernelArgumentType(QualType Ty) const;
+};
+} // namespace
+
+void CommonSPIRABIInfo::setCCs() {
+  assert(getRuntimeCC() == llvm::CallingConv::C);
+  RuntimeCC = llvm::CallingConv::SPIR_FUNC;
+}
+
+ABIArgInfo SPIRVABIInfo::classifyKernelArgumentType(QualType Ty) const {
+  if (getContext().getLangOpts().CUDAIsDevice) {
+    // Coerce pointer arguments with default address space to CrossWorkGroup
+    // pointers for HIPSPV/CUDASPV. When the language mode is HIP/CUDA, the
+    // SPIRTargetInfo maps cuda_device to SPIR-V's CrossWorkGroup address space.
+    llvm::Type *LTy = CGT.ConvertType(Ty);
+    auto DefaultAS = getContext().getTargetAddressSpace(LangAS::Default);
+    auto GlobalAS = getContext().getTargetAddressSpace(LangAS::cuda_device);
+    auto *PtrTy = llvm::dyn_cast<llvm::PointerType>(LTy);
+    if (PtrTy && PtrTy->getAddressSpace() == DefaultAS) {
+      LTy = llvm::PointerType::getWithSamePointeeType(PtrTy, GlobalAS);
+      return ABIArgInfo::getDirect(LTy, 0, nullptr, false);
+    }
+
+    // Force copying aggregate type in kernel arguments by value when
+    // compiling CUDA targeting SPIR-V. This is required for the object
+    // copied to be valid on the device.
+    // This behavior follows the CUDA spec
+    // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-function-argument-processing,
+    // and matches the NVPTX implementation.
+    if (isAggregateTypeForABI(Ty))
+      return getNaturalAlignIndirect(Ty, /* byval */ true);
+  }
+  return classifyArgumentType(Ty);
+}
+
+void SPIRVABIInfo::computeInfo(CGFunctionInfo &FI) const {
+  // The logic is same as in DefaultABIInfo with an exception on the kernel
+  // arguments handling.
+  llvm::CallingConv::ID CC = FI.getCallingConvention();
+
+  if (!getCXXABI().classifyReturnType(FI))
+    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+  for (auto &I : FI.arguments()) {
+    if (CC == llvm::CallingConv::SPIR_KERNEL) {
+      I.info = classifyKernelArgumentType(I.type);
+    } else {
+      I.info = classifyArgumentType(I.type);
+    }
+  }
+}
+
+CommonSPIRTargetCodeGenInfo::CommonSPIRTargetCodeGenInfo(CodeGenTypes &CGT)
+    : TargetCodeGenInfo(std::make_unique<CommonSPIRABIInfo>(CGT)) {}
+
+CommonSPIRTargetCodeGenInfo::CommonSPIRTargetCodeGenInfo(
+    std::unique_ptr<ABIInfo> ABIInfo)
+    : TargetCodeGenInfo(std::move(ABIInfo)) {}
+
+LangAS CommonSPIRTargetCodeGenInfo::getASTAllocaAddressSpace() const {
+  return getLangASFromTargetAS(
+      getABIInfo().getDataLayout().getAllocaAddrSpace());
+}
+
+unsigned CommonSPIRTargetCodeGenInfo::getOpenCLKernelCallingConv() const {
+  return llvm::CallingConv::SPIR_KERNEL;
+}
+
+/// Construct a SPIR-V target extension type for the given OpenCL image type.
+static llvm::Type *getSPIRVImageType(llvm::LLVMContext &Ctx, StringRef BaseType,
+                                     StringRef OpenCLName,
+                                     unsigned AccessQualifier) {
+  // These parameters compare to the operands of OpTypeImage (see
+  // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage
+  // for more details). The first 6 integer parameters all default to 0, and
+  // will be changed to 1 only for the image type(s) that set the parameter to
+  // one. The 7th integer parameter is the access qualifier, which is tacked on
+  // at the end.
+  SmallVector<unsigned, 7> IntParams = {0, 0, 0, 0, 0, 0};
+
+  // Choose the dimension of the image--this corresponds to the Dim enum in
+  // SPIR-V (first integer parameter of OpTypeImage).
+  if (OpenCLName.startswith("image2d"))
+    IntParams[0] = 1; // 1D
+  else if (OpenCLName.startswith("image3d"))
+    IntParams[0] = 2; // 2D
+  else if (OpenCLName == "image1d_buffer")
+    IntParams[0] = 5; // Buffer
+  else
+    assert(OpenCLName.startswith("image1d") && "Unknown image type");
+
+  // Set the other integer parameters of OpTypeImage if necessary. Note that the
+  // OpenCL image types don't provide any information for the Sampled or
+  // Image Format parameters.
+  if (OpenCLName.contains("_depth"))
+    IntParams[1] = 1;
+  if (OpenCLName.contains("_array"))
+    IntParams[2] = 1;
+  if (OpenCLName.contains("_msaa"))
+    IntParams[3] = 1;
+
+  // Access qualifier
+  IntParams.push_back(AccessQualifier);
+
+  return llvm::TargetExtType::get(Ctx, BaseType, {llvm::Type::getVoidTy(Ctx)},
+                                  IntParams);
+}
+
+llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM,
+                                                       const Type *Ty) const {
+  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
+  if (auto *PipeTy = dyn_cast<PipeType>(Ty))
+    return llvm::TargetExtType::get(Ctx, "spirv.Pipe", {},
+                                    {!PipeTy->isReadOnly()});
+  if (auto *BuiltinTy = dyn_cast<BuiltinType>(Ty)) {
+    enum AccessQualifier : unsigned { AQ_ro = 0, AQ_wo = 1, AQ_rw = 2 };
+    switch (BuiltinTy->getKind()) {
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
+  case BuiltinType::Id:                                                        \
+    return getSPIRVImageType(Ctx, "spirv.Image", #ImgType, AQ_##Suffix);
+#include "clang/Basic/OpenCLImageTypes.def"
+    case BuiltinType::OCLSampler:
+      return llvm::TargetExtType::get(Ctx, "spirv.Sampler");
+    case BuiltinType::OCLEvent:
+      return llvm::TargetExtType::get(Ctx, "spirv.Event");
+    case BuiltinType::OCLClkEvent:
+      return llvm::TargetExtType::get(Ctx, "spirv.DeviceEvent");
+    case BuiltinType::OCLQueue:
+      return llvm::TargetExtType::get(Ctx, "spirv.Queue");
+    case BuiltinType::OCLReserveID:
+      return llvm::TargetExtType::get(Ctx, "spirv.ReserveId");
+#define INTEL_SUBGROUP_AVC_TYPE(Name, Id)                                      \
+  case BuiltinType::OCLIntelSubgroupAVC##Id:                                   \
+    return llvm::TargetExtType::get(Ctx, "spirv.Avc" #Id "INTEL");
+#include "clang/Basic/OpenCLExtensionTypes.def"
+    default:
+      return nullptr;
+    }
+  }
+
+  return nullptr;
+}
+
+SPIRVTargetCodeGenInfo::SPIRVTargetCodeGenInfo(CodeGenTypes &CGT)
+    : CommonSPIRTargetCodeGenInfo(std::make_unique<SPIRVABIInfo>(CGT)) {}
+
+void SPIRVTargetCodeGenInfo::setCUDAKernelCallingConvention(
+    const FunctionType *&FT) const {
+  // Convert HIP kernels to SPIR-V kernels.
+  if (getABIInfo().getContext().getLangOpts().HIP) {
+    FT = getABIInfo().getContext().adjustFunctionType(
+        FT, FT->getExtInfo().withCallingConv(CC_OpenCLKernel));
+    return;
+  }
+}
+
+namespace clang::CodeGen {
+void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) {
+  if (CGM.getTarget().getTriple().isSPIRV())
+    SPIRVABIInfo(CGM.getTypes()).computeInfo(FI);
+  else
+    CommonSPIRABIInfo(CGM.getTypes()).computeInfo(FI);
+}
+} // namespace clang::CodeGen
Index: clang/lib/CodeGen/Targets/M68k.h
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/M68k.h
@@ -0,0 +1,26 @@
+//===- M68k.h ---------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_TARGET_M68K_H
+#define LLVM_CLANG_LIB_CODEGEN_TARGET_M68K_H
+
+#include "TargetInfo.h"
+
+namespace clang::CodeGen {
+
+class M68kTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  explicit M68kTargetCodeGenInfo(CodeGenTypes &CGT);
+
+  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+                           CodeGen::CodeGenModule &M) const override;
+};
+
+} // namespace clang::CodeGen
+
+#endif // LLVM_CLANG_LIB_CODEGEN_TARGET_M68K_H
Index: clang/lib/CodeGen/Targets/M68k.cpp
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/M68k.cpp
@@ -0,0 +1,39 @@
+//===- M68k.cpp -----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// M68k ABI Implementation
+//===----------------------------------------------------------------------===//
+
+#include "M68k.h"
+#include "ABIInfoImpl.h"
+
+using namespace clang;
+using namespace clang::CodeGen;
+
+M68kTargetCodeGenInfo::M68kTargetCodeGenInfo(CodeGenTypes &CGT)
+    : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
+
+void M68kTargetCodeGenInfo::setTargetAttributes(
+    const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+  if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+    if (const auto *attr = FD->getAttr<M68kInterruptAttr>()) {
+      // Handle 'interrupt' attribute:
+      llvm::Function *F = cast<llvm::Function>(GV);
+
+      // Step 1: Set ISR calling convention.
+      F->setCallingConv(llvm::CallingConv::M68k_INTR);
+
+      // Step 2: Add attributes goodness.
+      F->addFnAttr(llvm::Attribute::NoInline);
+
+      // Step 3: Emit ISR vector alias.
+      unsigned Num = attr->getNumber() / 2;
+      llvm::GlobalAlias::create(llvm::Function::ExternalLinkage,
+                                "__isr_" + Twine(Num), F);
+    }
+  }
+}
Index: clang/lib/CodeGen/Targets/CSKY.h
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/CSKY.h
@@ -0,0 +1,23 @@
+//===- CSKY.h ---------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_TARGETS_CSKY_H
+#define LLVM_CLANG_LIB_CODEGEN_TARGETS_CSKY_H
+
+#include "TargetInfo.h"
+
+namespace clang::CodeGen {
+
+class CSKYTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen);
+};
+
+} // namespace clang::CodeGen
+
+#endif // LLVM_CLANG_LIB_CODEGEN_TARGETS_CSKY_H
Index: clang/lib/CodeGen/Targets/CSKY.cpp
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/CSKY.cpp
@@ -0,0 +1,167 @@
+//===- CSKY.cpp -----------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// CSKY ABI Implementation
+//===----------------------------------------------------------------------===//
+
+#include "CSKY.h"
+#include "ABIInfoImpl.h"
+
+using namespace clang;
+using namespace clang::CodeGen;
+
+//===----------------------------------------------------------------------===//
+// CSKY ABI Implementation
+//===----------------------------------------------------------------------===//
+namespace {
+class CSKYABIInfo : public DefaultABIInfo {
+  static const int NumArgGPRs = 4;
+  static const int NumArgFPRs = 4;
+
+  static const unsigned XLen = 32;
+  unsigned FLen;
+
+public:
+  CSKYABIInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)
+      : DefaultABIInfo(CGT), FLen(FLen) {}
+
+  void computeInfo(CGFunctionInfo &FI) const override;
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                    QualType Ty) const override;
+
+private:
+  ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
+                                  int &ArgFPRsLeft,
+                                  bool isReturnType = false) const;
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+};
+} // namespace
+
+void CSKYABIInfo::computeInfo(CGFunctionInfo &FI) const {
+  QualType RetTy = FI.getReturnType();
+  if (!getCXXABI().classifyReturnType(FI))
+    FI.getReturnInfo() = classifyReturnType(RetTy);
+
+  bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;
+
+  // We must track the number of GPRs used in order to conform to the CSKY
+  // ABI, as integer scalars passed in registers should have signext/zeroext
+  // when promoted.
+  int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
+  int ArgFPRsLeft = FLen ? NumArgFPRs : 0;
+
+  for (auto &ArgInfo : FI.arguments())
+    ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft, ArgFPRsLeft);
+}
+
+Address CSKYABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                               QualType Ty) const {
+  CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8);
+
+  // Empty records are ignored for parameter passing purposes.
+  if (isEmptyRecord(getContext(), Ty, true)) {
+    Address Addr = Address(CGF.Builder.CreateLoad(VAListAddr),
+                           getVAListElementType(CGF), SlotSize);
+    Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
+    return Addr;
+  }
+
+  auto TInfo = getContext().getTypeInfoInChars(Ty);
+
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, false, TInfo, SlotSize,
+                          /*AllowHigherAlign=*/true);
+}
+
+ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
+                                             int &ArgFPRsLeft,
+                                             bool isReturnType) const {
+  assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");
+  Ty = useFirstFieldIfTransparentUnion(Ty);
+
+  // Structures with either a non-trivial destructor or a non-trivial
+  // copy constructor are always passed indirectly.
+  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
+    if (ArgGPRsLeft)
+      ArgGPRsLeft -= 1;
+    return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
+                                           CGCXXABI::RAA_DirectInMemory);
+  }
+
+  // Ignore empty structs/unions.
+  if (isEmptyRecord(getContext(), Ty, true))
+    return ABIArgInfo::getIgnore();
+
+  if (!Ty->getAsUnionType())
+    if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
+      return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
+
+  uint64_t Size = getContext().getTypeSize(Ty);
+  // Pass floating point values via FPRs if possible.
+  if (Ty->isFloatingType() && !Ty->isComplexType() && FLen >= Size &&
+      ArgFPRsLeft) {
+    ArgFPRsLeft--;
+    return ABIArgInfo::getDirect();
+  }
+
+  // Complex types for the hard float ABI must be passed direct rather than
+  // using CoerceAndExpand.
+  if (Ty->isComplexType() && FLen && !isReturnType) {
+    QualType EltTy = Ty->castAs<ComplexType>()->getElementType();
+    if (getContext().getTypeSize(EltTy) <= FLen) {
+      ArgFPRsLeft -= 2;
+      return ABIArgInfo::getDirect();
+    }
+  }
+
+  if (!isAggregateTypeForABI(Ty)) {
+    // Treat an enum type as its underlying type.
+    if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+      Ty = EnumTy->getDecl()->getIntegerType();
+
+    // All integral types are promoted to XLen width, unless passed on the
+    // stack.
+    if (Size < XLen && Ty->isIntegralOrEnumerationType())
+      return ABIArgInfo::getExtend(Ty);
+
+    if (const auto *EIT = Ty->getAs<BitIntType>())
+      if (EIT->getNumBits() < XLen)
+        return ABIArgInfo::getExtend(Ty);
+
+    return ABIArgInfo::getDirect();
+  }
+
+  // For argument type, the first 4*XLen parts of aggregate will be passed
+  // in registers, and the rest will be passed in stack.
+  // So we can coerce to integers directly and let backend handle it correctly.
+  // For return type, aggregate which <= 2*XLen will be returned in registers.
+  // Otherwise, aggregate will be returned indirectly.
+  if (!isReturnType || (isReturnType && Size <= 2 * XLen)) {
+    if (Size <= XLen) {
+      return ABIArgInfo::getDirect(
+          llvm::IntegerType::get(getVMContext(), XLen));
+    }
+    return ABIArgInfo::getDirect(llvm::ArrayType::get(
+        llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen));
+  }
+  return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+}
+
+ABIArgInfo CSKYABIInfo::classifyReturnType(QualType RetTy) const {
+  if (RetTy->isVoidType())
+    return ABIArgInfo::getIgnore();
+
+  int ArgGPRsLeft = 2;
+  int ArgFPRsLeft = FLen ? 1 : 0;
+
+  // The rules for return and argument types are the same, so defer to
+  // classifyArgumentType.
+  return classifyArgumentType(RetTy, ArgGPRsLeft, ArgFPRsLeft, true);
+}
+
+CSKYTargetCodeGenInfo::CSKYTargetCodeGenInfo(CodeGenTypes &CGT, unsigned FLen)
+    : TargetCodeGenInfo(std::make_unique<CSKYABIInfo>(CGT, FLen)) {}
Index: clang/lib/CodeGen/Targets/ARC.h
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/ARC.h
@@ -0,0 +1,23 @@
+//===- ARC.h ----------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_TARGETS_ARC_H
+#define LLVM_CLANG_LIB_CODEGEN_TARGETS_ARC_H
+
+#include "TargetInfo.h"
+
+namespace clang::CodeGen {
+
+class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  explicit ARCTargetCodeGenInfo(CodeGenTypes &CGT);
+};
+
+} // namespace clang::CodeGen
+
+#endif // LLVM_CLANG_LIB_CODEGEN_TARGETS_ARC_H
Index: clang/lib/CodeGen/Targets/ARC.cpp
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/Targets/ARC.cpp
@@ -0,0 +1,153 @@
+//===- ARC.cpp ------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// ARC ABI Implementation
+//===----------------------------------------------------------------------===//
+
+#include "ARC.h"
+#include "ABIInfoImpl.h"
+
+using namespace clang;
+using namespace clang::CodeGen;
+
+namespace {
+class ARCABIInfo : public DefaultABIInfo {
+  struct CCState {
+    unsigned FreeRegs;
+  };
+
+public:
+  explicit ARCABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+
+  void computeInfo(CGFunctionInfo &FI) const override;
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                    QualType Ty) const override;
+
+private:
+  void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const;
+
+  ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
+  ABIArgInfo getIndirectByValue(QualType Ty) const;
+  ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+};
+} // namespace
+
+void ARCABIInfo::updateState(const ABIArgInfo &Info, QualType Ty,
+                             ARCABIInfo::CCState &State) const {
+  if (!State.FreeRegs)
+    return;
+  if (Info.isIndirect() && Info.getInReg()) {
+    State.FreeRegs--;
+  } else if (Info.isDirect() && Info.getInReg()) {
+    unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
+    if (sz < State.FreeRegs)
+      State.FreeRegs -= sz;
+    else
+      State.FreeRegs = 0;
+  }
+}
+
+ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
+  return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty)
+                     : getNaturalAlignIndirect(Ty, false);
+}
+
+ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
+  // Compute the byval alignment.
+  const unsigned MinABIStackAlignInBytes = 4;
+  unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
+  return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
+                                 TypeAlign > MinABIStackAlignInBytes);
+}
+
+ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
+                                            uint8_t FreeRegs) const {
+  // Handle the generic C++ ABI.
+  const RecordType *RT = Ty->getAs<RecordType>();
+  if (RT) {
+    CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
+    if (RAA == CGCXXABI::RAA_Indirect)
+      return getIndirectByRef(Ty, FreeRegs > 0);
+
+    if (RAA == CGCXXABI::RAA_DirectInMemory)
+      return getIndirectByValue(Ty);
+  }
+
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+    Ty = EnumTy->getDecl()->getIntegerType();
+
+  auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
+
+  if (isAggregateTypeForABI(Ty)) {
+    // Structures with flexible arrays are always indirect.
+    if (RT && RT->getDecl()->hasFlexibleArrayMember())
+      return getIndirectByValue(Ty);
+
+    // Ignore empty structs/unions.
+    if (isEmptyRecord(getContext(), Ty, true))
+      return ABIArgInfo::getIgnore();
+
+    llvm::LLVMContext &LLVMContext = getVMContext();
+
+    llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
+    SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
+    llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
+
+    return FreeRegs >= SizeInRegs
+               ? ABIArgInfo::getDirectInReg(Result)
+               : ABIArgInfo::getDirect(Result, 0, nullptr, false);
+  }
+
+  if (const auto *EIT = Ty->getAs<BitIntType>())
+    if (EIT->getNumBits() > 64)
+      return getIndirectByValue(Ty);
+
+  return isPromotableIntegerTypeForABI(Ty)
+             ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty)
+                                       : ABIArgInfo::getExtend(Ty))
+             : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg()
+                                       : ABIArgInfo::getDirect());
+}
+
+ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
+  if (RetTy->isAnyComplexType())
+    return ABIArgInfo::getDirectInReg();
+
+  // Arguments of size > 4 registers are indirect.
+  auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
+  if (RetSize > 4)
+    return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
+
+  return DefaultABIInfo::classifyReturnType(RetTy);
+}
+
+void ARCABIInfo::computeInfo(CGFunctionInfo &FI) const {
+  CCState State;
+  // ARC uses 8 registers to pass arguments.
+  State.FreeRegs = 8;
+
+  if (!getCXXABI().classifyReturnType(FI))
+    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  updateState(FI.getReturnInfo(), FI.getReturnType(), State);
+  for (auto &I : FI.arguments()) {
+    I.info = classifyArgumentType(I.type, State.FreeRegs);
+    updateState(I.info, I.type, State);
+  }
+}
+
+Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                              QualType Ty) const {
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+                          getContext().getTypeInfoInChars(Ty),
+                          CharUnits::fromQuantity(4), true);
+}
+
+ARCTargetCodeGenInfo::ARCTargetCodeGenInfo(CodeGenTypes &CGT)
+    : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {}
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -13,10 +13,15 @@
 
 #include "TargetInfo.h"
 #include "ABIInfo.h"
+#include "ABIInfoImpl.h"
 #include "CGBlocks.h"
 #include "CGCXXABI.h"
 #include "CGValue.h"
 #include "CodeGenFunction.h"
+#include "Targets/ARC.h"
+#include "Targets/CSKY.h"
+#include "Targets/M68k.h"
+#include "Targets/SPIR.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/Builtins.h"
@@ -77,7 +82,7 @@
   }
 }
 
-static bool isAggregateTypeForABI(QualType T) {
+bool CodeGen::isAggregateTypeForABI(QualType T) {
   return !CodeGenFunction::hasScalarEvaluationKind(T) ||
          T->isMemberFunctionPointerType();
 }
@@ -100,7 +105,7 @@
   return Address::invalid();
 }
 
-static llvm::Type *getVAListElementType(CodeGenFunction &CGF) {
+llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) {
   return CGF.ConvertTypeForMem(
       CGF.getContext().getBuiltinVaListType()->getPointeeType());
 }
@@ -164,8 +169,8 @@
   return (VectorSize.getQuantity() > 8 && VectorSize.getQuantity() <= 16);
 }
 
-static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
-                                              CGCXXABI &CXXABI) {
+CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT,
+                                                CGCXXABI &CXXABI) {
   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
   if (!RD) {
     if (!RT->getDecl()->canPassInRegisters())
@@ -175,8 +180,7 @@
   return CXXABI.getRecordArgABI(RD);
 }
 
-static CGCXXABI::RecordArgABI getRecordArgABI(QualType T,
-                                              CGCXXABI &CXXABI) {
+CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) {
   const RecordType *RT = T->getAs<RecordType>();
   if (!RT)
     return CGCXXABI::RAA_Default;
@@ -199,7 +203,7 @@
 
 /// Pass transparent unions as if they were the type of the first element. Sema
 /// should ensure that all elements of the union have the same "machine type".
-static QualType useFirstFieldIfTransparentUnion(QualType Ty) {
+QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) {
   if (const RecordType *UT = Ty->getAsUnionType()) {
     const RecordDecl *UD = UT->getDecl();
     if (UD->hasAttr<TransparentUnionAttr>()) {
@@ -382,12 +386,12 @@
 /// \param ForceRightAdjust - Default is false. On big-endian platform and
 ///   if the argument is smaller than a slot, set this flag will force
 ///   right-adjust the argument in its slot irrespective of the type.
-static Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
-                                QualType ValueTy, bool IsIndirect,
-                                TypeInfoChars ValueInfo,
-                                CharUnits SlotSizeAndAlign,
-                                bool AllowHigherAlign,
-                                bool ForceRightAdjust = false) {
+Address CodeGen::emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                                  QualType ValueTy, bool IsIndirect,
+                                  TypeInfoChars ValueInfo,
+                                  CharUnits SlotSizeAndAlign,
+                                  bool AllowHigherAlign,
+                                  bool ForceRightAdjust) {
   // The size and alignment of the value that was passed directly.
   CharUnits DirectSize, DirectAlign;
   if (IsIndirect) {
@@ -548,12 +552,10 @@
   return Ctx.getOrInsertSyncScopeID(""); /* default sync scope */
 }
 
-static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
-
 /// isEmptyField - Return true iff a the field is "empty", that is it
 /// is an unnamed bit-field or an (array of) empty record(s).
-static bool isEmptyField(ASTContext &Context, const FieldDecl *FD,
-                         bool AllowArrays) {
+bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,
+                           bool AllowArrays) {
   if (FD->isUnnamedBitfield())
     return true;
 
@@ -596,7 +598,7 @@
 /// isEmptyRecord - Return true iff a structure contains only empty
 /// fields. Note that a structure with a flexible array member is not
 /// considered empty.
-static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
+bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
   const RecordType *RT = T->getAs<RecordType>();
   if (!RT)
     return false;
@@ -624,7 +626,7 @@
 ///
 /// \return The field declaration for the single non-empty field, if
 /// it exists.
-static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
+const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
   const RecordType *RT = T->getAs<RecordType>();
   if (!RT)
     return nullptr;
@@ -691,9 +693,8 @@
   return Found;
 }
 
-namespace {
-Address EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
-                       const ABIArgInfo &AI) {
+static Address EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr,
+                              QualType Ty, const ABIArgInfo &AI) {
   // This default implementation defers to the llvm backend's va_arg
   // instruction. It can handle only passing arguments directly
   // (typically only handled in the backend for primitive types), or
@@ -741,35 +742,25 @@
   }
 }
 
-/// DefaultABIInfo - The default implementation for ABI specific
-/// details. This implementation provides information which results in
-/// self-consistent and sensible LLVM IR generation, but does not
-/// conform to any particular ABI.
-class DefaultABIInfo : public ABIInfo {
-public:
-  DefaultABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
-
-  ABIArgInfo classifyReturnType(QualType RetTy) const;
-  ABIArgInfo classifyArgumentType(QualType RetTy) const;
-
-  void computeInfo(CGFunctionInfo &FI) const override {
-    if (!getCXXABI().classifyReturnType(FI))
-      FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
-    for (auto &I : FI.arguments())
-      I.info = classifyArgumentType(I.type);
-  }
+void DefaultABIInfo::computeInfo(CGFunctionInfo &FI) const {
+  if (!getCXXABI().classifyReturnType(FI))
+    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  for (auto &I : FI.arguments())
+    I.info = classifyArgumentType(I.type);
+}
 
-  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
-                    QualType Ty) const override {
-    return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty));
-  }
-};
+Address DefaultABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                                  QualType Ty) const {
+  return EmitVAArgInstr(CGF, VAListAddr, Ty, classifyArgumentType(Ty));
+}
 
+namespace {
 class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
 public:
   DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
       : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
 };
+} // namespace
 
 ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
   Ty = useFirstFieldIfTransparentUnion(Ty);
@@ -821,6 +812,8 @@
                                                : ABIArgInfo::getDirect());
 }
 
+namespace {
+
 //===----------------------------------------------------------------------===//
 // WebAssembly ABI Implementation
 //
@@ -8422,43 +8415,6 @@
   return false;
 }
 
-//===----------------------------------------------------------------------===//
-// M68k ABI Implementation
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class M68kTargetCodeGenInfo : public TargetCodeGenInfo {
-public:
-  M68kTargetCodeGenInfo(CodeGenTypes &CGT)
-      : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
-  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
-                           CodeGen::CodeGenModule &M) const override;
-};
-
-} // namespace
-
-void M68kTargetCodeGenInfo::setTargetAttributes(
-    const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
-  if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
-    if (const auto *attr = FD->getAttr<M68kInterruptAttr>()) {
-      // Handle 'interrupt' attribute:
-      llvm::Function *F = cast<llvm::Function>(GV);
-
-      // Step 1: Set ISR calling convention.
-      F->setCallingConv(llvm::CallingConv::M68k_INTR);
-
-      // Step 2: Add attributes goodness.
-      F->addFnAttr(llvm::Attribute::NoInline);
-
-      // Step 3: Emit ISR vector alias.
-      unsigned Num = attr->getNumber() / 2;
-      llvm::GlobalAlias::create(llvm::Function::ExternalLinkage,
-                                "__isr_" + Twine(Num), F);
-    }
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // AVR ABI Implementation. Documented at
 // https://gcc.gnu.org/wiki/avr-gcc#Calling_Convention
@@ -10088,142 +10044,6 @@
   return false;
 }
 
-// ARC ABI implementation.
-namespace {
-
-class ARCABIInfo : public DefaultABIInfo {
-public:
-  using DefaultABIInfo::DefaultABIInfo;
-
-private:
-  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
-                    QualType Ty) const override;
-
-  void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
-    if (!State.FreeRegs)
-      return;
-    if (Info.isIndirect() && Info.getInReg())
-      State.FreeRegs--;
-    else if (Info.isDirect() && Info.getInReg()) {
-      unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
-      if (sz < State.FreeRegs)
-        State.FreeRegs -= sz;
-      else
-        State.FreeRegs = 0;
-    }
-  }
-
-  void computeInfo(CGFunctionInfo &FI) const override {
-    CCState State(FI);
-    // ARC uses 8 registers to pass arguments.
-    State.FreeRegs = 8;
-
-    if (!getCXXABI().classifyReturnType(FI))
-      FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
-    updateState(FI.getReturnInfo(), FI.getReturnType(), State);
-    for (auto &I : FI.arguments()) {
-      I.info = classifyArgumentType(I.type, State.FreeRegs);
-      updateState(I.info, I.type, State);
-    }
-  }
-
-  ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
-  ABIArgInfo getIndirectByValue(QualType Ty) const;
-  ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
-  ABIArgInfo classifyReturnType(QualType RetTy) const;
-};
-
-class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
-public:
-  ARCTargetCodeGenInfo(CodeGenTypes &CGT)
-      : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {}
-};
-
-
-ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
-  return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) :
-                       getNaturalAlignIndirect(Ty, false);
-}
-
-ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
-  // Compute the byval alignment.
-  const unsigned MinABIStackAlignInBytes = 4;
-  unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
-  return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
-                                 TypeAlign > MinABIStackAlignInBytes);
-}
-
-Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
-                              QualType Ty) const {
-  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
-                          getContext().getTypeInfoInChars(Ty),
-                          CharUnits::fromQuantity(4), true);
-}
-
-ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
-                                            uint8_t FreeRegs) const {
-  // Handle the generic C++ ABI.
-  const RecordType *RT = Ty->getAs<RecordType>();
-  if (RT) {
-    CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
-    if (RAA == CGCXXABI::RAA_Indirect)
-      return getIndirectByRef(Ty, FreeRegs > 0);
-
-    if (RAA == CGCXXABI::RAA_DirectInMemory)
-      return getIndirectByValue(Ty);
-  }
-
-  // Treat an enum type as its underlying type.
-  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
-    Ty = EnumTy->getDecl()->getIntegerType();
-
-  auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
-
-  if (isAggregateTypeForABI(Ty)) {
-    // Structures with flexible arrays are always indirect.
-    if (RT && RT->getDecl()->hasFlexibleArrayMember())
-      return getIndirectByValue(Ty);
-
-    // Ignore empty structs/unions.
-    if (isEmptyRecord(getContext(), Ty, true))
-      return ABIArgInfo::getIgnore();
-
-    llvm::LLVMContext &LLVMContext = getVMContext();
-
-    llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
-    SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
-    llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
-
-    return FreeRegs >= SizeInRegs ?
-        ABIArgInfo::getDirectInReg(Result) :
-        ABIArgInfo::getDirect(Result, 0, nullptr, false);
-  }
-
-  if (const auto *EIT = Ty->getAs<BitIntType>())
-    if (EIT->getNumBits() > 64)
-      return getIndirectByValue(Ty);
-
-  return isPromotableIntegerTypeForABI(Ty)
-             ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty)
-                                       : ABIArgInfo::getExtend(Ty))
-             : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg()
-                                       : ABIArgInfo::getDirect());
-}
-
-ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
-  if (RetTy->isAnyComplexType())
-    return ABIArgInfo::getDirectInReg();
-
-  // Arguments of size > 4 registers are indirect.
-  auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
-  if (RetSize > 4)
-    return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
-
-  return DefaultABIInfo::classifyReturnType(RetTy);
-}
-
-} // End anonymous namespace.
-
 //===----------------------------------------------------------------------===//
 // XCore ABI Implementation
 //===----------------------------------------------------------------------===//
@@ -10536,126 +10356,6 @@
   }
 }
 
-//===----------------------------------------------------------------------===//
-// Base ABI and target codegen info implementation common between SPIR and
-// SPIR-V.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class CommonSPIRABIInfo : public DefaultABIInfo {
-public:
-  CommonSPIRABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) { setCCs(); }
-
-private:
-  void setCCs();
-};
-
-class SPIRVABIInfo : public CommonSPIRABIInfo {
-public:
-  SPIRVABIInfo(CodeGenTypes &CGT) : CommonSPIRABIInfo(CGT) {}
-  void computeInfo(CGFunctionInfo &FI) const override;
-
-private:
-  ABIArgInfo classifyKernelArgumentType(QualType Ty) const;
-};
-} // end anonymous namespace
-namespace {
-class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {
-public:
-  CommonSPIRTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
-      : TargetCodeGenInfo(std::make_unique<CommonSPIRABIInfo>(CGT)) {}
-  CommonSPIRTargetCodeGenInfo(std::unique_ptr<ABIInfo> ABIInfo)
-      : TargetCodeGenInfo(std::move(ABIInfo)) {}
-
-  LangAS getASTAllocaAddressSpace() const override {
-    return getLangASFromTargetAS(
-        getABIInfo().getDataLayout().getAllocaAddrSpace());
-  }
-
-  unsigned getOpenCLKernelCallingConv() const override;
-  llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override;
-};
-class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo {
-public:
-  SPIRVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
-      : CommonSPIRTargetCodeGenInfo(std::make_unique<SPIRVABIInfo>(CGT)) {}
-  void setCUDAKernelCallingConvention(const FunctionType *&FT) const override;
-};
-} // End anonymous namespace.
-
-void CommonSPIRABIInfo::setCCs() {
-  assert(getRuntimeCC() == llvm::CallingConv::C);
-  RuntimeCC = llvm::CallingConv::SPIR_FUNC;
-}
-
-ABIArgInfo SPIRVABIInfo::classifyKernelArgumentType(QualType Ty) const {
-  if (getContext().getLangOpts().CUDAIsDevice) {
-    // Coerce pointer arguments with default address space to CrossWorkGroup
-    // pointers for HIPSPV/CUDASPV. When the language mode is HIP/CUDA, the
-    // SPIRTargetInfo maps cuda_device to SPIR-V's CrossWorkGroup address space.
-    llvm::Type *LTy = CGT.ConvertType(Ty);
-    auto DefaultAS = getContext().getTargetAddressSpace(LangAS::Default);
-    auto GlobalAS = getContext().getTargetAddressSpace(LangAS::cuda_device);
-    auto *PtrTy = llvm::dyn_cast<llvm::PointerType>(LTy);
-    if (PtrTy && PtrTy->getAddressSpace() == DefaultAS) {
-      LTy = llvm::PointerType::getWithSamePointeeType(PtrTy, GlobalAS);
-      return ABIArgInfo::getDirect(LTy, 0, nullptr, false);
-    }
-
-    // Force copying aggregate type in kernel arguments by value when
-    // compiling CUDA targeting SPIR-V. This is required for the object
-    // copied to be valid on the device.
-    // This behavior follows the CUDA spec
-    // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-function-argument-processing,
-    // and matches the NVPTX implementation.
-    if (isAggregateTypeForABI(Ty))
-      return getNaturalAlignIndirect(Ty, /* byval */ true);
-  }
-  return classifyArgumentType(Ty);
-}
-
-void SPIRVABIInfo::computeInfo(CGFunctionInfo &FI) const {
-  // The logic is same as in DefaultABIInfo with an exception on the kernel
-  // arguments handling.
-  llvm::CallingConv::ID CC = FI.getCallingConvention();
-
-  if (!getCXXABI().classifyReturnType(FI))
-    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
-
-  for (auto &I : FI.arguments()) {
-    if (CC == llvm::CallingConv::SPIR_KERNEL) {
-      I.info = classifyKernelArgumentType(I.type);
-    } else {
-      I.info = classifyArgumentType(I.type);
-    }
-  }
-}
-
-namespace clang {
-namespace CodeGen {
-void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) {
-  if (CGM.getTarget().getTriple().isSPIRV())
-    SPIRVABIInfo(CGM.getTypes()).computeInfo(FI);
-  else
-    CommonSPIRABIInfo(CGM.getTypes()).computeInfo(FI);
-}
-}
-}
-
-unsigned CommonSPIRTargetCodeGenInfo::getOpenCLKernelCallingConv() const {
-  return llvm::CallingConv::SPIR_KERNEL;
-}
-
-void SPIRVTargetCodeGenInfo::setCUDAKernelCallingConvention(
-    const FunctionType *&FT) const {
-  // Convert HIP kernels to SPIR-V kernels.
-  if (getABIInfo().getContext().getLangOpts().HIP) {
-    FT = getABIInfo().getContext().adjustFunctionType(
-        FT, FT->getExtInfo().withCallingConv(CC_OpenCLKernel));
-    return;
-  }
-}
-
 static bool appendType(SmallStringEnc &Enc, QualType QType,
                        const CodeGen::CodeGenModule &CGM,
                        TypeStringCache &TSC);
@@ -10988,80 +10688,6 @@
   return false;
 }
 
-/// Construct a SPIR-V target extension type for the given OpenCL image type.
-static llvm::Type *getSPIRVImageType(llvm::LLVMContext &Ctx, StringRef BaseType,
-                                     StringRef OpenCLName,
-                                     unsigned AccessQualifier) {
-  // These parameters compare to the operands of OpTypeImage (see
-  // https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage
-  // for more details). The first 6 integer parameters all default to 0, and
-  // will be changed to 1 only for the image type(s) that set the parameter to
-  // one. The 7th integer parameter is the access qualifier, which is tacked on
-  // at the end.
-  SmallVector<unsigned, 7> IntParams = {0, 0, 0, 0, 0, 0};
-
-  // Choose the dimension of the image--this corresponds to the Dim enum in
-  // SPIR-V (first integer parameter of OpTypeImage).
-  if (OpenCLName.startswith("image2d"))
-    IntParams[0] = 1; // 1D
-  else if (OpenCLName.startswith("image3d"))
-    IntParams[0] = 2; // 2D
-  else if (OpenCLName == "image1d_buffer")
-    IntParams[0] = 5; // Buffer
-  else
-    assert(OpenCLName.startswith("image1d") && "Unknown image type");
-
-  // Set the other integer parameters of OpTypeImage if necessary. Note that the
-  // OpenCL image types don't provide any information for the Sampled or
-  // Image Format parameters.
-  if (OpenCLName.contains("_depth"))
-    IntParams[1] = 1;
-  if (OpenCLName.contains("_array"))
-    IntParams[2] = 1;
-  if (OpenCLName.contains("_msaa"))
-    IntParams[3] = 1;
-
-  // Access qualifier
-  IntParams.push_back(AccessQualifier);
-
-  return llvm::TargetExtType::get(Ctx, BaseType, {llvm::Type::getVoidTy(Ctx)},
-                                  IntParams);
-}
-
-llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM,
-                                                       const Type *Ty) const {
-  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
-  if (auto *PipeTy = dyn_cast<PipeType>(Ty))
-    return llvm::TargetExtType::get(Ctx, "spirv.Pipe", {},
-                                    {!PipeTy->isReadOnly()});
-  if (auto *BuiltinTy = dyn_cast<BuiltinType>(Ty)) {
-    enum AccessQualifier : unsigned { AQ_ro = 0, AQ_wo = 1, AQ_rw = 2 };
-    switch (BuiltinTy->getKind()) {
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
-    case BuiltinType::Id:                                                      \
-      return getSPIRVImageType(Ctx, "spirv.Image", #ImgType, AQ_##Suffix);
-#include "clang/Basic/OpenCLImageTypes.def"
-    case BuiltinType::OCLSampler:
-      return llvm::TargetExtType::get(Ctx, "spirv.Sampler");
-    case BuiltinType::OCLEvent:
-      return llvm::TargetExtType::get(Ctx, "spirv.Event");
-    case BuiltinType::OCLClkEvent:
-      return llvm::TargetExtType::get(Ctx, "spirv.DeviceEvent");
-    case BuiltinType::OCLQueue:
-      return llvm::TargetExtType::get(Ctx, "spirv.Queue");
-    case BuiltinType::OCLReserveID:
-      return llvm::TargetExtType::get(Ctx, "spirv.ReserveId");
-#define INTEL_SUBGROUP_AVC_TYPE(Name, Id)                                      \
-    case BuiltinType::OCLIntelSubgroupAVC##Id:                                 \
-      return llvm::TargetExtType::get(Ctx, "spirv.Avc" #Id "INTEL");
-#include "clang/Basic/OpenCLExtensionTypes.def"
-    default:
-      return nullptr;
-    }
-  }
-
-  return nullptr;
-}
 //===----------------------------------------------------------------------===//
 // RISC-V ABI Implementation
 //===----------------------------------------------------------------------===//
@@ -11592,165 +11218,6 @@
 };
 } // end anonymous namespace
 
-//===----------------------------------------------------------------------===//
-// CSKY ABI Implementation
-//===----------------------------------------------------------------------===//
-namespace {
-class CSKYABIInfo : public DefaultABIInfo {
-  static const int NumArgGPRs = 4;
-  static const int NumArgFPRs = 4;
-
-  static const unsigned XLen = 32;
-  unsigned FLen;
-
-public:
-  CSKYABIInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)
-      : DefaultABIInfo(CGT), FLen(FLen) {}
-
-  void computeInfo(CGFunctionInfo &FI) const override;
-  ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
-                                  int &ArgFPRsLeft,
-                                  bool isReturnType = false) const;
-  ABIArgInfo classifyReturnType(QualType RetTy) const;
-
-  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
-                    QualType Ty) const override;
-};
-
-} // end anonymous namespace
-
-void CSKYABIInfo::computeInfo(CGFunctionInfo &FI) const {
-  QualType RetTy = FI.getReturnType();
-  if (!getCXXABI().classifyReturnType(FI))
-    FI.getReturnInfo() = classifyReturnType(RetTy);
-
-  bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;
-
-  // We must track the number of GPRs used in order to conform to the CSKY
-  // ABI, as integer scalars passed in registers should have signext/zeroext
-  // when promoted.
-  int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
-  int ArgFPRsLeft = FLen ? NumArgFPRs : 0;
-
-  for (auto &ArgInfo : FI.arguments()) {
-    ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft, ArgFPRsLeft);
-  }
-}
-
-Address CSKYABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
-                               QualType Ty) const {
-  CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8);
-
-  // Empty records are ignored for parameter passing purposes.
-  if (isEmptyRecord(getContext(), Ty, true)) {
-    Address Addr = Address(CGF.Builder.CreateLoad(VAListAddr),
-                           getVAListElementType(CGF), SlotSize);
-    Addr = CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty));
-    return Addr;
-  }
-
-  auto TInfo = getContext().getTypeInfoInChars(Ty);
-
-  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, false, TInfo, SlotSize,
-                          /*AllowHigherAlign=*/true);
-}
-
-ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
-                                             int &ArgFPRsLeft,
-                                             bool isReturnType) const {
-  assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");
-  Ty = useFirstFieldIfTransparentUnion(Ty);
-
-  // Structures with either a non-trivial destructor or a non-trivial
-  // copy constructor are always passed indirectly.
-  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
-    if (ArgGPRsLeft)
-      ArgGPRsLeft -= 1;
-    return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
-                                           CGCXXABI::RAA_DirectInMemory);
-  }
-
-  // Ignore empty structs/unions.
-  if (isEmptyRecord(getContext(), Ty, true))
-    return ABIArgInfo::getIgnore();
-
-  if (!Ty->getAsUnionType())
-    if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
-      return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
-
-  uint64_t Size = getContext().getTypeSize(Ty);
-  // Pass floating point values via FPRs if possible.
-  if (Ty->isFloatingType() && !Ty->isComplexType() && FLen >= Size &&
-      ArgFPRsLeft) {
-    ArgFPRsLeft--;
-    return ABIArgInfo::getDirect();
-  }
-
-  // Complex types for the hard float ABI must be passed direct rather than
-  // using CoerceAndExpand.
-  if (Ty->isComplexType() && FLen && !isReturnType) {
-    QualType EltTy = Ty->castAs<ComplexType>()->getElementType();
-    if (getContext().getTypeSize(EltTy) <= FLen) {
-      ArgFPRsLeft -= 2;
-      return ABIArgInfo::getDirect();
-    }
-  }
-
-  if (!isAggregateTypeForABI(Ty)) {
-    // Treat an enum type as its underlying type.
-    if (const EnumType *EnumTy = Ty->getAs<EnumType>())
-      Ty = EnumTy->getDecl()->getIntegerType();
-
-    // All integral types are promoted to XLen width, unless passed on the
-    // stack.
-    if (Size < XLen && Ty->isIntegralOrEnumerationType())
-      return ABIArgInfo::getExtend(Ty);
-
-    if (const auto *EIT = Ty->getAs<BitIntType>()) {
-      if (EIT->getNumBits() < XLen)
-        return ABIArgInfo::getExtend(Ty);
-    }
-
-    return ABIArgInfo::getDirect();
-  }
-
-  // For argument type, the first 4*XLen parts of aggregate will be passed
-  // in registers, and the rest will be passed in stack.
-  // So we can coerce to integers directly and let backend handle it correctly.
-  // For return type, aggregate which <= 2*XLen will be returned in registers.
-  // Otherwise, aggregate will be returned indirectly.
-  if (!isReturnType || (isReturnType && Size <= 2 * XLen)) {
-    if (Size <= XLen) {
-      return ABIArgInfo::getDirect(
-          llvm::IntegerType::get(getVMContext(), XLen));
-    } else {
-      return ABIArgInfo::getDirect(llvm::ArrayType::get(
-          llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen));
-    }
-  }
-  return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
-}
-
-ABIArgInfo CSKYABIInfo::classifyReturnType(QualType RetTy) const {
-  if (RetTy->isVoidType())
-    return ABIArgInfo::getIgnore();
-
-  int ArgGPRsLeft = 2;
-  int ArgFPRsLeft = FLen ? 1 : 0;
-
-  // The rules for return and argument types are the same, so defer to
-  // classifyArgumentType.
-  return classifyArgumentType(RetTy, ArgGPRsLeft, ArgFPRsLeft, true);
-}
-
-namespace {
-class CSKYTargetCodeGenInfo : public TargetCodeGenInfo {
-public:
-  CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)
-      : TargetCodeGenInfo(std::make_unique<CSKYABIInfo>(CGT, FLen)) {}
-};
-} // end anonymous namespace
-
 //===----------------------------------------------------------------------===//
 // BPF ABI Implementation
 //===----------------------------------------------------------------------===//
Index: clang/lib/CodeGen/CMakeLists.txt
===================================================================
--- clang/lib/CodeGen/CMakeLists.txt
+++ clang/lib/CodeGen/CMakeLists.txt
@@ -31,6 +31,10 @@
   )
 
 add_clang_library(clangCodeGen
+  Targets/ARC.cpp
+  Targets/CSKY.cpp
+  Targets/M68k.cpp
+  Targets/SPIR.cpp
   BackendUtil.cpp
   CGAtomic.cpp
   CGBlocks.cpp
Index: clang/lib/CodeGen/ABIInfoImpl.h
===================================================================
--- /dev/null
+++ clang/lib/CodeGen/ABIInfoImpl.h
@@ -0,0 +1,56 @@
+//===- DefaultABIInfo.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFOIMPL_H
+#define LLVM_CLANG_LIB_CODEGEN_ABIINFOIMPL_H
+
+#include "ABIInfo.h"
+#include "CGCXXABI.h"
+
+namespace clang::CodeGen {
+
+/// DefaultABIInfo - The default implementation for ABI specific details.
+/// This implementation provides information which results in self-consistent
+/// and sensible LLVM IR generation, but does not conform to any particular ABI.
+class DefaultABIInfo : public ABIInfo {
+public:
+  DefaultABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override;
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                    QualType Ty) const override;
+};
+
+bool isAggregateTypeForABI(QualType T);
+
+llvm::Type *getVAListElementType(CodeGenFunction &CGF);
+
+CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI);
+
+CGCXXABI::RecordArgABI getRecordArgABI(QualType T, CGCXXABI &CXXABI);
+
+QualType useFirstFieldIfTransparentUnion(QualType Ty);
+
+Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr,
+                         QualType ValueTy, bool IsIndirect,
+                         TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign,
+                         bool AllowHigherAlign, bool ForceRightAdjust = false);
+
+bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays);
+
+bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
+
+const Type *isSingleElementStruct(QualType T, ASTContext &Context);
+
+} // namespace clang::CodeGen
+
+#endif // LLVM_CLANG_LIB_CODEGEN_ABIINFOIMPL_H
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to