xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/Hexagon.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric //===- Hexagon.cpp --------------------------------------------------------===//
2*06c3fb27SDimitry Andric //
3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06c3fb27SDimitry Andric //
7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
8*06c3fb27SDimitry Andric 
9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h"
10*06c3fb27SDimitry Andric #include "TargetInfo.h"
11*06c3fb27SDimitry Andric 
12*06c3fb27SDimitry Andric using namespace clang;
13*06c3fb27SDimitry Andric using namespace clang::CodeGen;
14*06c3fb27SDimitry Andric 
15*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
16*06c3fb27SDimitry Andric // Hexagon ABI Implementation
17*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
18*06c3fb27SDimitry Andric 
19*06c3fb27SDimitry Andric namespace {
20*06c3fb27SDimitry Andric 
21*06c3fb27SDimitry Andric class HexagonABIInfo : public DefaultABIInfo {
22*06c3fb27SDimitry Andric public:
23*06c3fb27SDimitry Andric   HexagonABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
24*06c3fb27SDimitry Andric 
25*06c3fb27SDimitry Andric private:
26*06c3fb27SDimitry Andric   ABIArgInfo classifyReturnType(QualType RetTy) const;
27*06c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy) const;
28*06c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy, unsigned *RegsLeft) const;
29*06c3fb27SDimitry Andric 
30*06c3fb27SDimitry Andric   void computeInfo(CGFunctionInfo &FI) const override;
31*06c3fb27SDimitry Andric 
32*06c3fb27SDimitry Andric   Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
33*06c3fb27SDimitry Andric                     QualType Ty) const override;
34*06c3fb27SDimitry Andric   Address EmitVAArgFromMemory(CodeGenFunction &CFG, Address VAListAddr,
35*06c3fb27SDimitry Andric                               QualType Ty) const;
36*06c3fb27SDimitry Andric   Address EmitVAArgForHexagon(CodeGenFunction &CFG, Address VAListAddr,
37*06c3fb27SDimitry Andric                               QualType Ty) const;
38*06c3fb27SDimitry Andric   Address EmitVAArgForHexagonLinux(CodeGenFunction &CFG, Address VAListAddr,
39*06c3fb27SDimitry Andric                                    QualType Ty) const;
40*06c3fb27SDimitry Andric };
41*06c3fb27SDimitry Andric 
42*06c3fb27SDimitry Andric class HexagonTargetCodeGenInfo : public TargetCodeGenInfo {
43*06c3fb27SDimitry Andric public:
44*06c3fb27SDimitry Andric   HexagonTargetCodeGenInfo(CodeGenTypes &CGT)
45*06c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<HexagonABIInfo>(CGT)) {}
46*06c3fb27SDimitry Andric 
47*06c3fb27SDimitry Andric   int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
48*06c3fb27SDimitry Andric     return 29;
49*06c3fb27SDimitry Andric   }
50*06c3fb27SDimitry Andric 
51*06c3fb27SDimitry Andric   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
52*06c3fb27SDimitry Andric                            CodeGen::CodeGenModule &GCM) const override {
53*06c3fb27SDimitry Andric     if (GV->isDeclaration())
54*06c3fb27SDimitry Andric       return;
55*06c3fb27SDimitry Andric     const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
56*06c3fb27SDimitry Andric     if (!FD)
57*06c3fb27SDimitry Andric       return;
58*06c3fb27SDimitry Andric   }
59*06c3fb27SDimitry Andric };
60*06c3fb27SDimitry Andric 
61*06c3fb27SDimitry Andric } // namespace
62*06c3fb27SDimitry Andric 
63*06c3fb27SDimitry Andric void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const {
64*06c3fb27SDimitry Andric   unsigned RegsLeft = 6;
65*06c3fb27SDimitry Andric   if (!getCXXABI().classifyReturnType(FI))
66*06c3fb27SDimitry Andric     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
67*06c3fb27SDimitry Andric   for (auto &I : FI.arguments())
68*06c3fb27SDimitry Andric     I.info = classifyArgumentType(I.type, &RegsLeft);
69*06c3fb27SDimitry Andric }
70*06c3fb27SDimitry Andric 
71*06c3fb27SDimitry Andric static bool HexagonAdjustRegsLeft(uint64_t Size, unsigned *RegsLeft) {
72*06c3fb27SDimitry Andric   assert(Size <= 64 && "Not expecting to pass arguments larger than 64 bits"
73*06c3fb27SDimitry Andric                        " through registers");
74*06c3fb27SDimitry Andric 
75*06c3fb27SDimitry Andric   if (*RegsLeft == 0)
76*06c3fb27SDimitry Andric     return false;
77*06c3fb27SDimitry Andric 
78*06c3fb27SDimitry Andric   if (Size <= 32) {
79*06c3fb27SDimitry Andric     (*RegsLeft)--;
80*06c3fb27SDimitry Andric     return true;
81*06c3fb27SDimitry Andric   }
82*06c3fb27SDimitry Andric 
83*06c3fb27SDimitry Andric   if (2 <= (*RegsLeft & (~1U))) {
84*06c3fb27SDimitry Andric     *RegsLeft = (*RegsLeft & (~1U)) - 2;
85*06c3fb27SDimitry Andric     return true;
86*06c3fb27SDimitry Andric   }
87*06c3fb27SDimitry Andric 
88*06c3fb27SDimitry Andric   // Next available register was r5 but candidate was greater than 32-bits so it
89*06c3fb27SDimitry Andric   // has to go on the stack. However we still consume r5
90*06c3fb27SDimitry Andric   if (*RegsLeft == 1)
91*06c3fb27SDimitry Andric     *RegsLeft = 0;
92*06c3fb27SDimitry Andric 
93*06c3fb27SDimitry Andric   return false;
94*06c3fb27SDimitry Andric }
95*06c3fb27SDimitry Andric 
96*06c3fb27SDimitry Andric ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty,
97*06c3fb27SDimitry Andric                                                 unsigned *RegsLeft) const {
98*06c3fb27SDimitry Andric   if (!isAggregateTypeForABI(Ty)) {
99*06c3fb27SDimitry Andric     // Treat an enum type as its underlying type.
100*06c3fb27SDimitry Andric     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
101*06c3fb27SDimitry Andric       Ty = EnumTy->getDecl()->getIntegerType();
102*06c3fb27SDimitry Andric 
103*06c3fb27SDimitry Andric     uint64_t Size = getContext().getTypeSize(Ty);
104*06c3fb27SDimitry Andric     if (Size <= 64)
105*06c3fb27SDimitry Andric       HexagonAdjustRegsLeft(Size, RegsLeft);
106*06c3fb27SDimitry Andric 
107*06c3fb27SDimitry Andric     if (Size > 64 && Ty->isBitIntType())
108*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
109*06c3fb27SDimitry Andric 
110*06c3fb27SDimitry Andric     return isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
111*06c3fb27SDimitry Andric                                              : ABIArgInfo::getDirect();
112*06c3fb27SDimitry Andric   }
113*06c3fb27SDimitry Andric 
114*06c3fb27SDimitry Andric   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
115*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
116*06c3fb27SDimitry Andric 
117*06c3fb27SDimitry Andric   // Ignore empty records.
118*06c3fb27SDimitry Andric   if (isEmptyRecord(getContext(), Ty, true))
119*06c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
120*06c3fb27SDimitry Andric 
121*06c3fb27SDimitry Andric   uint64_t Size = getContext().getTypeSize(Ty);
122*06c3fb27SDimitry Andric   unsigned Align = getContext().getTypeAlign(Ty);
123*06c3fb27SDimitry Andric 
124*06c3fb27SDimitry Andric   if (Size > 64)
125*06c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
126*06c3fb27SDimitry Andric 
127*06c3fb27SDimitry Andric   if (HexagonAdjustRegsLeft(Size, RegsLeft))
128*06c3fb27SDimitry Andric     Align = Size <= 32 ? 32 : 64;
129*06c3fb27SDimitry Andric   if (Size <= Align) {
130*06c3fb27SDimitry Andric     // Pass in the smallest viable integer type.
131*06c3fb27SDimitry Andric     Size = llvm::bit_ceil(Size);
132*06c3fb27SDimitry Andric     return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
133*06c3fb27SDimitry Andric   }
134*06c3fb27SDimitry Andric   return DefaultABIInfo::classifyArgumentType(Ty);
135*06c3fb27SDimitry Andric }
136*06c3fb27SDimitry Andric 
137*06c3fb27SDimitry Andric ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
138*06c3fb27SDimitry Andric   if (RetTy->isVoidType())
139*06c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
140*06c3fb27SDimitry Andric 
141*06c3fb27SDimitry Andric   const TargetInfo &T = CGT.getTarget();
142*06c3fb27SDimitry Andric   uint64_t Size = getContext().getTypeSize(RetTy);
143*06c3fb27SDimitry Andric 
144*06c3fb27SDimitry Andric   if (RetTy->getAs<VectorType>()) {
145*06c3fb27SDimitry Andric     // HVX vectors are returned in vector registers or register pairs.
146*06c3fb27SDimitry Andric     if (T.hasFeature("hvx")) {
147*06c3fb27SDimitry Andric       assert(T.hasFeature("hvx-length64b") || T.hasFeature("hvx-length128b"));
148*06c3fb27SDimitry Andric       uint64_t VecSize = T.hasFeature("hvx-length64b") ? 64*8 : 128*8;
149*06c3fb27SDimitry Andric       if (Size == VecSize || Size == 2*VecSize)
150*06c3fb27SDimitry Andric         return ABIArgInfo::getDirectInReg();
151*06c3fb27SDimitry Andric     }
152*06c3fb27SDimitry Andric     // Large vector types should be returned via memory.
153*06c3fb27SDimitry Andric     if (Size > 64)
154*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy);
155*06c3fb27SDimitry Andric   }
156*06c3fb27SDimitry Andric 
157*06c3fb27SDimitry Andric   if (!isAggregateTypeForABI(RetTy)) {
158*06c3fb27SDimitry Andric     // Treat an enum type as its underlying type.
159*06c3fb27SDimitry Andric     if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
160*06c3fb27SDimitry Andric       RetTy = EnumTy->getDecl()->getIntegerType();
161*06c3fb27SDimitry Andric 
162*06c3fb27SDimitry Andric     if (Size > 64 && RetTy->isBitIntType())
163*06c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy, /*ByVal=*/false);
164*06c3fb27SDimitry Andric 
165*06c3fb27SDimitry Andric     return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
166*06c3fb27SDimitry Andric                                                 : ABIArgInfo::getDirect();
167*06c3fb27SDimitry Andric   }
168*06c3fb27SDimitry Andric 
169*06c3fb27SDimitry Andric   if (isEmptyRecord(getContext(), RetTy, true))
170*06c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
171*06c3fb27SDimitry Andric 
172*06c3fb27SDimitry Andric   // Aggregates <= 8 bytes are returned in registers, other aggregates
173*06c3fb27SDimitry Andric   // are returned indirectly.
174*06c3fb27SDimitry Andric   if (Size <= 64) {
175*06c3fb27SDimitry Andric     // Return in the smallest viable integer type.
176*06c3fb27SDimitry Andric     Size = llvm::bit_ceil(Size);
177*06c3fb27SDimitry Andric     return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
178*06c3fb27SDimitry Andric   }
179*06c3fb27SDimitry Andric   return getNaturalAlignIndirect(RetTy, /*ByVal=*/true);
180*06c3fb27SDimitry Andric }
181*06c3fb27SDimitry Andric 
182*06c3fb27SDimitry Andric Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF,
183*06c3fb27SDimitry Andric                                             Address VAListAddr,
184*06c3fb27SDimitry Andric                                             QualType Ty) const {
185*06c3fb27SDimitry Andric   // Load the overflow area pointer.
186*06c3fb27SDimitry Andric   Address __overflow_area_pointer_p =
187*06c3fb27SDimitry Andric       CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p");
188*06c3fb27SDimitry Andric   llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad(
189*06c3fb27SDimitry Andric       __overflow_area_pointer_p, "__overflow_area_pointer");
190*06c3fb27SDimitry Andric 
191*06c3fb27SDimitry Andric   uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
192*06c3fb27SDimitry Andric   if (Align > 4) {
193*06c3fb27SDimitry Andric     // Alignment should be a power of 2.
194*06c3fb27SDimitry Andric     assert((Align & (Align - 1)) == 0 && "Alignment is not power of 2!");
195*06c3fb27SDimitry Andric 
196*06c3fb27SDimitry Andric     // overflow_arg_area = (overflow_arg_area + align - 1) & -align;
197*06c3fb27SDimitry Andric     llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int64Ty, Align - 1);
198*06c3fb27SDimitry Andric 
199*06c3fb27SDimitry Andric     // Add offset to the current pointer to access the argument.
200*06c3fb27SDimitry Andric     __overflow_area_pointer =
201*06c3fb27SDimitry Andric         CGF.Builder.CreateGEP(CGF.Int8Ty, __overflow_area_pointer, Offset);
202*06c3fb27SDimitry Andric     llvm::Value *AsInt =
203*06c3fb27SDimitry Andric         CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty);
204*06c3fb27SDimitry Andric 
205*06c3fb27SDimitry Andric     // Create a mask which should be "AND"ed
206*06c3fb27SDimitry Andric     // with (overflow_arg_area + align - 1)
207*06c3fb27SDimitry Andric     llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -(int)Align);
208*06c3fb27SDimitry Andric     __overflow_area_pointer = CGF.Builder.CreateIntToPtr(
209*06c3fb27SDimitry Andric         CGF.Builder.CreateAnd(AsInt, Mask), __overflow_area_pointer->getType(),
210*06c3fb27SDimitry Andric         "__overflow_area_pointer.align");
211*06c3fb27SDimitry Andric   }
212*06c3fb27SDimitry Andric 
213*06c3fb27SDimitry Andric   // Get the type of the argument from memory and bitcast
214*06c3fb27SDimitry Andric   // overflow area pointer to the argument type.
215*06c3fb27SDimitry Andric   llvm::Type *PTy = CGF.ConvertTypeForMem(Ty);
216*06c3fb27SDimitry Andric   Address AddrTyped =
217*06c3fb27SDimitry Andric       Address(__overflow_area_pointer, PTy, CharUnits::fromQuantity(Align));
218*06c3fb27SDimitry Andric 
219*06c3fb27SDimitry Andric   // Round up to the minimum stack alignment for varargs which is 4 bytes.
220*06c3fb27SDimitry Andric   uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
221*06c3fb27SDimitry Andric 
222*06c3fb27SDimitry Andric   __overflow_area_pointer = CGF.Builder.CreateGEP(
223*06c3fb27SDimitry Andric       CGF.Int8Ty, __overflow_area_pointer,
224*06c3fb27SDimitry Andric       llvm::ConstantInt::get(CGF.Int32Ty, Offset),
225*06c3fb27SDimitry Andric       "__overflow_area_pointer.next");
226*06c3fb27SDimitry Andric   CGF.Builder.CreateStore(__overflow_area_pointer, __overflow_area_pointer_p);
227*06c3fb27SDimitry Andric 
228*06c3fb27SDimitry Andric   return AddrTyped;
229*06c3fb27SDimitry Andric }
230*06c3fb27SDimitry Andric 
231*06c3fb27SDimitry Andric Address HexagonABIInfo::EmitVAArgForHexagon(CodeGenFunction &CGF,
232*06c3fb27SDimitry Andric                                             Address VAListAddr,
233*06c3fb27SDimitry Andric                                             QualType Ty) const {
234*06c3fb27SDimitry Andric   // FIXME: Need to handle alignment
235*06c3fb27SDimitry Andric   llvm::Type *BP = CGF.Int8PtrTy;
236*06c3fb27SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
237*06c3fb27SDimitry Andric   Address VAListAddrAsBPP = VAListAddr.withElementType(BP);
238*06c3fb27SDimitry Andric   llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
239*06c3fb27SDimitry Andric   // Handle address alignment for type alignment > 32 bits
240*06c3fb27SDimitry Andric   uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
241*06c3fb27SDimitry Andric   if (TyAlign > 4) {
242*06c3fb27SDimitry Andric     assert((TyAlign & (TyAlign - 1)) == 0 && "Alignment is not power of 2!");
243*06c3fb27SDimitry Andric     llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty);
244*06c3fb27SDimitry Andric     AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1));
245*06c3fb27SDimitry Andric     AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1)));
246*06c3fb27SDimitry Andric     Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
247*06c3fb27SDimitry Andric   }
248*06c3fb27SDimitry Andric   Address AddrTyped =
249*06c3fb27SDimitry Andric       Address(Addr, CGF.ConvertType(Ty), CharUnits::fromQuantity(TyAlign));
250*06c3fb27SDimitry Andric 
251*06c3fb27SDimitry Andric   uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
252*06c3fb27SDimitry Andric   llvm::Value *NextAddr = Builder.CreateGEP(
253*06c3fb27SDimitry Andric       CGF.Int8Ty, Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next");
254*06c3fb27SDimitry Andric   Builder.CreateStore(NextAddr, VAListAddrAsBPP);
255*06c3fb27SDimitry Andric 
256*06c3fb27SDimitry Andric   return AddrTyped;
257*06c3fb27SDimitry Andric }
258*06c3fb27SDimitry Andric 
259*06c3fb27SDimitry Andric Address HexagonABIInfo::EmitVAArgForHexagonLinux(CodeGenFunction &CGF,
260*06c3fb27SDimitry Andric                                                  Address VAListAddr,
261*06c3fb27SDimitry Andric                                                  QualType Ty) const {
262*06c3fb27SDimitry Andric   int ArgSize = CGF.getContext().getTypeSize(Ty) / 8;
263*06c3fb27SDimitry Andric 
264*06c3fb27SDimitry Andric   if (ArgSize > 8)
265*06c3fb27SDimitry Andric     return EmitVAArgFromMemory(CGF, VAListAddr, Ty);
266*06c3fb27SDimitry Andric 
267*06c3fb27SDimitry Andric   // Here we have check if the argument is in register area or
268*06c3fb27SDimitry Andric   // in overflow area.
269*06c3fb27SDimitry Andric   // If the saved register area pointer + argsize rounded up to alignment >
270*06c3fb27SDimitry Andric   // saved register area end pointer, argument is in overflow area.
271*06c3fb27SDimitry Andric   unsigned RegsLeft = 6;
272*06c3fb27SDimitry Andric   Ty = CGF.getContext().getCanonicalType(Ty);
273*06c3fb27SDimitry Andric   (void)classifyArgumentType(Ty, &RegsLeft);
274*06c3fb27SDimitry Andric 
275*06c3fb27SDimitry Andric   llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg");
276*06c3fb27SDimitry Andric   llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
277*06c3fb27SDimitry Andric   llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack");
278*06c3fb27SDimitry Andric   llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
279*06c3fb27SDimitry Andric 
280*06c3fb27SDimitry Andric   // Get rounded size of the argument.GCC does not allow vararg of
281*06c3fb27SDimitry Andric   // size < 4 bytes. We follow the same logic here.
282*06c3fb27SDimitry Andric   ArgSize = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8;
283*06c3fb27SDimitry Andric   int ArgAlign = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8;
284*06c3fb27SDimitry Andric 
285*06c3fb27SDimitry Andric   // Argument may be in saved register area
286*06c3fb27SDimitry Andric   CGF.EmitBlock(MaybeRegBlock);
287*06c3fb27SDimitry Andric 
288*06c3fb27SDimitry Andric   // Load the current saved register area pointer.
289*06c3fb27SDimitry Andric   Address __current_saved_reg_area_pointer_p = CGF.Builder.CreateStructGEP(
290*06c3fb27SDimitry Andric       VAListAddr, 0, "__current_saved_reg_area_pointer_p");
291*06c3fb27SDimitry Andric   llvm::Value *__current_saved_reg_area_pointer = CGF.Builder.CreateLoad(
292*06c3fb27SDimitry Andric       __current_saved_reg_area_pointer_p, "__current_saved_reg_area_pointer");
293*06c3fb27SDimitry Andric 
294*06c3fb27SDimitry Andric   // Load the saved register area end pointer.
295*06c3fb27SDimitry Andric   Address __saved_reg_area_end_pointer_p = CGF.Builder.CreateStructGEP(
296*06c3fb27SDimitry Andric       VAListAddr, 1, "__saved_reg_area_end_pointer_p");
297*06c3fb27SDimitry Andric   llvm::Value *__saved_reg_area_end_pointer = CGF.Builder.CreateLoad(
298*06c3fb27SDimitry Andric       __saved_reg_area_end_pointer_p, "__saved_reg_area_end_pointer");
299*06c3fb27SDimitry Andric 
300*06c3fb27SDimitry Andric   // If the size of argument is > 4 bytes, check if the stack
301*06c3fb27SDimitry Andric   // location is aligned to 8 bytes
302*06c3fb27SDimitry Andric   if (ArgAlign > 4) {
303*06c3fb27SDimitry Andric 
304*06c3fb27SDimitry Andric     llvm::Value *__current_saved_reg_area_pointer_int =
305*06c3fb27SDimitry Andric         CGF.Builder.CreatePtrToInt(__current_saved_reg_area_pointer,
306*06c3fb27SDimitry Andric                                    CGF.Int32Ty);
307*06c3fb27SDimitry Andric 
308*06c3fb27SDimitry Andric     __current_saved_reg_area_pointer_int = CGF.Builder.CreateAdd(
309*06c3fb27SDimitry Andric         __current_saved_reg_area_pointer_int,
310*06c3fb27SDimitry Andric         llvm::ConstantInt::get(CGF.Int32Ty, (ArgAlign - 1)),
311*06c3fb27SDimitry Andric         "align_current_saved_reg_area_pointer");
312*06c3fb27SDimitry Andric 
313*06c3fb27SDimitry Andric     __current_saved_reg_area_pointer_int =
314*06c3fb27SDimitry Andric         CGF.Builder.CreateAnd(__current_saved_reg_area_pointer_int,
315*06c3fb27SDimitry Andric                               llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign),
316*06c3fb27SDimitry Andric                               "align_current_saved_reg_area_pointer");
317*06c3fb27SDimitry Andric 
318*06c3fb27SDimitry Andric     __current_saved_reg_area_pointer =
319*06c3fb27SDimitry Andric         CGF.Builder.CreateIntToPtr(__current_saved_reg_area_pointer_int,
320*06c3fb27SDimitry Andric                                    __current_saved_reg_area_pointer->getType(),
321*06c3fb27SDimitry Andric                                    "align_current_saved_reg_area_pointer");
322*06c3fb27SDimitry Andric   }
323*06c3fb27SDimitry Andric 
324*06c3fb27SDimitry Andric   llvm::Value *__new_saved_reg_area_pointer =
325*06c3fb27SDimitry Andric       CGF.Builder.CreateGEP(CGF.Int8Ty, __current_saved_reg_area_pointer,
326*06c3fb27SDimitry Andric                             llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
327*06c3fb27SDimitry Andric                             "__new_saved_reg_area_pointer");
328*06c3fb27SDimitry Andric 
329*06c3fb27SDimitry Andric   llvm::Value *UsingStack = nullptr;
330*06c3fb27SDimitry Andric   UsingStack = CGF.Builder.CreateICmpSGT(__new_saved_reg_area_pointer,
331*06c3fb27SDimitry Andric                                          __saved_reg_area_end_pointer);
332*06c3fb27SDimitry Andric 
333*06c3fb27SDimitry Andric   CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, InRegBlock);
334*06c3fb27SDimitry Andric 
335*06c3fb27SDimitry Andric   // Argument in saved register area
336*06c3fb27SDimitry Andric   // Implement the block where argument is in register saved area
337*06c3fb27SDimitry Andric   CGF.EmitBlock(InRegBlock);
338*06c3fb27SDimitry Andric 
339*06c3fb27SDimitry Andric   llvm::Type *PTy = CGF.ConvertType(Ty);
340*06c3fb27SDimitry Andric   llvm::Value *__saved_reg_area_p = CGF.Builder.CreateBitCast(
341*06c3fb27SDimitry Andric       __current_saved_reg_area_pointer, llvm::PointerType::getUnqual(PTy));
342*06c3fb27SDimitry Andric 
343*06c3fb27SDimitry Andric   CGF.Builder.CreateStore(__new_saved_reg_area_pointer,
344*06c3fb27SDimitry Andric                           __current_saved_reg_area_pointer_p);
345*06c3fb27SDimitry Andric 
346*06c3fb27SDimitry Andric   CGF.EmitBranch(ContBlock);
347*06c3fb27SDimitry Andric 
348*06c3fb27SDimitry Andric   // Argument in overflow area
349*06c3fb27SDimitry Andric   // Implement the block where the argument is in overflow area.
350*06c3fb27SDimitry Andric   CGF.EmitBlock(OnStackBlock);
351*06c3fb27SDimitry Andric 
352*06c3fb27SDimitry Andric   // Load the overflow area pointer
353*06c3fb27SDimitry Andric   Address __overflow_area_pointer_p =
354*06c3fb27SDimitry Andric       CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p");
355*06c3fb27SDimitry Andric   llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad(
356*06c3fb27SDimitry Andric       __overflow_area_pointer_p, "__overflow_area_pointer");
357*06c3fb27SDimitry Andric 
358*06c3fb27SDimitry Andric   // Align the overflow area pointer according to the alignment of the argument
359*06c3fb27SDimitry Andric   if (ArgAlign > 4) {
360*06c3fb27SDimitry Andric     llvm::Value *__overflow_area_pointer_int =
361*06c3fb27SDimitry Andric         CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty);
362*06c3fb27SDimitry Andric 
363*06c3fb27SDimitry Andric     __overflow_area_pointer_int =
364*06c3fb27SDimitry Andric         CGF.Builder.CreateAdd(__overflow_area_pointer_int,
365*06c3fb27SDimitry Andric                               llvm::ConstantInt::get(CGF.Int32Ty, ArgAlign - 1),
366*06c3fb27SDimitry Andric                               "align_overflow_area_pointer");
367*06c3fb27SDimitry Andric 
368*06c3fb27SDimitry Andric     __overflow_area_pointer_int =
369*06c3fb27SDimitry Andric         CGF.Builder.CreateAnd(__overflow_area_pointer_int,
370*06c3fb27SDimitry Andric                               llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign),
371*06c3fb27SDimitry Andric                               "align_overflow_area_pointer");
372*06c3fb27SDimitry Andric 
373*06c3fb27SDimitry Andric     __overflow_area_pointer = CGF.Builder.CreateIntToPtr(
374*06c3fb27SDimitry Andric         __overflow_area_pointer_int, __overflow_area_pointer->getType(),
375*06c3fb27SDimitry Andric         "align_overflow_area_pointer");
376*06c3fb27SDimitry Andric   }
377*06c3fb27SDimitry Andric 
378*06c3fb27SDimitry Andric   // Get the pointer for next argument in overflow area and store it
379*06c3fb27SDimitry Andric   // to overflow area pointer.
380*06c3fb27SDimitry Andric   llvm::Value *__new_overflow_area_pointer = CGF.Builder.CreateGEP(
381*06c3fb27SDimitry Andric       CGF.Int8Ty, __overflow_area_pointer,
382*06c3fb27SDimitry Andric       llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
383*06c3fb27SDimitry Andric       "__overflow_area_pointer.next");
384*06c3fb27SDimitry Andric 
385*06c3fb27SDimitry Andric   CGF.Builder.CreateStore(__new_overflow_area_pointer,
386*06c3fb27SDimitry Andric                           __overflow_area_pointer_p);
387*06c3fb27SDimitry Andric 
388*06c3fb27SDimitry Andric   CGF.Builder.CreateStore(__new_overflow_area_pointer,
389*06c3fb27SDimitry Andric                           __current_saved_reg_area_pointer_p);
390*06c3fb27SDimitry Andric 
391*06c3fb27SDimitry Andric   // Bitcast the overflow area pointer to the type of argument.
392*06c3fb27SDimitry Andric   llvm::Type *OverflowPTy = CGF.ConvertTypeForMem(Ty);
393*06c3fb27SDimitry Andric   llvm::Value *__overflow_area_p = CGF.Builder.CreateBitCast(
394*06c3fb27SDimitry Andric       __overflow_area_pointer, llvm::PointerType::getUnqual(OverflowPTy));
395*06c3fb27SDimitry Andric 
396*06c3fb27SDimitry Andric   CGF.EmitBranch(ContBlock);
397*06c3fb27SDimitry Andric 
398*06c3fb27SDimitry Andric   // Get the correct pointer to load the variable argument
399*06c3fb27SDimitry Andric   // Implement the ContBlock
400*06c3fb27SDimitry Andric   CGF.EmitBlock(ContBlock);
401*06c3fb27SDimitry Andric 
402*06c3fb27SDimitry Andric   llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty);
403*06c3fb27SDimitry Andric   llvm::Type *MemPTy = llvm::PointerType::getUnqual(MemTy);
404*06c3fb27SDimitry Andric   llvm::PHINode *ArgAddr = CGF.Builder.CreatePHI(MemPTy, 2, "vaarg.addr");
405*06c3fb27SDimitry Andric   ArgAddr->addIncoming(__saved_reg_area_p, InRegBlock);
406*06c3fb27SDimitry Andric   ArgAddr->addIncoming(__overflow_area_p, OnStackBlock);
407*06c3fb27SDimitry Andric 
408*06c3fb27SDimitry Andric   return Address(ArgAddr, MemTy, CharUnits::fromQuantity(ArgAlign));
409*06c3fb27SDimitry Andric }
410*06c3fb27SDimitry Andric 
411*06c3fb27SDimitry Andric Address HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
412*06c3fb27SDimitry Andric                                   QualType Ty) const {
413*06c3fb27SDimitry Andric 
414*06c3fb27SDimitry Andric   if (getTarget().getTriple().isMusl())
415*06c3fb27SDimitry Andric     return EmitVAArgForHexagonLinux(CGF, VAListAddr, Ty);
416*06c3fb27SDimitry Andric 
417*06c3fb27SDimitry Andric   return EmitVAArgForHexagon(CGF, VAListAddr, Ty);
418*06c3fb27SDimitry Andric }
419*06c3fb27SDimitry Andric 
420*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
421*06c3fb27SDimitry Andric CodeGen::createHexagonTargetCodeGenInfo(CodeGenModule &CGM) {
422*06c3fb27SDimitry Andric   return std::make_unique<HexagonTargetCodeGenInfo>(CGM.getTypes());
423*06c3fb27SDimitry Andric }
424