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