xref: /llvm-project/clang/lib/CodeGen/Targets/Hexagon.cpp (revision 6d973b4548e281d0b8e75e85833804bb45b6a0e8)
1992cb984SSergei Barannikov //===- Hexagon.cpp --------------------------------------------------------===//
2992cb984SSergei Barannikov //
3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6992cb984SSergei Barannikov //
7992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8992cb984SSergei Barannikov 
9992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10992cb984SSergei Barannikov #include "TargetInfo.h"
11992cb984SSergei Barannikov 
12992cb984SSergei Barannikov using namespace clang;
13992cb984SSergei Barannikov using namespace clang::CodeGen;
14992cb984SSergei Barannikov 
15992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
16992cb984SSergei Barannikov // Hexagon ABI Implementation
17992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
18992cb984SSergei Barannikov 
19992cb984SSergei Barannikov namespace {
20992cb984SSergei Barannikov 
21992cb984SSergei Barannikov class HexagonABIInfo : public DefaultABIInfo {
22992cb984SSergei Barannikov public:
HexagonABIInfo(CodeGenTypes & CGT)23992cb984SSergei Barannikov   HexagonABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
24992cb984SSergei Barannikov 
25992cb984SSergei Barannikov private:
26992cb984SSergei Barannikov   ABIArgInfo classifyReturnType(QualType RetTy) const;
27992cb984SSergei Barannikov   ABIArgInfo classifyArgumentType(QualType RetTy) const;
28992cb984SSergei Barannikov   ABIArgInfo classifyArgumentType(QualType RetTy, unsigned *RegsLeft) const;
29992cb984SSergei Barannikov 
30992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override;
31992cb984SSergei Barannikov 
32*6d973b45SMariya Podchishchaeva   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
33*6d973b45SMariya Podchishchaeva                    AggValueSlot Slot) const override;
34992cb984SSergei Barannikov   Address EmitVAArgFromMemory(CodeGenFunction &CFG, Address VAListAddr,
35992cb984SSergei Barannikov                               QualType Ty) const;
36992cb984SSergei Barannikov   Address EmitVAArgForHexagon(CodeGenFunction &CFG, Address VAListAddr,
37992cb984SSergei Barannikov                               QualType Ty) const;
38992cb984SSergei Barannikov   Address EmitVAArgForHexagonLinux(CodeGenFunction &CFG, Address VAListAddr,
39992cb984SSergei Barannikov                                    QualType Ty) const;
40992cb984SSergei Barannikov };
41992cb984SSergei Barannikov 
42992cb984SSergei Barannikov class HexagonTargetCodeGenInfo : public TargetCodeGenInfo {
43992cb984SSergei Barannikov public:
HexagonTargetCodeGenInfo(CodeGenTypes & CGT)44992cb984SSergei Barannikov   HexagonTargetCodeGenInfo(CodeGenTypes &CGT)
45992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<HexagonABIInfo>(CGT)) {}
46992cb984SSergei Barannikov 
getDwarfEHStackPointer(CodeGen::CodeGenModule & M) const47992cb984SSergei Barannikov   int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
48992cb984SSergei Barannikov     return 29;
49992cb984SSergei Barannikov   }
50992cb984SSergei Barannikov 
setTargetAttributes(const Decl * D,llvm::GlobalValue * GV,CodeGen::CodeGenModule & GCM) const51992cb984SSergei Barannikov   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
52992cb984SSergei Barannikov                            CodeGen::CodeGenModule &GCM) const override {
53992cb984SSergei Barannikov     if (GV->isDeclaration())
54992cb984SSergei Barannikov       return;
55992cb984SSergei Barannikov     const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
56992cb984SSergei Barannikov     if (!FD)
57992cb984SSergei Barannikov       return;
58992cb984SSergei Barannikov   }
59992cb984SSergei Barannikov };
60992cb984SSergei Barannikov 
61992cb984SSergei Barannikov } // namespace
62992cb984SSergei Barannikov 
computeInfo(CGFunctionInfo & FI) const63992cb984SSergei Barannikov void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const {
64992cb984SSergei Barannikov   unsigned RegsLeft = 6;
65992cb984SSergei Barannikov   if (!getCXXABI().classifyReturnType(FI))
66992cb984SSergei Barannikov     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
67992cb984SSergei Barannikov   for (auto &I : FI.arguments())
68992cb984SSergei Barannikov     I.info = classifyArgumentType(I.type, &RegsLeft);
69992cb984SSergei Barannikov }
70992cb984SSergei Barannikov 
HexagonAdjustRegsLeft(uint64_t Size,unsigned * RegsLeft)71992cb984SSergei Barannikov static bool HexagonAdjustRegsLeft(uint64_t Size, unsigned *RegsLeft) {
72992cb984SSergei Barannikov   assert(Size <= 64 && "Not expecting to pass arguments larger than 64 bits"
73992cb984SSergei Barannikov                        " through registers");
74992cb984SSergei Barannikov 
75992cb984SSergei Barannikov   if (*RegsLeft == 0)
76992cb984SSergei Barannikov     return false;
77992cb984SSergei Barannikov 
78992cb984SSergei Barannikov   if (Size <= 32) {
79992cb984SSergei Barannikov     (*RegsLeft)--;
80992cb984SSergei Barannikov     return true;
81992cb984SSergei Barannikov   }
82992cb984SSergei Barannikov 
83992cb984SSergei Barannikov   if (2 <= (*RegsLeft & (~1U))) {
84992cb984SSergei Barannikov     *RegsLeft = (*RegsLeft & (~1U)) - 2;
85992cb984SSergei Barannikov     return true;
86992cb984SSergei Barannikov   }
87992cb984SSergei Barannikov 
88992cb984SSergei Barannikov   // Next available register was r5 but candidate was greater than 32-bits so it
89992cb984SSergei Barannikov   // has to go on the stack. However we still consume r5
90992cb984SSergei Barannikov   if (*RegsLeft == 1)
91992cb984SSergei Barannikov     *RegsLeft = 0;
92992cb984SSergei Barannikov 
93992cb984SSergei Barannikov   return false;
94992cb984SSergei Barannikov }
95992cb984SSergei Barannikov 
classifyArgumentType(QualType Ty,unsigned * RegsLeft) const96992cb984SSergei Barannikov ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty,
97992cb984SSergei Barannikov                                                 unsigned *RegsLeft) const {
98992cb984SSergei Barannikov   if (!isAggregateTypeForABI(Ty)) {
99992cb984SSergei Barannikov     // Treat an enum type as its underlying type.
100992cb984SSergei Barannikov     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
101992cb984SSergei Barannikov       Ty = EnumTy->getDecl()->getIntegerType();
102992cb984SSergei Barannikov 
103992cb984SSergei Barannikov     uint64_t Size = getContext().getTypeSize(Ty);
104992cb984SSergei Barannikov     if (Size <= 64)
105992cb984SSergei Barannikov       HexagonAdjustRegsLeft(Size, RegsLeft);
106992cb984SSergei Barannikov 
107992cb984SSergei Barannikov     if (Size > 64 && Ty->isBitIntType())
108992cb984SSergei Barannikov       return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
109992cb984SSergei Barannikov 
110992cb984SSergei Barannikov     return isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
111992cb984SSergei Barannikov                                              : ABIArgInfo::getDirect();
112992cb984SSergei Barannikov   }
113992cb984SSergei Barannikov 
114992cb984SSergei Barannikov   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
115992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
116992cb984SSergei Barannikov 
117992cb984SSergei Barannikov   // Ignore empty records.
118992cb984SSergei Barannikov   if (isEmptyRecord(getContext(), Ty, true))
119992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
120992cb984SSergei Barannikov 
121992cb984SSergei Barannikov   uint64_t Size = getContext().getTypeSize(Ty);
122992cb984SSergei Barannikov   unsigned Align = getContext().getTypeAlign(Ty);
123992cb984SSergei Barannikov 
124992cb984SSergei Barannikov   if (Size > 64)
125992cb984SSergei Barannikov     return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
126992cb984SSergei Barannikov 
127992cb984SSergei Barannikov   if (HexagonAdjustRegsLeft(Size, RegsLeft))
128992cb984SSergei Barannikov     Align = Size <= 32 ? 32 : 64;
129992cb984SSergei Barannikov   if (Size <= Align) {
130992cb984SSergei Barannikov     // Pass in the smallest viable integer type.
131992cb984SSergei Barannikov     Size = llvm::bit_ceil(Size);
132992cb984SSergei Barannikov     return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
133992cb984SSergei Barannikov   }
134992cb984SSergei Barannikov   return DefaultABIInfo::classifyArgumentType(Ty);
135992cb984SSergei Barannikov }
136992cb984SSergei Barannikov 
classifyReturnType(QualType RetTy) const137992cb984SSergei Barannikov ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
138992cb984SSergei Barannikov   if (RetTy->isVoidType())
139992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
140992cb984SSergei Barannikov 
141992cb984SSergei Barannikov   const TargetInfo &T = CGT.getTarget();
142992cb984SSergei Barannikov   uint64_t Size = getContext().getTypeSize(RetTy);
143992cb984SSergei Barannikov 
144992cb984SSergei Barannikov   if (RetTy->getAs<VectorType>()) {
145992cb984SSergei Barannikov     // HVX vectors are returned in vector registers or register pairs.
146992cb984SSergei Barannikov     if (T.hasFeature("hvx")) {
147992cb984SSergei Barannikov       assert(T.hasFeature("hvx-length64b") || T.hasFeature("hvx-length128b"));
148992cb984SSergei Barannikov       uint64_t VecSize = T.hasFeature("hvx-length64b") ? 64*8 : 128*8;
149992cb984SSergei Barannikov       if (Size == VecSize || Size == 2*VecSize)
150992cb984SSergei Barannikov         return ABIArgInfo::getDirectInReg();
151992cb984SSergei Barannikov     }
152992cb984SSergei Barannikov     // Large vector types should be returned via memory.
153992cb984SSergei Barannikov     if (Size > 64)
154992cb984SSergei Barannikov       return getNaturalAlignIndirect(RetTy);
155992cb984SSergei Barannikov   }
156992cb984SSergei Barannikov 
157992cb984SSergei Barannikov   if (!isAggregateTypeForABI(RetTy)) {
158992cb984SSergei Barannikov     // Treat an enum type as its underlying type.
159992cb984SSergei Barannikov     if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
160992cb984SSergei Barannikov       RetTy = EnumTy->getDecl()->getIntegerType();
161992cb984SSergei Barannikov 
162992cb984SSergei Barannikov     if (Size > 64 && RetTy->isBitIntType())
163992cb984SSergei Barannikov       return getNaturalAlignIndirect(RetTy, /*ByVal=*/false);
164992cb984SSergei Barannikov 
165992cb984SSergei Barannikov     return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
166992cb984SSergei Barannikov                                                 : ABIArgInfo::getDirect();
167992cb984SSergei Barannikov   }
168992cb984SSergei Barannikov 
169992cb984SSergei Barannikov   if (isEmptyRecord(getContext(), RetTy, true))
170992cb984SSergei Barannikov     return ABIArgInfo::getIgnore();
171992cb984SSergei Barannikov 
172992cb984SSergei Barannikov   // Aggregates <= 8 bytes are returned in registers, other aggregates
173992cb984SSergei Barannikov   // are returned indirectly.
174992cb984SSergei Barannikov   if (Size <= 64) {
175992cb984SSergei Barannikov     // Return in the smallest viable integer type.
176992cb984SSergei Barannikov     Size = llvm::bit_ceil(Size);
177992cb984SSergei Barannikov     return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
178992cb984SSergei Barannikov   }
179992cb984SSergei Barannikov   return getNaturalAlignIndirect(RetTy, /*ByVal=*/true);
180992cb984SSergei Barannikov }
181992cb984SSergei Barannikov 
EmitVAArgFromMemory(CodeGenFunction & CGF,Address VAListAddr,QualType Ty) const182992cb984SSergei Barannikov Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF,
183992cb984SSergei Barannikov                                             Address VAListAddr,
184992cb984SSergei Barannikov                                             QualType Ty) const {
185992cb984SSergei Barannikov   // Load the overflow area pointer.
186992cb984SSergei Barannikov   Address __overflow_area_pointer_p =
187992cb984SSergei Barannikov       CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p");
188992cb984SSergei Barannikov   llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad(
189992cb984SSergei Barannikov       __overflow_area_pointer_p, "__overflow_area_pointer");
190992cb984SSergei Barannikov 
191992cb984SSergei Barannikov   uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
192992cb984SSergei Barannikov   if (Align > 4) {
193992cb984SSergei Barannikov     // Alignment should be a power of 2.
194992cb984SSergei Barannikov     assert((Align & (Align - 1)) == 0 && "Alignment is not power of 2!");
195992cb984SSergei Barannikov 
196992cb984SSergei Barannikov     // overflow_arg_area = (overflow_arg_area + align - 1) & -align;
197992cb984SSergei Barannikov     llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int64Ty, Align - 1);
198992cb984SSergei Barannikov 
199992cb984SSergei Barannikov     // Add offset to the current pointer to access the argument.
200992cb984SSergei Barannikov     __overflow_area_pointer =
201992cb984SSergei Barannikov         CGF.Builder.CreateGEP(CGF.Int8Ty, __overflow_area_pointer, Offset);
202992cb984SSergei Barannikov     llvm::Value *AsInt =
203992cb984SSergei Barannikov         CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty);
204992cb984SSergei Barannikov 
205992cb984SSergei Barannikov     // Create a mask which should be "AND"ed
206992cb984SSergei Barannikov     // with (overflow_arg_area + align - 1)
207992cb984SSergei Barannikov     llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -(int)Align);
208992cb984SSergei Barannikov     __overflow_area_pointer = CGF.Builder.CreateIntToPtr(
209992cb984SSergei Barannikov         CGF.Builder.CreateAnd(AsInt, Mask), __overflow_area_pointer->getType(),
210992cb984SSergei Barannikov         "__overflow_area_pointer.align");
211992cb984SSergei Barannikov   }
212992cb984SSergei Barannikov 
213992cb984SSergei Barannikov   // Get the type of the argument from memory and bitcast
214992cb984SSergei Barannikov   // overflow area pointer to the argument type.
215992cb984SSergei Barannikov   llvm::Type *PTy = CGF.ConvertTypeForMem(Ty);
216474ec694SYoungsuk Kim   Address AddrTyped =
217474ec694SYoungsuk Kim       Address(__overflow_area_pointer, PTy, CharUnits::fromQuantity(Align));
218992cb984SSergei Barannikov 
219992cb984SSergei Barannikov   // Round up to the minimum stack alignment for varargs which is 4 bytes.
220992cb984SSergei Barannikov   uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
221992cb984SSergei Barannikov 
222992cb984SSergei Barannikov   __overflow_area_pointer = CGF.Builder.CreateGEP(
223992cb984SSergei Barannikov       CGF.Int8Ty, __overflow_area_pointer,
224992cb984SSergei Barannikov       llvm::ConstantInt::get(CGF.Int32Ty, Offset),
225992cb984SSergei Barannikov       "__overflow_area_pointer.next");
226992cb984SSergei Barannikov   CGF.Builder.CreateStore(__overflow_area_pointer, __overflow_area_pointer_p);
227992cb984SSergei Barannikov 
228992cb984SSergei Barannikov   return AddrTyped;
229992cb984SSergei Barannikov }
230992cb984SSergei Barannikov 
EmitVAArgForHexagon(CodeGenFunction & CGF,Address VAListAddr,QualType Ty) const231992cb984SSergei Barannikov Address HexagonABIInfo::EmitVAArgForHexagon(CodeGenFunction &CGF,
232992cb984SSergei Barannikov                                             Address VAListAddr,
233992cb984SSergei Barannikov                                             QualType Ty) const {
234992cb984SSergei Barannikov   // FIXME: Need to handle alignment
235992cb984SSergei Barannikov   llvm::Type *BP = CGF.Int8PtrTy;
236992cb984SSergei Barannikov   CGBuilderTy &Builder = CGF.Builder;
23744e63ffeSYoungsuk Kim   Address VAListAddrAsBPP = VAListAddr.withElementType(BP);
238992cb984SSergei Barannikov   llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
239992cb984SSergei Barannikov   // Handle address alignment for type alignment > 32 bits
240992cb984SSergei Barannikov   uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
241992cb984SSergei Barannikov   if (TyAlign > 4) {
242992cb984SSergei Barannikov     assert((TyAlign & (TyAlign - 1)) == 0 && "Alignment is not power of 2!");
243992cb984SSergei Barannikov     llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty);
244992cb984SSergei Barannikov     AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1));
245992cb984SSergei Barannikov     AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1)));
246992cb984SSergei Barannikov     Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
247992cb984SSergei Barannikov   }
248474ec694SYoungsuk Kim   Address AddrTyped =
249474ec694SYoungsuk Kim       Address(Addr, CGF.ConvertType(Ty), CharUnits::fromQuantity(TyAlign));
250992cb984SSergei Barannikov 
251992cb984SSergei Barannikov   uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
252992cb984SSergei Barannikov   llvm::Value *NextAddr = Builder.CreateGEP(
253992cb984SSergei Barannikov       CGF.Int8Ty, Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next");
254992cb984SSergei Barannikov   Builder.CreateStore(NextAddr, VAListAddrAsBPP);
255992cb984SSergei Barannikov 
256992cb984SSergei Barannikov   return AddrTyped;
257992cb984SSergei Barannikov }
258992cb984SSergei Barannikov 
EmitVAArgForHexagonLinux(CodeGenFunction & CGF,Address VAListAddr,QualType Ty) const259992cb984SSergei Barannikov Address HexagonABIInfo::EmitVAArgForHexagonLinux(CodeGenFunction &CGF,
260992cb984SSergei Barannikov                                                  Address VAListAddr,
261992cb984SSergei Barannikov                                                  QualType Ty) const {
262992cb984SSergei Barannikov   int ArgSize = CGF.getContext().getTypeSize(Ty) / 8;
263992cb984SSergei Barannikov 
264992cb984SSergei Barannikov   if (ArgSize > 8)
265992cb984SSergei Barannikov     return EmitVAArgFromMemory(CGF, VAListAddr, Ty);
266992cb984SSergei Barannikov 
267992cb984SSergei Barannikov   // Here we have check if the argument is in register area or
268992cb984SSergei Barannikov   // in overflow area.
269992cb984SSergei Barannikov   // If the saved register area pointer + argsize rounded up to alignment >
270992cb984SSergei Barannikov   // saved register area end pointer, argument is in overflow area.
271992cb984SSergei Barannikov   unsigned RegsLeft = 6;
272992cb984SSergei Barannikov   Ty = CGF.getContext().getCanonicalType(Ty);
273992cb984SSergei Barannikov   (void)classifyArgumentType(Ty, &RegsLeft);
274992cb984SSergei Barannikov 
275992cb984SSergei Barannikov   llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg");
276992cb984SSergei Barannikov   llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
277992cb984SSergei Barannikov   llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack");
278992cb984SSergei Barannikov   llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
279992cb984SSergei Barannikov 
280992cb984SSergei Barannikov   // Get rounded size of the argument.GCC does not allow vararg of
281992cb984SSergei Barannikov   // size < 4 bytes. We follow the same logic here.
282992cb984SSergei Barannikov   ArgSize = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8;
283992cb984SSergei Barannikov   int ArgAlign = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8;
284992cb984SSergei Barannikov 
285992cb984SSergei Barannikov   // Argument may be in saved register area
286992cb984SSergei Barannikov   CGF.EmitBlock(MaybeRegBlock);
287992cb984SSergei Barannikov 
288992cb984SSergei Barannikov   // Load the current saved register area pointer.
289992cb984SSergei Barannikov   Address __current_saved_reg_area_pointer_p = CGF.Builder.CreateStructGEP(
290992cb984SSergei Barannikov       VAListAddr, 0, "__current_saved_reg_area_pointer_p");
291992cb984SSergei Barannikov   llvm::Value *__current_saved_reg_area_pointer = CGF.Builder.CreateLoad(
292992cb984SSergei Barannikov       __current_saved_reg_area_pointer_p, "__current_saved_reg_area_pointer");
293992cb984SSergei Barannikov 
294992cb984SSergei Barannikov   // Load the saved register area end pointer.
295992cb984SSergei Barannikov   Address __saved_reg_area_end_pointer_p = CGF.Builder.CreateStructGEP(
296992cb984SSergei Barannikov       VAListAddr, 1, "__saved_reg_area_end_pointer_p");
297992cb984SSergei Barannikov   llvm::Value *__saved_reg_area_end_pointer = CGF.Builder.CreateLoad(
298992cb984SSergei Barannikov       __saved_reg_area_end_pointer_p, "__saved_reg_area_end_pointer");
299992cb984SSergei Barannikov 
300992cb984SSergei Barannikov   // If the size of argument is > 4 bytes, check if the stack
301992cb984SSergei Barannikov   // location is aligned to 8 bytes
302992cb984SSergei Barannikov   if (ArgAlign > 4) {
303992cb984SSergei Barannikov 
304992cb984SSergei Barannikov     llvm::Value *__current_saved_reg_area_pointer_int =
305992cb984SSergei Barannikov         CGF.Builder.CreatePtrToInt(__current_saved_reg_area_pointer,
306992cb984SSergei Barannikov                                    CGF.Int32Ty);
307992cb984SSergei Barannikov 
308992cb984SSergei Barannikov     __current_saved_reg_area_pointer_int = CGF.Builder.CreateAdd(
309992cb984SSergei Barannikov         __current_saved_reg_area_pointer_int,
310992cb984SSergei Barannikov         llvm::ConstantInt::get(CGF.Int32Ty, (ArgAlign - 1)),
311992cb984SSergei Barannikov         "align_current_saved_reg_area_pointer");
312992cb984SSergei Barannikov 
313992cb984SSergei Barannikov     __current_saved_reg_area_pointer_int =
314992cb984SSergei Barannikov         CGF.Builder.CreateAnd(__current_saved_reg_area_pointer_int,
315992cb984SSergei Barannikov                               llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign),
316992cb984SSergei Barannikov                               "align_current_saved_reg_area_pointer");
317992cb984SSergei Barannikov 
318992cb984SSergei Barannikov     __current_saved_reg_area_pointer =
319992cb984SSergei Barannikov         CGF.Builder.CreateIntToPtr(__current_saved_reg_area_pointer_int,
320992cb984SSergei Barannikov                                    __current_saved_reg_area_pointer->getType(),
321992cb984SSergei Barannikov                                    "align_current_saved_reg_area_pointer");
322992cb984SSergei Barannikov   }
323992cb984SSergei Barannikov 
324992cb984SSergei Barannikov   llvm::Value *__new_saved_reg_area_pointer =
325992cb984SSergei Barannikov       CGF.Builder.CreateGEP(CGF.Int8Ty, __current_saved_reg_area_pointer,
326992cb984SSergei Barannikov                             llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
327992cb984SSergei Barannikov                             "__new_saved_reg_area_pointer");
328992cb984SSergei Barannikov 
329992cb984SSergei Barannikov   llvm::Value *UsingStack = nullptr;
330992cb984SSergei Barannikov   UsingStack = CGF.Builder.CreateICmpSGT(__new_saved_reg_area_pointer,
331992cb984SSergei Barannikov                                          __saved_reg_area_end_pointer);
332992cb984SSergei Barannikov 
333992cb984SSergei Barannikov   CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, InRegBlock);
334992cb984SSergei Barannikov 
335992cb984SSergei Barannikov   // Argument in saved register area
336992cb984SSergei Barannikov   // Implement the block where argument is in register saved area
337992cb984SSergei Barannikov   CGF.EmitBlock(InRegBlock);
338992cb984SSergei Barannikov 
339992cb984SSergei Barannikov   llvm::Type *PTy = CGF.ConvertType(Ty);
340992cb984SSergei Barannikov   llvm::Value *__saved_reg_area_p = CGF.Builder.CreateBitCast(
341992cb984SSergei Barannikov       __current_saved_reg_area_pointer, llvm::PointerType::getUnqual(PTy));
342992cb984SSergei Barannikov 
343992cb984SSergei Barannikov   CGF.Builder.CreateStore(__new_saved_reg_area_pointer,
344992cb984SSergei Barannikov                           __current_saved_reg_area_pointer_p);
345992cb984SSergei Barannikov 
346992cb984SSergei Barannikov   CGF.EmitBranch(ContBlock);
347992cb984SSergei Barannikov 
348992cb984SSergei Barannikov   // Argument in overflow area
349992cb984SSergei Barannikov   // Implement the block where the argument is in overflow area.
350992cb984SSergei Barannikov   CGF.EmitBlock(OnStackBlock);
351992cb984SSergei Barannikov 
352992cb984SSergei Barannikov   // Load the overflow area pointer
353992cb984SSergei Barannikov   Address __overflow_area_pointer_p =
354992cb984SSergei Barannikov       CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p");
355992cb984SSergei Barannikov   llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad(
356992cb984SSergei Barannikov       __overflow_area_pointer_p, "__overflow_area_pointer");
357992cb984SSergei Barannikov 
358992cb984SSergei Barannikov   // Align the overflow area pointer according to the alignment of the argument
359992cb984SSergei Barannikov   if (ArgAlign > 4) {
360992cb984SSergei Barannikov     llvm::Value *__overflow_area_pointer_int =
361992cb984SSergei Barannikov         CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty);
362992cb984SSergei Barannikov 
363992cb984SSergei Barannikov     __overflow_area_pointer_int =
364992cb984SSergei Barannikov         CGF.Builder.CreateAdd(__overflow_area_pointer_int,
365992cb984SSergei Barannikov                               llvm::ConstantInt::get(CGF.Int32Ty, ArgAlign - 1),
366992cb984SSergei Barannikov                               "align_overflow_area_pointer");
367992cb984SSergei Barannikov 
368992cb984SSergei Barannikov     __overflow_area_pointer_int =
369992cb984SSergei Barannikov         CGF.Builder.CreateAnd(__overflow_area_pointer_int,
370992cb984SSergei Barannikov                               llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign),
371992cb984SSergei Barannikov                               "align_overflow_area_pointer");
372992cb984SSergei Barannikov 
373992cb984SSergei Barannikov     __overflow_area_pointer = CGF.Builder.CreateIntToPtr(
374992cb984SSergei Barannikov         __overflow_area_pointer_int, __overflow_area_pointer->getType(),
375992cb984SSergei Barannikov         "align_overflow_area_pointer");
376992cb984SSergei Barannikov   }
377992cb984SSergei Barannikov 
378992cb984SSergei Barannikov   // Get the pointer for next argument in overflow area and store it
379992cb984SSergei Barannikov   // to overflow area pointer.
380992cb984SSergei Barannikov   llvm::Value *__new_overflow_area_pointer = CGF.Builder.CreateGEP(
381992cb984SSergei Barannikov       CGF.Int8Ty, __overflow_area_pointer,
382992cb984SSergei Barannikov       llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
383992cb984SSergei Barannikov       "__overflow_area_pointer.next");
384992cb984SSergei Barannikov 
385992cb984SSergei Barannikov   CGF.Builder.CreateStore(__new_overflow_area_pointer,
386992cb984SSergei Barannikov                           __overflow_area_pointer_p);
387992cb984SSergei Barannikov 
388992cb984SSergei Barannikov   CGF.Builder.CreateStore(__new_overflow_area_pointer,
389992cb984SSergei Barannikov                           __current_saved_reg_area_pointer_p);
390992cb984SSergei Barannikov 
391992cb984SSergei Barannikov   // Bitcast the overflow area pointer to the type of argument.
392992cb984SSergei Barannikov   llvm::Type *OverflowPTy = CGF.ConvertTypeForMem(Ty);
393992cb984SSergei Barannikov   llvm::Value *__overflow_area_p = CGF.Builder.CreateBitCast(
394992cb984SSergei Barannikov       __overflow_area_pointer, llvm::PointerType::getUnqual(OverflowPTy));
395992cb984SSergei Barannikov 
396992cb984SSergei Barannikov   CGF.EmitBranch(ContBlock);
397992cb984SSergei Barannikov 
398992cb984SSergei Barannikov   // Get the correct pointer to load the variable argument
399992cb984SSergei Barannikov   // Implement the ContBlock
400992cb984SSergei Barannikov   CGF.EmitBlock(ContBlock);
401992cb984SSergei Barannikov 
402992cb984SSergei Barannikov   llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty);
403992cb984SSergei Barannikov   llvm::Type *MemPTy = llvm::PointerType::getUnqual(MemTy);
404992cb984SSergei Barannikov   llvm::PHINode *ArgAddr = CGF.Builder.CreatePHI(MemPTy, 2, "vaarg.addr");
405992cb984SSergei Barannikov   ArgAddr->addIncoming(__saved_reg_area_p, InRegBlock);
406992cb984SSergei Barannikov   ArgAddr->addIncoming(__overflow_area_p, OnStackBlock);
407992cb984SSergei Barannikov 
408992cb984SSergei Barannikov   return Address(ArgAddr, MemTy, CharUnits::fromQuantity(ArgAlign));
409992cb984SSergei Barannikov }
410992cb984SSergei Barannikov 
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const411*6d973b45SMariya Podchishchaeva RValue HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
412*6d973b45SMariya Podchishchaeva                                  QualType Ty, AggValueSlot Slot) const {
413992cb984SSergei Barannikov 
414992cb984SSergei Barannikov   if (getTarget().getTriple().isMusl())
415*6d973b45SMariya Podchishchaeva     return CGF.EmitLoadOfAnyValue(
416*6d973b45SMariya Podchishchaeva         CGF.MakeAddrLValue(EmitVAArgForHexagonLinux(CGF, VAListAddr, Ty), Ty),
417*6d973b45SMariya Podchishchaeva         Slot);
418992cb984SSergei Barannikov 
419*6d973b45SMariya Podchishchaeva   return CGF.EmitLoadOfAnyValue(
420*6d973b45SMariya Podchishchaeva       CGF.MakeAddrLValue(EmitVAArgForHexagon(CGF, VAListAddr, Ty), Ty), Slot);
421992cb984SSergei Barannikov }
422992cb984SSergei Barannikov 
423992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
createHexagonTargetCodeGenInfo(CodeGenModule & CGM)424992cb984SSergei Barannikov CodeGen::createHexagonTargetCodeGenInfo(CodeGenModule &CGM) {
425992cb984SSergei Barannikov   return std::make_unique<HexagonTargetCodeGenInfo>(CGM.getTypes());
426992cb984SSergei Barannikov }
427