clang 24.0.0git
Xtensa.cpp
Go to the documentation of this file.
1//===- Xtensa.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// Xtensa ABI Implementation
16//===----------------------------------------------------------------------===//
17
18namespace {
19class XtensaABIInfo : public DefaultABIInfo {
20private:
21 static const int MaxNumArgGPRs = 6;
22 static const int MaxNumRetGPRs = 4;
23
24public:
25 XtensaABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
26
27 void computeInfo(CGFunctionInfo &FI) const override;
28
29 ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft) const;
30
31 ABIArgInfo classifyReturnType(QualType RetTy) const;
32
33 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
34 AggValueSlot Slot) const override;
35
36 ABIArgInfo extendType(QualType Ty) const;
37};
38} // end anonymous namespace
39
40void XtensaABIInfo::computeInfo(CGFunctionInfo &FI) const {
41 QualType RetTy = FI.getReturnType();
42 if (!getCXXABI().classifyReturnType(FI))
44
45 int ArgGPRsLeft = MaxNumArgGPRs;
46 for (auto &[Type, Info] : FI.arguments()) {
47 Info = classifyArgumentType(Type, ArgGPRsLeft);
48 }
49}
50
51ABIArgInfo XtensaABIInfo::classifyArgumentType(QualType Ty,
52 int &ArgGPRsLeft) const {
53 assert(ArgGPRsLeft <= MaxNumArgGPRs && "Arg GPR tracking underflow");
55 // Structures with either a non-trivial destructor or a non-trivial
56 // copy constructor are always passed indirectly.
57 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
58 if (ArgGPRsLeft)
59 ArgGPRsLeft -= 1;
60 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
61 /*ByVal=*/RAA ==
63 }
64
65 // Ignore empty structs/unions.
66 if (isEmptyRecord(getContext(), Ty, true))
67 return ABIArgInfo::getIgnore();
68
69 uint64_t Size = getContext().getTypeSize(Ty);
70 uint64_t NeededAlign = getContext().getTypeAlign(Ty);
71 int NeededArgGPRs = (Size + 31) / 32;
72
73 if (NeededAlign == (2 * 32))
74 NeededArgGPRs += (ArgGPRsLeft % 2);
75
76 // Push onto the stack objects that do not fit into 6 registers,
77 // also push onto the stack an object with alignment greater than 16 bytes,
78 // and an object with alignment of 16 bytes if it is not the first argument.
79 if ((NeededArgGPRs > ArgGPRsLeft) || (NeededAlign > (4 * 32)) ||
80 ((ArgGPRsLeft < 6) && (NeededAlign == (4 * 32)))) {
81 ArgGPRsLeft = 0;
82 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
83 /*ByVal=*/true);
84 }
85 ArgGPRsLeft -= NeededArgGPRs;
86
87 if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) {
88 // Treat an enum type as its underlying type.
89 if (const auto *ED = Ty->getAsEnumDecl())
90 Ty = ED->getIntegerType();
91 // All integral types less then 32-bit width are promoted to 32-bit width.
92 if (Size < 32 && Ty->isIntegralOrEnumerationType()) {
93 return extendType(Ty);
94 }
95 // Assume that type has 32, 64 or 128 bits
96 return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size));
97 }
98
99 // Aggregates which are <= 6*32 will be passed in registers if possible,
100 // so coerce to integers.
101 if (Size <= (MaxNumArgGPRs * 32)) {
102 if (Size <= 32) {
103 return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), 32));
104 } else if (NeededAlign == (2 * 32)) {
105 return ABIArgInfo::getDirect(llvm::ArrayType::get(
106 llvm::IntegerType::get(getVMContext(), 64), NeededArgGPRs / 2));
107 } else if (NeededAlign == (4 * 32)) {
108 return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), 128));
109 }
110
111 return ABIArgInfo::getDirect(llvm::ArrayType::get(
112 llvm::IntegerType::get(getVMContext(), 32), NeededArgGPRs));
113 }
114
115 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
116 /*ByVal=*/true);
117}
118
119ABIArgInfo XtensaABIInfo::classifyReturnType(QualType RetTy) const {
120 if (RetTy->isVoidType())
121 return ABIArgInfo::getIgnore();
122
123 int ArgGPRsLeft = MaxNumRetGPRs;
124 auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
125
126 // The rules for return value and for argument with type size more
127 // then 4 bytes are the same, so defer to classifyArgumentType.
128 if (RetSize > 1)
129 return classifyArgumentType(RetTy, ArgGPRsLeft);
130
132}
133
134RValue XtensaABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
135 QualType Ty, AggValueSlot Slot) const {
136 // The va_list structure memory layout:
137 // struct __va_list_tag {
138 // int32_t *va_stk;
139 // int32_t *va_reg;
140 // int32_t va_ndx;
141 // };
142 CGBuilderTy &Builder = CGF.Builder;
143
144 Address OverflowAreaPtr = Builder.CreateStructGEP(VAListAddr, 0, "__va_stk");
145 Address OverflowArea = Address(Builder.CreateLoad(OverflowAreaPtr, ""),
147 Address RegSaveAreaPtr = Builder.CreateStructGEP(VAListAddr, 1, "__va_reg");
148 Address RegSaveArea = Address(Builder.CreateLoad(RegSaveAreaPtr, ""),
150 Address ARAreaPtr = Builder.CreateStructGEP(VAListAddr, 2, "__va_ndx");
151 llvm::Value *ARIndex = Builder.CreateLoad(ARAreaPtr, "");
152
153 ARIndex = Builder.CreateLShr(ARIndex, Builder.getInt32(2));
154
155 unsigned Align = getContext().getTypeAlign(Ty) / 32;
156 unsigned Size = (getContext().getTypeSize(Ty) + 31) / 32;
157
158 if (Align > 1) {
159 ARIndex = Builder.CreateAdd(ARIndex, Builder.getInt32(Align - 1));
160 ARIndex =
161 Builder.CreateAnd(ARIndex, Builder.getInt32((uint32_t)~(Align - 1)));
162 }
163
164 llvm::Value *ARIndexNext = Builder.CreateAdd(ARIndex, Builder.getInt32(Size));
165 Builder.CreateStore(Builder.CreateShl(ARIndexNext, Builder.getInt32(2)),
166 ARAreaPtr);
167
168 const unsigned OverflowLimit = 6;
169 llvm::Value *CC = Builder.CreateICmpULE(
170 ARIndexNext, Builder.getInt32(OverflowLimit), "cond");
171
172 llvm::BasicBlock *UsingRegSaveArea =
173 CGF.createBasicBlock("using_regsavearea");
174 llvm::BasicBlock *UsingOverflow = CGF.createBasicBlock("using_overflow");
175 llvm::BasicBlock *Cont = CGF.createBasicBlock("cont");
176
177 Builder.CreateCondBr(CC, UsingRegSaveArea, UsingOverflow);
178
179 llvm::Type *DirectTy = CGF.ConvertType(Ty);
180
181 // Case 1: consume registers.
182 Address RegAddr = Address::invalid();
183 {
184 CGF.EmitBlock(UsingRegSaveArea);
185
186 CharUnits RegSize = CharUnits::fromQuantity(4);
187 RegSaveArea =
188 Address(Builder.CreateInBoundsGEP(
189 CGF.Int32Ty, RegSaveArea.emitRawPointer(CGF), ARIndex),
190 CGF.Int32Ty,
191 RegSaveArea.getAlignment().alignmentOfArrayElement(RegSize));
192 RegAddr = RegSaveArea.withElementType(DirectTy);
193 CGF.EmitBranch(Cont);
194 }
195
196 // Case 2: consume space in the overflow area.
197 Address MemAddr = Address::invalid();
198 {
199 CGF.EmitBlock(UsingOverflow);
200 llvm::Value *CC1 = Builder.CreateICmpULE(
201 ARIndex, Builder.getInt32(OverflowLimit), "cond_overflow");
202
203 llvm::Value *ARIndexOff = Builder.CreateSelect(
204 CC1, Builder.CreateSub(Builder.getInt32(8), ARIndex),
205 Builder.getInt32(0));
206
207 llvm::Value *ARIndexCorr = Builder.CreateAdd(ARIndex, ARIndexOff);
208 llvm::Value *ARIndexNextCorr = Builder.CreateAdd(ARIndexNext, ARIndexOff);
209 Builder.CreateStore(Builder.CreateShl(ARIndexNextCorr, Builder.getInt32(2)),
210 ARAreaPtr);
211
212 CharUnits RegSize = CharUnits::fromQuantity(4);
213 OverflowArea =
214 Address(Builder.CreateInBoundsGEP(
215 CGF.Int32Ty, OverflowArea.emitRawPointer(CGF), ARIndexCorr),
216 CGF.Int32Ty,
217 OverflowArea.getAlignment().alignmentOfArrayElement(RegSize));
218 MemAddr = OverflowArea.withElementType(DirectTy);
219 CGF.EmitBranch(Cont);
220 }
221
222 CGF.EmitBlock(Cont);
223
224 // Merge the cases with a phi.
226 emitMergePHI(CGF, RegAddr, UsingRegSaveArea, MemAddr, UsingOverflow, "");
227
228 return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Result, Ty), Slot);
229}
230
231ABIArgInfo XtensaABIInfo::extendType(QualType Ty) const {
232 return ABIArgInfo::getExtend(Ty);
233}
234
235namespace {
236class XtensaTargetCodeGenInfo : public TargetCodeGenInfo {
237public:
238 XtensaTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
239 : TargetCodeGenInfo(std::make_unique<XtensaABIInfo>(CGT)) {}
240};
241} // namespace
242
243std::unique_ptr<TargetCodeGenInfo>
245 return std::make_unique<XtensaTargetCodeGenInfo>(CGM.getTypes());
246}
Result
Implement __builtin_bit_cast and related operations.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition CharUnits.h:184
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:58
static ABIArgInfo getIgnore()
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true, unsigned Align=0)
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T=nullptr, llvm::Type *Padding=nullptr)
static Address invalid()
Definition Address.h:176
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:253
CharUnits getAlignment() const
Definition Address.h:194
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Definition Address.h:276
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()
llvm::Type * ConvertType(QualType T)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
RValue EmitLoadOfAnyValue(LValue V, AggValueSlot Slot=AggValueSlot::ignored(), SourceLocation Loc={})
Like EmitLoadOfLValue but also handles complex and aggregate types.
Definition CGExpr.cpp:2531
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
Definition CGStmt.cpp:675
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
Definition CGStmt.cpp:655
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
ABIArgInfo classifyReturnType(QualType RetTy) const
bool isVoidType() const
Definition TypeBase.h:9068
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
Definition Type.h:53
bool isVectorType() const
Definition TypeBase.h:8822
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)
std::unique_ptr< TargetCodeGenInfo > createXtensaTargetCodeGenInfo(CodeGenModule &CGM)
Definition Xtensa.cpp:244
Address emitMergePHI(CodeGenFunction &CGF, Address Addr1, llvm::BasicBlock *Block1, Address Addr2, llvm::BasicBlock *Block2, const llvm::Twine &Name="")
bool isAggregateTypeForABI(QualType T)
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.
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
Top level wrappers for InstallAPI frontend operations.
unsigned long uint64_t