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