xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/Hexagon.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===- Hexagon.cpp --------------------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric 
906c3fb27SDimitry Andric #include "ABIInfoImpl.h"
1006c3fb27SDimitry Andric #include "TargetInfo.h"
1106c3fb27SDimitry Andric 
1206c3fb27SDimitry Andric using namespace clang;
1306c3fb27SDimitry Andric using namespace clang::CodeGen;
1406c3fb27SDimitry Andric 
1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1606c3fb27SDimitry Andric // Hexagon ABI Implementation
1706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1806c3fb27SDimitry Andric 
1906c3fb27SDimitry Andric namespace {
2006c3fb27SDimitry Andric 
2106c3fb27SDimitry Andric class HexagonABIInfo : public DefaultABIInfo {
2206c3fb27SDimitry Andric public:
2306c3fb27SDimitry Andric   HexagonABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
2406c3fb27SDimitry Andric 
2506c3fb27SDimitry Andric private:
2606c3fb27SDimitry Andric   ABIArgInfo classifyReturnType(QualType RetTy) const;
2706c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy) const;
2806c3fb27SDimitry Andric   ABIArgInfo classifyArgumentType(QualType RetTy, unsigned *RegsLeft) const;
2906c3fb27SDimitry Andric 
3006c3fb27SDimitry Andric   void computeInfo(CGFunctionInfo &FI) const override;
3106c3fb27SDimitry Andric 
32*0fca6ea1SDimitry Andric   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
33*0fca6ea1SDimitry Andric                    AggValueSlot Slot) const override;
3406c3fb27SDimitry Andric   Address EmitVAArgFromMemory(CodeGenFunction &CFG, Address VAListAddr,
3506c3fb27SDimitry Andric                               QualType Ty) const;
3606c3fb27SDimitry Andric   Address EmitVAArgForHexagon(CodeGenFunction &CFG, Address VAListAddr,
3706c3fb27SDimitry Andric                               QualType Ty) const;
3806c3fb27SDimitry Andric   Address EmitVAArgForHexagonLinux(CodeGenFunction &CFG, Address VAListAddr,
3906c3fb27SDimitry Andric                                    QualType Ty) const;
4006c3fb27SDimitry Andric };
4106c3fb27SDimitry Andric 
4206c3fb27SDimitry Andric class HexagonTargetCodeGenInfo : public TargetCodeGenInfo {
4306c3fb27SDimitry Andric public:
4406c3fb27SDimitry Andric   HexagonTargetCodeGenInfo(CodeGenTypes &CGT)
4506c3fb27SDimitry Andric       : TargetCodeGenInfo(std::make_unique<HexagonABIInfo>(CGT)) {}
4606c3fb27SDimitry Andric 
4706c3fb27SDimitry Andric   int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
4806c3fb27SDimitry Andric     return 29;
4906c3fb27SDimitry Andric   }
5006c3fb27SDimitry Andric 
5106c3fb27SDimitry Andric   void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
5206c3fb27SDimitry Andric                            CodeGen::CodeGenModule &GCM) const override {
5306c3fb27SDimitry Andric     if (GV->isDeclaration())
5406c3fb27SDimitry Andric       return;
5506c3fb27SDimitry Andric     const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
5606c3fb27SDimitry Andric     if (!FD)
5706c3fb27SDimitry Andric       return;
5806c3fb27SDimitry Andric   }
5906c3fb27SDimitry Andric };
6006c3fb27SDimitry Andric 
6106c3fb27SDimitry Andric } // namespace
6206c3fb27SDimitry Andric 
6306c3fb27SDimitry Andric void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const {
6406c3fb27SDimitry Andric   unsigned RegsLeft = 6;
6506c3fb27SDimitry Andric   if (!getCXXABI().classifyReturnType(FI))
6606c3fb27SDimitry Andric     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
6706c3fb27SDimitry Andric   for (auto &I : FI.arguments())
6806c3fb27SDimitry Andric     I.info = classifyArgumentType(I.type, &RegsLeft);
6906c3fb27SDimitry Andric }
7006c3fb27SDimitry Andric 
7106c3fb27SDimitry Andric static bool HexagonAdjustRegsLeft(uint64_t Size, unsigned *RegsLeft) {
7206c3fb27SDimitry Andric   assert(Size <= 64 && "Not expecting to pass arguments larger than 64 bits"
7306c3fb27SDimitry Andric                        " through registers");
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric   if (*RegsLeft == 0)
7606c3fb27SDimitry Andric     return false;
7706c3fb27SDimitry Andric 
7806c3fb27SDimitry Andric   if (Size <= 32) {
7906c3fb27SDimitry Andric     (*RegsLeft)--;
8006c3fb27SDimitry Andric     return true;
8106c3fb27SDimitry Andric   }
8206c3fb27SDimitry Andric 
8306c3fb27SDimitry Andric   if (2 <= (*RegsLeft & (~1U))) {
8406c3fb27SDimitry Andric     *RegsLeft = (*RegsLeft & (~1U)) - 2;
8506c3fb27SDimitry Andric     return true;
8606c3fb27SDimitry Andric   }
8706c3fb27SDimitry Andric 
8806c3fb27SDimitry Andric   // Next available register was r5 but candidate was greater than 32-bits so it
8906c3fb27SDimitry Andric   // has to go on the stack. However we still consume r5
9006c3fb27SDimitry Andric   if (*RegsLeft == 1)
9106c3fb27SDimitry Andric     *RegsLeft = 0;
9206c3fb27SDimitry Andric 
9306c3fb27SDimitry Andric   return false;
9406c3fb27SDimitry Andric }
9506c3fb27SDimitry Andric 
9606c3fb27SDimitry Andric ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty,
9706c3fb27SDimitry Andric                                                 unsigned *RegsLeft) const {
9806c3fb27SDimitry Andric   if (!isAggregateTypeForABI(Ty)) {
9906c3fb27SDimitry Andric     // Treat an enum type as its underlying type.
10006c3fb27SDimitry Andric     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
10106c3fb27SDimitry Andric       Ty = EnumTy->getDecl()->getIntegerType();
10206c3fb27SDimitry Andric 
10306c3fb27SDimitry Andric     uint64_t Size = getContext().getTypeSize(Ty);
10406c3fb27SDimitry Andric     if (Size <= 64)
10506c3fb27SDimitry Andric       HexagonAdjustRegsLeft(Size, RegsLeft);
10606c3fb27SDimitry Andric 
10706c3fb27SDimitry Andric     if (Size > 64 && Ty->isBitIntType())
10806c3fb27SDimitry Andric       return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
10906c3fb27SDimitry Andric 
11006c3fb27SDimitry Andric     return isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
11106c3fb27SDimitry Andric                                              : ABIArgInfo::getDirect();
11206c3fb27SDimitry Andric   }
11306c3fb27SDimitry Andric 
11406c3fb27SDimitry Andric   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
11506c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
11606c3fb27SDimitry Andric 
11706c3fb27SDimitry Andric   // Ignore empty records.
11806c3fb27SDimitry Andric   if (isEmptyRecord(getContext(), Ty, true))
11906c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
12006c3fb27SDimitry Andric 
12106c3fb27SDimitry Andric   uint64_t Size = getContext().getTypeSize(Ty);
12206c3fb27SDimitry Andric   unsigned Align = getContext().getTypeAlign(Ty);
12306c3fb27SDimitry Andric 
12406c3fb27SDimitry Andric   if (Size > 64)
12506c3fb27SDimitry Andric     return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
12606c3fb27SDimitry Andric 
12706c3fb27SDimitry Andric   if (HexagonAdjustRegsLeft(Size, RegsLeft))
12806c3fb27SDimitry Andric     Align = Size <= 32 ? 32 : 64;
12906c3fb27SDimitry Andric   if (Size <= Align) {
13006c3fb27SDimitry Andric     // Pass in the smallest viable integer type.
13106c3fb27SDimitry Andric     Size = llvm::bit_ceil(Size);
13206c3fb27SDimitry Andric     return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
13306c3fb27SDimitry Andric   }
13406c3fb27SDimitry Andric   return DefaultABIInfo::classifyArgumentType(Ty);
13506c3fb27SDimitry Andric }
13606c3fb27SDimitry Andric 
13706c3fb27SDimitry Andric ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
13806c3fb27SDimitry Andric   if (RetTy->isVoidType())
13906c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
14006c3fb27SDimitry Andric 
14106c3fb27SDimitry Andric   const TargetInfo &T = CGT.getTarget();
14206c3fb27SDimitry Andric   uint64_t Size = getContext().getTypeSize(RetTy);
14306c3fb27SDimitry Andric 
14406c3fb27SDimitry Andric   if (RetTy->getAs<VectorType>()) {
14506c3fb27SDimitry Andric     // HVX vectors are returned in vector registers or register pairs.
14606c3fb27SDimitry Andric     if (T.hasFeature("hvx")) {
14706c3fb27SDimitry Andric       assert(T.hasFeature("hvx-length64b") || T.hasFeature("hvx-length128b"));
14806c3fb27SDimitry Andric       uint64_t VecSize = T.hasFeature("hvx-length64b") ? 64*8 : 128*8;
14906c3fb27SDimitry Andric       if (Size == VecSize || Size == 2*VecSize)
15006c3fb27SDimitry Andric         return ABIArgInfo::getDirectInReg();
15106c3fb27SDimitry Andric     }
15206c3fb27SDimitry Andric     // Large vector types should be returned via memory.
15306c3fb27SDimitry Andric     if (Size > 64)
15406c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy);
15506c3fb27SDimitry Andric   }
15606c3fb27SDimitry Andric 
15706c3fb27SDimitry Andric   if (!isAggregateTypeForABI(RetTy)) {
15806c3fb27SDimitry Andric     // Treat an enum type as its underlying type.
15906c3fb27SDimitry Andric     if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
16006c3fb27SDimitry Andric       RetTy = EnumTy->getDecl()->getIntegerType();
16106c3fb27SDimitry Andric 
16206c3fb27SDimitry Andric     if (Size > 64 && RetTy->isBitIntType())
16306c3fb27SDimitry Andric       return getNaturalAlignIndirect(RetTy, /*ByVal=*/false);
16406c3fb27SDimitry Andric 
16506c3fb27SDimitry Andric     return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)
16606c3fb27SDimitry Andric                                                 : ABIArgInfo::getDirect();
16706c3fb27SDimitry Andric   }
16806c3fb27SDimitry Andric 
16906c3fb27SDimitry Andric   if (isEmptyRecord(getContext(), RetTy, true))
17006c3fb27SDimitry Andric     return ABIArgInfo::getIgnore();
17106c3fb27SDimitry Andric 
17206c3fb27SDimitry Andric   // Aggregates <= 8 bytes are returned in registers, other aggregates
17306c3fb27SDimitry Andric   // are returned indirectly.
17406c3fb27SDimitry Andric   if (Size <= 64) {
17506c3fb27SDimitry Andric     // Return in the smallest viable integer type.
17606c3fb27SDimitry Andric     Size = llvm::bit_ceil(Size);
17706c3fb27SDimitry Andric     return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size));
17806c3fb27SDimitry Andric   }
17906c3fb27SDimitry Andric   return getNaturalAlignIndirect(RetTy, /*ByVal=*/true);
18006c3fb27SDimitry Andric }
18106c3fb27SDimitry Andric 
18206c3fb27SDimitry Andric Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF,
18306c3fb27SDimitry Andric                                             Address VAListAddr,
18406c3fb27SDimitry Andric                                             QualType Ty) const {
18506c3fb27SDimitry Andric   // Load the overflow area pointer.
18606c3fb27SDimitry Andric   Address __overflow_area_pointer_p =
18706c3fb27SDimitry Andric       CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p");
18806c3fb27SDimitry Andric   llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad(
18906c3fb27SDimitry Andric       __overflow_area_pointer_p, "__overflow_area_pointer");
19006c3fb27SDimitry Andric 
19106c3fb27SDimitry Andric   uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8;
19206c3fb27SDimitry Andric   if (Align > 4) {
19306c3fb27SDimitry Andric     // Alignment should be a power of 2.
19406c3fb27SDimitry Andric     assert((Align & (Align - 1)) == 0 && "Alignment is not power of 2!");
19506c3fb27SDimitry Andric 
19606c3fb27SDimitry Andric     // overflow_arg_area = (overflow_arg_area + align - 1) & -align;
19706c3fb27SDimitry Andric     llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int64Ty, Align - 1);
19806c3fb27SDimitry Andric 
19906c3fb27SDimitry Andric     // Add offset to the current pointer to access the argument.
20006c3fb27SDimitry Andric     __overflow_area_pointer =
20106c3fb27SDimitry Andric         CGF.Builder.CreateGEP(CGF.Int8Ty, __overflow_area_pointer, Offset);
20206c3fb27SDimitry Andric     llvm::Value *AsInt =
20306c3fb27SDimitry Andric         CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty);
20406c3fb27SDimitry Andric 
20506c3fb27SDimitry Andric     // Create a mask which should be "AND"ed
20606c3fb27SDimitry Andric     // with (overflow_arg_area + align - 1)
20706c3fb27SDimitry Andric     llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -(int)Align);
20806c3fb27SDimitry Andric     __overflow_area_pointer = CGF.Builder.CreateIntToPtr(
20906c3fb27SDimitry Andric         CGF.Builder.CreateAnd(AsInt, Mask), __overflow_area_pointer->getType(),
21006c3fb27SDimitry Andric         "__overflow_area_pointer.align");
21106c3fb27SDimitry Andric   }
21206c3fb27SDimitry Andric 
21306c3fb27SDimitry Andric   // Get the type of the argument from memory and bitcast
21406c3fb27SDimitry Andric   // overflow area pointer to the argument type.
21506c3fb27SDimitry Andric   llvm::Type *PTy = CGF.ConvertTypeForMem(Ty);
21606c3fb27SDimitry Andric   Address AddrTyped =
21706c3fb27SDimitry Andric       Address(__overflow_area_pointer, PTy, CharUnits::fromQuantity(Align));
21806c3fb27SDimitry Andric 
21906c3fb27SDimitry Andric   // Round up to the minimum stack alignment for varargs which is 4 bytes.
22006c3fb27SDimitry Andric   uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
22106c3fb27SDimitry Andric 
22206c3fb27SDimitry Andric   __overflow_area_pointer = CGF.Builder.CreateGEP(
22306c3fb27SDimitry Andric       CGF.Int8Ty, __overflow_area_pointer,
22406c3fb27SDimitry Andric       llvm::ConstantInt::get(CGF.Int32Ty, Offset),
22506c3fb27SDimitry Andric       "__overflow_area_pointer.next");
22606c3fb27SDimitry Andric   CGF.Builder.CreateStore(__overflow_area_pointer, __overflow_area_pointer_p);
22706c3fb27SDimitry Andric 
22806c3fb27SDimitry Andric   return AddrTyped;
22906c3fb27SDimitry Andric }
23006c3fb27SDimitry Andric 
23106c3fb27SDimitry Andric Address HexagonABIInfo::EmitVAArgForHexagon(CodeGenFunction &CGF,
23206c3fb27SDimitry Andric                                             Address VAListAddr,
23306c3fb27SDimitry Andric                                             QualType Ty) const {
23406c3fb27SDimitry Andric   // FIXME: Need to handle alignment
23506c3fb27SDimitry Andric   llvm::Type *BP = CGF.Int8PtrTy;
23606c3fb27SDimitry Andric   CGBuilderTy &Builder = CGF.Builder;
23706c3fb27SDimitry Andric   Address VAListAddrAsBPP = VAListAddr.withElementType(BP);
23806c3fb27SDimitry Andric   llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
23906c3fb27SDimitry Andric   // Handle address alignment for type alignment > 32 bits
24006c3fb27SDimitry Andric   uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8;
24106c3fb27SDimitry Andric   if (TyAlign > 4) {
24206c3fb27SDimitry Andric     assert((TyAlign & (TyAlign - 1)) == 0 && "Alignment is not power of 2!");
24306c3fb27SDimitry Andric     llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty);
24406c3fb27SDimitry Andric     AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1));
24506c3fb27SDimitry Andric     AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1)));
24606c3fb27SDimitry Andric     Addr = Builder.CreateIntToPtr(AddrAsInt, BP);
24706c3fb27SDimitry Andric   }
24806c3fb27SDimitry Andric   Address AddrTyped =
24906c3fb27SDimitry Andric       Address(Addr, CGF.ConvertType(Ty), CharUnits::fromQuantity(TyAlign));
25006c3fb27SDimitry Andric 
25106c3fb27SDimitry Andric   uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
25206c3fb27SDimitry Andric   llvm::Value *NextAddr = Builder.CreateGEP(
25306c3fb27SDimitry Andric       CGF.Int8Ty, Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next");
25406c3fb27SDimitry Andric   Builder.CreateStore(NextAddr, VAListAddrAsBPP);
25506c3fb27SDimitry Andric 
25606c3fb27SDimitry Andric   return AddrTyped;
25706c3fb27SDimitry Andric }
25806c3fb27SDimitry Andric 
25906c3fb27SDimitry Andric Address HexagonABIInfo::EmitVAArgForHexagonLinux(CodeGenFunction &CGF,
26006c3fb27SDimitry Andric                                                  Address VAListAddr,
26106c3fb27SDimitry Andric                                                  QualType Ty) const {
26206c3fb27SDimitry Andric   int ArgSize = CGF.getContext().getTypeSize(Ty) / 8;
26306c3fb27SDimitry Andric 
26406c3fb27SDimitry Andric   if (ArgSize > 8)
26506c3fb27SDimitry Andric     return EmitVAArgFromMemory(CGF, VAListAddr, Ty);
26606c3fb27SDimitry Andric 
26706c3fb27SDimitry Andric   // Here we have check if the argument is in register area or
26806c3fb27SDimitry Andric   // in overflow area.
26906c3fb27SDimitry Andric   // If the saved register area pointer + argsize rounded up to alignment >
27006c3fb27SDimitry Andric   // saved register area end pointer, argument is in overflow area.
27106c3fb27SDimitry Andric   unsigned RegsLeft = 6;
27206c3fb27SDimitry Andric   Ty = CGF.getContext().getCanonicalType(Ty);
27306c3fb27SDimitry Andric   (void)classifyArgumentType(Ty, &RegsLeft);
27406c3fb27SDimitry Andric 
27506c3fb27SDimitry Andric   llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg");
27606c3fb27SDimitry Andric   llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");
27706c3fb27SDimitry Andric   llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack");
27806c3fb27SDimitry Andric   llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");
27906c3fb27SDimitry Andric 
28006c3fb27SDimitry Andric   // Get rounded size of the argument.GCC does not allow vararg of
28106c3fb27SDimitry Andric   // size < 4 bytes. We follow the same logic here.
28206c3fb27SDimitry Andric   ArgSize = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8;
28306c3fb27SDimitry Andric   int ArgAlign = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8;
28406c3fb27SDimitry Andric 
28506c3fb27SDimitry Andric   // Argument may be in saved register area
28606c3fb27SDimitry Andric   CGF.EmitBlock(MaybeRegBlock);
28706c3fb27SDimitry Andric 
28806c3fb27SDimitry Andric   // Load the current saved register area pointer.
28906c3fb27SDimitry Andric   Address __current_saved_reg_area_pointer_p = CGF.Builder.CreateStructGEP(
29006c3fb27SDimitry Andric       VAListAddr, 0, "__current_saved_reg_area_pointer_p");
29106c3fb27SDimitry Andric   llvm::Value *__current_saved_reg_area_pointer = CGF.Builder.CreateLoad(
29206c3fb27SDimitry Andric       __current_saved_reg_area_pointer_p, "__current_saved_reg_area_pointer");
29306c3fb27SDimitry Andric 
29406c3fb27SDimitry Andric   // Load the saved register area end pointer.
29506c3fb27SDimitry Andric   Address __saved_reg_area_end_pointer_p = CGF.Builder.CreateStructGEP(
29606c3fb27SDimitry Andric       VAListAddr, 1, "__saved_reg_area_end_pointer_p");
29706c3fb27SDimitry Andric   llvm::Value *__saved_reg_area_end_pointer = CGF.Builder.CreateLoad(
29806c3fb27SDimitry Andric       __saved_reg_area_end_pointer_p, "__saved_reg_area_end_pointer");
29906c3fb27SDimitry Andric 
30006c3fb27SDimitry Andric   // If the size of argument is > 4 bytes, check if the stack
30106c3fb27SDimitry Andric   // location is aligned to 8 bytes
30206c3fb27SDimitry Andric   if (ArgAlign > 4) {
30306c3fb27SDimitry Andric 
30406c3fb27SDimitry Andric     llvm::Value *__current_saved_reg_area_pointer_int =
30506c3fb27SDimitry Andric         CGF.Builder.CreatePtrToInt(__current_saved_reg_area_pointer,
30606c3fb27SDimitry Andric                                    CGF.Int32Ty);
30706c3fb27SDimitry Andric 
30806c3fb27SDimitry Andric     __current_saved_reg_area_pointer_int = CGF.Builder.CreateAdd(
30906c3fb27SDimitry Andric         __current_saved_reg_area_pointer_int,
31006c3fb27SDimitry Andric         llvm::ConstantInt::get(CGF.Int32Ty, (ArgAlign - 1)),
31106c3fb27SDimitry Andric         "align_current_saved_reg_area_pointer");
31206c3fb27SDimitry Andric 
31306c3fb27SDimitry Andric     __current_saved_reg_area_pointer_int =
31406c3fb27SDimitry Andric         CGF.Builder.CreateAnd(__current_saved_reg_area_pointer_int,
31506c3fb27SDimitry Andric                               llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign),
31606c3fb27SDimitry Andric                               "align_current_saved_reg_area_pointer");
31706c3fb27SDimitry Andric 
31806c3fb27SDimitry Andric     __current_saved_reg_area_pointer =
31906c3fb27SDimitry Andric         CGF.Builder.CreateIntToPtr(__current_saved_reg_area_pointer_int,
32006c3fb27SDimitry Andric                                    __current_saved_reg_area_pointer->getType(),
32106c3fb27SDimitry Andric                                    "align_current_saved_reg_area_pointer");
32206c3fb27SDimitry Andric   }
32306c3fb27SDimitry Andric 
32406c3fb27SDimitry Andric   llvm::Value *__new_saved_reg_area_pointer =
32506c3fb27SDimitry Andric       CGF.Builder.CreateGEP(CGF.Int8Ty, __current_saved_reg_area_pointer,
32606c3fb27SDimitry Andric                             llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
32706c3fb27SDimitry Andric                             "__new_saved_reg_area_pointer");
32806c3fb27SDimitry Andric 
32906c3fb27SDimitry Andric   llvm::Value *UsingStack = nullptr;
33006c3fb27SDimitry Andric   UsingStack = CGF.Builder.CreateICmpSGT(__new_saved_reg_area_pointer,
33106c3fb27SDimitry Andric                                          __saved_reg_area_end_pointer);
33206c3fb27SDimitry Andric 
33306c3fb27SDimitry Andric   CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, InRegBlock);
33406c3fb27SDimitry Andric 
33506c3fb27SDimitry Andric   // Argument in saved register area
33606c3fb27SDimitry Andric   // Implement the block where argument is in register saved area
33706c3fb27SDimitry Andric   CGF.EmitBlock(InRegBlock);
33806c3fb27SDimitry Andric 
33906c3fb27SDimitry Andric   llvm::Type *PTy = CGF.ConvertType(Ty);
34006c3fb27SDimitry Andric   llvm::Value *__saved_reg_area_p = CGF.Builder.CreateBitCast(
34106c3fb27SDimitry Andric       __current_saved_reg_area_pointer, llvm::PointerType::getUnqual(PTy));
34206c3fb27SDimitry Andric 
34306c3fb27SDimitry Andric   CGF.Builder.CreateStore(__new_saved_reg_area_pointer,
34406c3fb27SDimitry Andric                           __current_saved_reg_area_pointer_p);
34506c3fb27SDimitry Andric 
34606c3fb27SDimitry Andric   CGF.EmitBranch(ContBlock);
34706c3fb27SDimitry Andric 
34806c3fb27SDimitry Andric   // Argument in overflow area
34906c3fb27SDimitry Andric   // Implement the block where the argument is in overflow area.
35006c3fb27SDimitry Andric   CGF.EmitBlock(OnStackBlock);
35106c3fb27SDimitry Andric 
35206c3fb27SDimitry Andric   // Load the overflow area pointer
35306c3fb27SDimitry Andric   Address __overflow_area_pointer_p =
35406c3fb27SDimitry Andric       CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p");
35506c3fb27SDimitry Andric   llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad(
35606c3fb27SDimitry Andric       __overflow_area_pointer_p, "__overflow_area_pointer");
35706c3fb27SDimitry Andric 
35806c3fb27SDimitry Andric   // Align the overflow area pointer according to the alignment of the argument
35906c3fb27SDimitry Andric   if (ArgAlign > 4) {
36006c3fb27SDimitry Andric     llvm::Value *__overflow_area_pointer_int =
36106c3fb27SDimitry Andric         CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty);
36206c3fb27SDimitry Andric 
36306c3fb27SDimitry Andric     __overflow_area_pointer_int =
36406c3fb27SDimitry Andric         CGF.Builder.CreateAdd(__overflow_area_pointer_int,
36506c3fb27SDimitry Andric                               llvm::ConstantInt::get(CGF.Int32Ty, ArgAlign - 1),
36606c3fb27SDimitry Andric                               "align_overflow_area_pointer");
36706c3fb27SDimitry Andric 
36806c3fb27SDimitry Andric     __overflow_area_pointer_int =
36906c3fb27SDimitry Andric         CGF.Builder.CreateAnd(__overflow_area_pointer_int,
37006c3fb27SDimitry Andric                               llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign),
37106c3fb27SDimitry Andric                               "align_overflow_area_pointer");
37206c3fb27SDimitry Andric 
37306c3fb27SDimitry Andric     __overflow_area_pointer = CGF.Builder.CreateIntToPtr(
37406c3fb27SDimitry Andric         __overflow_area_pointer_int, __overflow_area_pointer->getType(),
37506c3fb27SDimitry Andric         "align_overflow_area_pointer");
37606c3fb27SDimitry Andric   }
37706c3fb27SDimitry Andric 
37806c3fb27SDimitry Andric   // Get the pointer for next argument in overflow area and store it
37906c3fb27SDimitry Andric   // to overflow area pointer.
38006c3fb27SDimitry Andric   llvm::Value *__new_overflow_area_pointer = CGF.Builder.CreateGEP(
38106c3fb27SDimitry Andric       CGF.Int8Ty, __overflow_area_pointer,
38206c3fb27SDimitry Andric       llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
38306c3fb27SDimitry Andric       "__overflow_area_pointer.next");
38406c3fb27SDimitry Andric 
38506c3fb27SDimitry Andric   CGF.Builder.CreateStore(__new_overflow_area_pointer,
38606c3fb27SDimitry Andric                           __overflow_area_pointer_p);
38706c3fb27SDimitry Andric 
38806c3fb27SDimitry Andric   CGF.Builder.CreateStore(__new_overflow_area_pointer,
38906c3fb27SDimitry Andric                           __current_saved_reg_area_pointer_p);
39006c3fb27SDimitry Andric 
39106c3fb27SDimitry Andric   // Bitcast the overflow area pointer to the type of argument.
39206c3fb27SDimitry Andric   llvm::Type *OverflowPTy = CGF.ConvertTypeForMem(Ty);
39306c3fb27SDimitry Andric   llvm::Value *__overflow_area_p = CGF.Builder.CreateBitCast(
39406c3fb27SDimitry Andric       __overflow_area_pointer, llvm::PointerType::getUnqual(OverflowPTy));
39506c3fb27SDimitry Andric 
39606c3fb27SDimitry Andric   CGF.EmitBranch(ContBlock);
39706c3fb27SDimitry Andric 
39806c3fb27SDimitry Andric   // Get the correct pointer to load the variable argument
39906c3fb27SDimitry Andric   // Implement the ContBlock
40006c3fb27SDimitry Andric   CGF.EmitBlock(ContBlock);
40106c3fb27SDimitry Andric 
40206c3fb27SDimitry Andric   llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty);
40306c3fb27SDimitry Andric   llvm::Type *MemPTy = llvm::PointerType::getUnqual(MemTy);
40406c3fb27SDimitry Andric   llvm::PHINode *ArgAddr = CGF.Builder.CreatePHI(MemPTy, 2, "vaarg.addr");
40506c3fb27SDimitry Andric   ArgAddr->addIncoming(__saved_reg_area_p, InRegBlock);
40606c3fb27SDimitry Andric   ArgAddr->addIncoming(__overflow_area_p, OnStackBlock);
40706c3fb27SDimitry Andric 
40806c3fb27SDimitry Andric   return Address(ArgAddr, MemTy, CharUnits::fromQuantity(ArgAlign));
40906c3fb27SDimitry Andric }
41006c3fb27SDimitry Andric 
411*0fca6ea1SDimitry Andric RValue HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
412*0fca6ea1SDimitry Andric                                  QualType Ty, AggValueSlot Slot) const {
41306c3fb27SDimitry Andric 
41406c3fb27SDimitry Andric   if (getTarget().getTriple().isMusl())
415*0fca6ea1SDimitry Andric     return CGF.EmitLoadOfAnyValue(
416*0fca6ea1SDimitry Andric         CGF.MakeAddrLValue(EmitVAArgForHexagonLinux(CGF, VAListAddr, Ty), Ty),
417*0fca6ea1SDimitry Andric         Slot);
41806c3fb27SDimitry Andric 
419*0fca6ea1SDimitry Andric   return CGF.EmitLoadOfAnyValue(
420*0fca6ea1SDimitry Andric       CGF.MakeAddrLValue(EmitVAArgForHexagon(CGF, VAListAddr, Ty), Ty), Slot);
42106c3fb27SDimitry Andric }
42206c3fb27SDimitry Andric 
42306c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo>
42406c3fb27SDimitry Andric CodeGen::createHexagonTargetCodeGenInfo(CodeGenModule &CGM) {
42506c3fb27SDimitry Andric   return std::make_unique<HexagonTargetCodeGenInfo>(CGM.getTypes());
42606c3fb27SDimitry Andric }
427