clang  19.0.0git
CSKY.cpp
Go to the documentation of this file.
1 //===- CSKY.cpp -----------------------------------------------------------===//
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 #include "ABIInfoImpl.h"
10 #include "TargetInfo.h"
11 
12 using namespace clang;
13 using namespace clang::CodeGen;
14 
15 //===----------------------------------------------------------------------===//
16 // CSKY ABI Implementation
17 //===----------------------------------------------------------------------===//
18 namespace {
19 class CSKYABIInfo : public DefaultABIInfo {
20  static const int NumArgGPRs = 4;
21  static const int NumArgFPRs = 4;
22 
23  static const unsigned XLen = 32;
24  unsigned FLen;
25 
26 public:
27  CSKYABIInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)
28  : DefaultABIInfo(CGT), FLen(FLen) {}
29 
30  void computeInfo(CGFunctionInfo &FI) const override;
31  ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft,
32  int &ArgFPRsLeft,
33  bool isReturnType = false) const;
35 
36  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
37  QualType Ty) const override;
38 };
39 
40 } // end anonymous namespace
41 
42 void CSKYABIInfo::computeInfo(CGFunctionInfo &FI) const {
43  QualType RetTy = FI.getReturnType();
44  if (!getCXXABI().classifyReturnType(FI))
45  FI.getReturnInfo() = classifyReturnType(RetTy);
46 
47  bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;
48 
49  // We must track the number of GPRs used in order to conform to the CSKY
50  // ABI, as integer scalars passed in registers should have signext/zeroext
51  // when promoted.
52  int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
53  int ArgFPRsLeft = FLen ? NumArgFPRs : 0;
54 
55  for (auto &ArgInfo : FI.arguments()) {
56  ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft, ArgFPRsLeft);
57  }
58 }
59 
60 Address CSKYABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
61  QualType Ty) const {
62  CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8);
63 
64  // Empty records are ignored for parameter passing purposes.
65  if (isEmptyRecord(getContext(), Ty, true)) {
66  return Address(CGF.Builder.CreateLoad(VAListAddr),
67  CGF.ConvertTypeForMem(Ty), SlotSize);
68  }
69 
70  auto TInfo = getContext().getTypeInfoInChars(Ty);
71 
72  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, false, TInfo, SlotSize,
73  /*AllowHigherAlign=*/true);
74 }
75 
77  int &ArgFPRsLeft,
78  bool isReturnType) const {
79  assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");
81 
82  // Structures with either a non-trivial destructor or a non-trivial
83  // copy constructor are always passed indirectly.
84  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
85  if (ArgGPRsLeft)
86  ArgGPRsLeft -= 1;
87  return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA ==
89  }
90 
91  // Ignore empty structs/unions.
92  if (isEmptyRecord(getContext(), Ty, true))
93  return ABIArgInfo::getIgnore();
94 
95  if (!Ty->getAsUnionType())
96  if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))
97  return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));
98 
99  uint64_t Size = getContext().getTypeSize(Ty);
100  // Pass floating point values via FPRs if possible.
101  if (Ty->isFloatingType() && !Ty->isComplexType() && FLen >= Size &&
102  ArgFPRsLeft) {
103  ArgFPRsLeft--;
104  return ABIArgInfo::getDirect();
105  }
106 
107  // Complex types for the hard float ABI must be passed direct rather than
108  // using CoerceAndExpand.
109  if (Ty->isComplexType() && FLen && !isReturnType) {
110  QualType EltTy = Ty->castAs<ComplexType>()->getElementType();
111  if (getContext().getTypeSize(EltTy) <= FLen) {
112  ArgFPRsLeft -= 2;
113  return ABIArgInfo::getDirect();
114  }
115  }
116 
117  if (!isAggregateTypeForABI(Ty)) {
118  // Treat an enum type as its underlying type.
119  if (const EnumType *EnumTy = Ty->getAs<EnumType>())
120  Ty = EnumTy->getDecl()->getIntegerType();
121 
122  // All integral types are promoted to XLen width, unless passed on the
123  // stack.
124  if (Size < XLen && Ty->isIntegralOrEnumerationType())
125  return ABIArgInfo::getExtend(Ty);
126 
127  if (const auto *EIT = Ty->getAs<BitIntType>()) {
128  if (EIT->getNumBits() < XLen)
129  return ABIArgInfo::getExtend(Ty);
130  }
131 
132  return ABIArgInfo::getDirect();
133  }
134 
135  // For argument type, the first 4*XLen parts of aggregate will be passed
136  // in registers, and the rest will be passed in stack.
137  // So we can coerce to integers directly and let backend handle it correctly.
138  // For return type, aggregate which <= 2*XLen will be returned in registers.
139  // Otherwise, aggregate will be returned indirectly.
140  if (!isReturnType || (isReturnType && Size <= 2 * XLen)) {
141  if (Size <= XLen) {
142  return ABIArgInfo::getDirect(
143  llvm::IntegerType::get(getVMContext(), XLen));
144  } else {
145  return ABIArgInfo::getDirect(llvm::ArrayType::get(
146  llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen));
147  }
148  }
149  return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
150 }
151 
153  if (RetTy->isVoidType())
154  return ABIArgInfo::getIgnore();
155 
156  int ArgGPRsLeft = 2;
157  int ArgFPRsLeft = FLen ? 1 : 0;
158 
159  // The rules for return and argument types are the same, so defer to
160  // classifyArgumentType.
161  return classifyArgumentType(RetTy, ArgGPRsLeft, ArgFPRsLeft, true);
162 }
163 
164 namespace {
165 class CSKYTargetCodeGenInfo : public TargetCodeGenInfo {
166 public:
167  CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)
168  : TargetCodeGenInfo(std::make_unique<CSKYABIInfo>(CGT, FLen)) {}
169 };
170 } // end anonymous namespace
171 
172 std::unique_ptr<TargetCodeGenInfo>
174  return std::make_unique<CSKYTargetCodeGenInfo>(CGM.getTypes(), FLen);
175 }
A fixed int type of a specified bitwidth.
Definition: Type.h:7254
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo getIgnore()
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr)
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition: Address.h:111
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Definition: CGBuilder.h:108
RecordArgABI
Specify how one should pass an argument of a record type.
Definition: CGCXXABI.h:150
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
Definition: CGCXXABI.h:158
CGFunctionInfo - Class to encapsulate the information about a function definition.
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Type * ConvertTypeForMem(QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
Definition: CodeGenTypes.h:54
DefaultABIInfo - The default implementation for ABI specific details.
Definition: ABIInfoImpl.h:21
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition: TargetInfo.h:46
Complex values, per C99 6.2.5p11.
Definition: Type.h:3098
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:5587
A (possibly-)qualified type.
Definition: Type.h:940
The base class of the type hierarchy.
Definition: Type.h:1813
bool isVoidType() const
Definition: Type.h:7939
const RecordType * getAsUnionType() const
NOTE: getAs*ArrayType are methods on ASTContext.
Definition: Type.cpp:740
bool isComplexType() const
isComplexType() does not include complex integers (a GCC extension).
Definition: Type.cpp:677
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8227
bool isFloatingType() const
Definition: Type.cpp:2248
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8160
ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to return a particular type.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI)
bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info)
Address emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
bool isAggregateTypeForABI(QualType T)
const Type * isSingleElementStruct(QualType T, ASTContext &Context)
isSingleElementStruct - Determine if a structure is a "single element struct", i.e.
QualType useFirstFieldIfTransparentUnion(QualType Ty)
Pass transparent unions as if they were the type of the first element.
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
std::unique_ptr< TargetCodeGenInfo > createCSKYTargetCodeGenInfo(CodeGenModule &CGM, unsigned FLen)
Definition: CSKY.cpp:173
The JSON file list parser is used to communicate input to InstallAPI.
unsigned long uint64_t
Definition: Format.h:5433