clang 22.0.0git
ARC.cpp
Go to the documentation of this file.
1//===- ARC.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
12using namespace clang;
13using namespace clang::CodeGen;
14
15// ARC ABI implementation.
16namespace {
17
18class ARCABIInfo : public DefaultABIInfo {
19 struct CCState {
20 unsigned FreeRegs;
21 };
22
23public:
25
26private:
27 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
28 AggValueSlot Slot) const override;
29
30 void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
31 if (!State.FreeRegs)
32 return;
33 if (Info.isIndirect() && Info.getInReg())
34 State.FreeRegs--;
35 else if (Info.isDirect() && Info.getInReg()) {
36 unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
37 if (sz < State.FreeRegs)
38 State.FreeRegs -= sz;
39 else
40 State.FreeRegs = 0;
41 }
42 }
43
44 void computeInfo(CGFunctionInfo &FI) const override {
45 CCState State;
46 // ARC uses 8 registers to pass arguments.
47 State.FreeRegs = 8;
48
49 if (!getCXXABI().classifyReturnType(FI))
51 updateState(FI.getReturnInfo(), FI.getReturnType(), State);
52 for (auto &I : FI.arguments()) {
53 I.info = classifyArgumentType(I.type, State.FreeRegs);
54 updateState(I.info, I.type, State);
55 }
56 }
57
58 ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
59 ABIArgInfo getIndirectByValue(QualType Ty) const;
60 ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
61 ABIArgInfo classifyReturnType(QualType RetTy) const;
62};
63
64class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
65public:
66 ARCTargetCodeGenInfo(CodeGenTypes &CGT)
67 : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {}
68};
69
70
71ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
72 return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty)
73 : getNaturalAlignIndirect(
74 Ty, getDataLayout().getAllocaAddrSpace(), false);
75}
76
77ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
78 // Compute the byval alignment.
79 const unsigned MinABIStackAlignInBytes = 4;
80 unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
83 /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
84 /*ByVal=*/true, TypeAlign > MinABIStackAlignInBytes);
85}
86
87RValue ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
88 QualType Ty, AggValueSlot Slot) const {
89 return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
90 getContext().getTypeInfoInChars(Ty),
91 CharUnits::fromQuantity(4), true, Slot);
92}
93
94ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
95 uint8_t FreeRegs) const {
96 // Handle the generic C++ ABI.
97 const RecordType *RT = Ty->getAsCanonical<RecordType>();
98 if (RT) {
99 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
100 if (RAA == CGCXXABI::RAA_Indirect)
101 return getIndirectByRef(Ty, FreeRegs > 0);
102
104 return getIndirectByValue(Ty);
105 }
106
107 // Treat an enum type as its underlying type.
108 if (const auto *ED = Ty->getAsEnumDecl())
109 Ty = ED->getIntegerType();
110
111 auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
112
113 if (isAggregateTypeForABI(Ty)) {
114 // Structures with flexible arrays are always indirect.
115 if (RT &&
116 RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())
117 return getIndirectByValue(Ty);
118
119 // Ignore empty structs/unions.
120 if (isEmptyRecord(getContext(), Ty, true))
121 return ABIArgInfo::getIgnore();
122
123 llvm::LLVMContext &LLVMContext = getVMContext();
124
125 llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
126 SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
127 llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
128
129 return FreeRegs >= SizeInRegs ?
131 ABIArgInfo::getDirect(Result, 0, nullptr, false);
132 }
133
134 if (const auto *EIT = Ty->getAs<BitIntType>())
135 if (EIT->getNumBits() > 64)
136 return getIndirectByValue(Ty);
137
138 return isPromotableIntegerTypeForABI(Ty)
139 ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty)
140 : ABIArgInfo::getExtend(Ty))
141 : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg()
142 : ABIArgInfo::getDirect());
143}
144
145ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
146 if (RetTy->isAnyComplexType())
148
149 // Arguments of size > 4 registers are indirect.
150 auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
151 if (RetSize > 4)
152 return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
153
155}
156
157} // End anonymous namespace.
158
159std::unique_ptr<TargetCodeGenInfo>
161 return std::make_unique<ARCTargetCodeGenInfo>(CGM.getTypes());
162}
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 getExtendInReg(QualType Ty, llvm::Type *T=nullptr)
static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
static ABIArgInfo getDirectInReg(llvm::Type *T=nullptr)
RecordArgABI
Specify how one should pass an argument of a record type.
Definition CGCXXABI.h:150
@ RAA_Indirect
Pass it as a pointer to temporary memory.
Definition CGCXXABI.h:161
@ RAA_DirectInMemory
Pass it on the stack using its defined layout.
Definition CGCXXABI.h:158
CanQualType getReturnType() const
MutableArrayRef< ArgInfo > arguments()
This class organizes the cross-function state that is used while generating LLVM code.
DefaultABIInfo - The default implementation for ABI specific details.
Definition ABIInfoImpl.h:21
DefaultABIInfo(CodeGen::CodeGenTypes &CGT)
Definition ABIInfoImpl.h:23
ABIArgInfo classifyReturnType(QualType RetTy) const
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition TargetInfo.h:47
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isAnyComplexType() const
Definition TypeBase.h:8657
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition TypeBase.h:2921
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9098
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)
RValue emitVoidPtrVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType ValueTy, bool IsIndirect, TypeInfoChars ValueInfo, CharUnits SlotSizeAndAlign, bool AllowHigherAlign, AggValueSlot Slot, bool ForceRightAdjust=false)
Emit va_arg for a platform using the common void* representation, where arguments are simply emitted ...
bool isAggregateTypeForABI(QualType T)
std::unique_ptr< TargetCodeGenInfo > createARCTargetCodeGenInfo(CodeGenModule &CGM)
Definition ARC.cpp:160
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, bool AsIfNoUniqueAddr=false)
isEmptyRecord - Return true iff a structure contains only empty fields.
The JSON file list parser is used to communicate input to InstallAPI.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
Definition TypeBase.h:905
#define false
Definition stdbool.h:26