1*06c3fb27SDimitry Andric //===- SystemZ.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 #include "clang/Basic/Builtins.h" 12*06c3fb27SDimitry Andric #include "llvm/IR/IntrinsicsS390.h" 13*06c3fb27SDimitry Andric 14*06c3fb27SDimitry Andric using namespace clang; 15*06c3fb27SDimitry Andric using namespace clang::CodeGen; 16*06c3fb27SDimitry Andric 17*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 18*06c3fb27SDimitry Andric // SystemZ ABI Implementation 19*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 20*06c3fb27SDimitry Andric 21*06c3fb27SDimitry Andric namespace { 22*06c3fb27SDimitry Andric 23*06c3fb27SDimitry Andric class SystemZABIInfo : public ABIInfo { 24*06c3fb27SDimitry Andric bool HasVector; 25*06c3fb27SDimitry Andric bool IsSoftFloatABI; 26*06c3fb27SDimitry Andric 27*06c3fb27SDimitry Andric public: 28*06c3fb27SDimitry Andric SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF) 29*06c3fb27SDimitry Andric : ABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {} 30*06c3fb27SDimitry Andric 31*06c3fb27SDimitry Andric bool isPromotableIntegerTypeForABI(QualType Ty) const; 32*06c3fb27SDimitry Andric bool isCompoundType(QualType Ty) const; 33*06c3fb27SDimitry Andric bool isVectorArgumentType(QualType Ty) const; 34*06c3fb27SDimitry Andric bool isFPArgumentType(QualType Ty) const; 35*06c3fb27SDimitry Andric QualType GetSingleElementType(QualType Ty) const; 36*06c3fb27SDimitry Andric 37*06c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const; 38*06c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType ArgTy) const; 39*06c3fb27SDimitry Andric 40*06c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 41*06c3fb27SDimitry Andric Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 42*06c3fb27SDimitry Andric QualType Ty) const override; 43*06c3fb27SDimitry Andric }; 44*06c3fb27SDimitry Andric 45*06c3fb27SDimitry Andric class SystemZTargetCodeGenInfo : public TargetCodeGenInfo { 46*06c3fb27SDimitry Andric ASTContext &Ctx; 47*06c3fb27SDimitry Andric 48*06c3fb27SDimitry Andric // These are used for speeding up the search for a visible vector ABI. 49*06c3fb27SDimitry Andric mutable bool HasVisibleVecABIFlag = false; 50*06c3fb27SDimitry Andric mutable std::set<const Type *> SeenTypes; 51*06c3fb27SDimitry Andric 52*06c3fb27SDimitry Andric // Returns true (the first time) if Ty is, or is found to include, a vector 53*06c3fb27SDimitry Andric // type that exposes the vector ABI. This is any vector >=16 bytes which 54*06c3fb27SDimitry Andric // with vector support are aligned to only 8 bytes. When IsParam is true, 55*06c3fb27SDimitry Andric // the type belongs to a value as passed between functions. If it is a 56*06c3fb27SDimitry Andric // vector <=16 bytes it will be passed in a vector register (if supported). 57*06c3fb27SDimitry Andric bool isVectorTypeBased(const Type *Ty, bool IsParam) const; 58*06c3fb27SDimitry Andric 59*06c3fb27SDimitry Andric public: 60*06c3fb27SDimitry Andric SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI) 61*06c3fb27SDimitry Andric : TargetCodeGenInfo( 62*06c3fb27SDimitry Andric std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)), 63*06c3fb27SDimitry Andric Ctx(CGT.getContext()) { 64*06c3fb27SDimitry Andric SwiftInfo = 65*06c3fb27SDimitry Andric std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false); 66*06c3fb27SDimitry Andric } 67*06c3fb27SDimitry Andric 68*06c3fb27SDimitry Andric // The vector ABI is different when the vector facility is present and when 69*06c3fb27SDimitry Andric // a module e.g. defines an externally visible vector variable, a flag 70*06c3fb27SDimitry Andric // indicating a visible vector ABI is added. Eventually this will result in 71*06c3fb27SDimitry Andric // a GNU attribute indicating the vector ABI of the module. Ty is the type 72*06c3fb27SDimitry Andric // of a variable or function parameter that is globally visible. 73*06c3fb27SDimitry Andric void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M, 74*06c3fb27SDimitry Andric bool IsParam) const { 75*06c3fb27SDimitry Andric if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) { 76*06c3fb27SDimitry Andric M.getModule().addModuleFlag(llvm::Module::Warning, 77*06c3fb27SDimitry Andric "s390x-visible-vector-ABI", 1); 78*06c3fb27SDimitry Andric HasVisibleVecABIFlag = true; 79*06c3fb27SDimitry Andric } 80*06c3fb27SDimitry Andric } 81*06c3fb27SDimitry Andric 82*06c3fb27SDimitry Andric void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 83*06c3fb27SDimitry Andric CodeGen::CodeGenModule &M) const override { 84*06c3fb27SDimitry Andric if (!D) 85*06c3fb27SDimitry Andric return; 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric // Check if the vector ABI becomes visible by an externally visible 88*06c3fb27SDimitry Andric // variable or function. 89*06c3fb27SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D)) { 90*06c3fb27SDimitry Andric if (VD->isExternallyVisible()) 91*06c3fb27SDimitry Andric handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M, 92*06c3fb27SDimitry Andric /*IsParam*/false); 93*06c3fb27SDimitry Andric } 94*06c3fb27SDimitry Andric else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 95*06c3fb27SDimitry Andric if (FD->isExternallyVisible()) 96*06c3fb27SDimitry Andric handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M, 97*06c3fb27SDimitry Andric /*IsParam*/false); 98*06c3fb27SDimitry Andric } 99*06c3fb27SDimitry Andric } 100*06c3fb27SDimitry Andric 101*06c3fb27SDimitry Andric llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID, 102*06c3fb27SDimitry Andric CGBuilderTy &Builder, 103*06c3fb27SDimitry Andric CodeGenModule &CGM) const override { 104*06c3fb27SDimitry Andric assert(V->getType()->isFloatingPointTy() && "V should have an FP type."); 105*06c3fb27SDimitry Andric // Only use TDC in constrained FP mode. 106*06c3fb27SDimitry Andric if (!Builder.getIsFPConstrained()) 107*06c3fb27SDimitry Andric return nullptr; 108*06c3fb27SDimitry Andric 109*06c3fb27SDimitry Andric llvm::Type *Ty = V->getType(); 110*06c3fb27SDimitry Andric if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) { 111*06c3fb27SDimitry Andric llvm::Module &M = CGM.getModule(); 112*06c3fb27SDimitry Andric auto &Ctx = M.getContext(); 113*06c3fb27SDimitry Andric llvm::Function *TDCFunc = 114*06c3fb27SDimitry Andric llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty); 115*06c3fb27SDimitry Andric unsigned TDCBits = 0; 116*06c3fb27SDimitry Andric switch (BuiltinID) { 117*06c3fb27SDimitry Andric case Builtin::BI__builtin_isnan: 118*06c3fb27SDimitry Andric TDCBits = 0xf; 119*06c3fb27SDimitry Andric break; 120*06c3fb27SDimitry Andric case Builtin::BIfinite: 121*06c3fb27SDimitry Andric case Builtin::BI__finite: 122*06c3fb27SDimitry Andric case Builtin::BIfinitef: 123*06c3fb27SDimitry Andric case Builtin::BI__finitef: 124*06c3fb27SDimitry Andric case Builtin::BIfinitel: 125*06c3fb27SDimitry Andric case Builtin::BI__finitel: 126*06c3fb27SDimitry Andric case Builtin::BI__builtin_isfinite: 127*06c3fb27SDimitry Andric TDCBits = 0xfc0; 128*06c3fb27SDimitry Andric break; 129*06c3fb27SDimitry Andric case Builtin::BI__builtin_isinf: 130*06c3fb27SDimitry Andric TDCBits = 0x30; 131*06c3fb27SDimitry Andric break; 132*06c3fb27SDimitry Andric default: 133*06c3fb27SDimitry Andric break; 134*06c3fb27SDimitry Andric } 135*06c3fb27SDimitry Andric if (TDCBits) 136*06c3fb27SDimitry Andric return Builder.CreateCall( 137*06c3fb27SDimitry Andric TDCFunc, 138*06c3fb27SDimitry Andric {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)}); 139*06c3fb27SDimitry Andric } 140*06c3fb27SDimitry Andric return nullptr; 141*06c3fb27SDimitry Andric } 142*06c3fb27SDimitry Andric }; 143*06c3fb27SDimitry Andric } 144*06c3fb27SDimitry Andric 145*06c3fb27SDimitry Andric bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const { 146*06c3fb27SDimitry Andric // Treat an enum type as its underlying type. 147*06c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 148*06c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 149*06c3fb27SDimitry Andric 150*06c3fb27SDimitry Andric // Promotable integer types are required to be promoted by the ABI. 151*06c3fb27SDimitry Andric if (ABIInfo::isPromotableIntegerTypeForABI(Ty)) 152*06c3fb27SDimitry Andric return true; 153*06c3fb27SDimitry Andric 154*06c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) 155*06c3fb27SDimitry Andric if (EIT->getNumBits() < 64) 156*06c3fb27SDimitry Andric return true; 157*06c3fb27SDimitry Andric 158*06c3fb27SDimitry Andric // 32-bit values must also be promoted. 159*06c3fb27SDimitry Andric if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) 160*06c3fb27SDimitry Andric switch (BT->getKind()) { 161*06c3fb27SDimitry Andric case BuiltinType::Int: 162*06c3fb27SDimitry Andric case BuiltinType::UInt: 163*06c3fb27SDimitry Andric return true; 164*06c3fb27SDimitry Andric default: 165*06c3fb27SDimitry Andric return false; 166*06c3fb27SDimitry Andric } 167*06c3fb27SDimitry Andric return false; 168*06c3fb27SDimitry Andric } 169*06c3fb27SDimitry Andric 170*06c3fb27SDimitry Andric bool SystemZABIInfo::isCompoundType(QualType Ty) const { 171*06c3fb27SDimitry Andric return (Ty->isAnyComplexType() || 172*06c3fb27SDimitry Andric Ty->isVectorType() || 173*06c3fb27SDimitry Andric isAggregateTypeForABI(Ty)); 174*06c3fb27SDimitry Andric } 175*06c3fb27SDimitry Andric 176*06c3fb27SDimitry Andric bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const { 177*06c3fb27SDimitry Andric return (HasVector && 178*06c3fb27SDimitry Andric Ty->isVectorType() && 179*06c3fb27SDimitry Andric getContext().getTypeSize(Ty) <= 128); 180*06c3fb27SDimitry Andric } 181*06c3fb27SDimitry Andric 182*06c3fb27SDimitry Andric bool SystemZABIInfo::isFPArgumentType(QualType Ty) const { 183*06c3fb27SDimitry Andric if (IsSoftFloatABI) 184*06c3fb27SDimitry Andric return false; 185*06c3fb27SDimitry Andric 186*06c3fb27SDimitry Andric if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) 187*06c3fb27SDimitry Andric switch (BT->getKind()) { 188*06c3fb27SDimitry Andric case BuiltinType::Float: 189*06c3fb27SDimitry Andric case BuiltinType::Double: 190*06c3fb27SDimitry Andric return true; 191*06c3fb27SDimitry Andric default: 192*06c3fb27SDimitry Andric return false; 193*06c3fb27SDimitry Andric } 194*06c3fb27SDimitry Andric 195*06c3fb27SDimitry Andric return false; 196*06c3fb27SDimitry Andric } 197*06c3fb27SDimitry Andric 198*06c3fb27SDimitry Andric QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { 199*06c3fb27SDimitry Andric const RecordType *RT = Ty->getAs<RecordType>(); 200*06c3fb27SDimitry Andric 201*06c3fb27SDimitry Andric if (RT && RT->isStructureOrClassType()) { 202*06c3fb27SDimitry Andric const RecordDecl *RD = RT->getDecl(); 203*06c3fb27SDimitry Andric QualType Found; 204*06c3fb27SDimitry Andric 205*06c3fb27SDimitry Andric // If this is a C++ record, check the bases first. 206*06c3fb27SDimitry Andric if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 207*06c3fb27SDimitry Andric if (CXXRD->hasDefinition()) 208*06c3fb27SDimitry Andric for (const auto &I : CXXRD->bases()) { 209*06c3fb27SDimitry Andric QualType Base = I.getType(); 210*06c3fb27SDimitry Andric 211*06c3fb27SDimitry Andric // Empty bases don't affect things either way. 212*06c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Base, true)) 213*06c3fb27SDimitry Andric continue; 214*06c3fb27SDimitry Andric 215*06c3fb27SDimitry Andric if (!Found.isNull()) 216*06c3fb27SDimitry Andric return Ty; 217*06c3fb27SDimitry Andric Found = GetSingleElementType(Base); 218*06c3fb27SDimitry Andric } 219*06c3fb27SDimitry Andric 220*06c3fb27SDimitry Andric // Check the fields. 221*06c3fb27SDimitry Andric for (const auto *FD : RD->fields()) { 222*06c3fb27SDimitry Andric // Unlike isSingleElementStruct(), empty structure and array fields 223*06c3fb27SDimitry Andric // do count. So do anonymous bitfields that aren't zero-sized. 224*06c3fb27SDimitry Andric 225*06c3fb27SDimitry Andric // Like isSingleElementStruct(), ignore C++20 empty data members. 226*06c3fb27SDimitry Andric if (FD->hasAttr<NoUniqueAddressAttr>() && 227*06c3fb27SDimitry Andric isEmptyRecord(getContext(), FD->getType(), true)) 228*06c3fb27SDimitry Andric continue; 229*06c3fb27SDimitry Andric 230*06c3fb27SDimitry Andric // Unlike isSingleElementStruct(), arrays do not count. 231*06c3fb27SDimitry Andric // Nested structures still do though. 232*06c3fb27SDimitry Andric if (!Found.isNull()) 233*06c3fb27SDimitry Andric return Ty; 234*06c3fb27SDimitry Andric Found = GetSingleElementType(FD->getType()); 235*06c3fb27SDimitry Andric } 236*06c3fb27SDimitry Andric 237*06c3fb27SDimitry Andric // Unlike isSingleElementStruct(), trailing padding is allowed. 238*06c3fb27SDimitry Andric // An 8-byte aligned struct s { float f; } is passed as a double. 239*06c3fb27SDimitry Andric if (!Found.isNull()) 240*06c3fb27SDimitry Andric return Found; 241*06c3fb27SDimitry Andric } 242*06c3fb27SDimitry Andric 243*06c3fb27SDimitry Andric return Ty; 244*06c3fb27SDimitry Andric } 245*06c3fb27SDimitry Andric 246*06c3fb27SDimitry Andric Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 247*06c3fb27SDimitry Andric QualType Ty) const { 248*06c3fb27SDimitry Andric // Assume that va_list type is correct; should be pointer to LLVM type: 249*06c3fb27SDimitry Andric // struct { 250*06c3fb27SDimitry Andric // i64 __gpr; 251*06c3fb27SDimitry Andric // i64 __fpr; 252*06c3fb27SDimitry Andric // i8 *__overflow_arg_area; 253*06c3fb27SDimitry Andric // i8 *__reg_save_area; 254*06c3fb27SDimitry Andric // }; 255*06c3fb27SDimitry Andric 256*06c3fb27SDimitry Andric // Every non-vector argument occupies 8 bytes and is passed by preference 257*06c3fb27SDimitry Andric // in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are 258*06c3fb27SDimitry Andric // always passed on the stack. 259*06c3fb27SDimitry Andric const SystemZTargetCodeGenInfo &SZCGI = 260*06c3fb27SDimitry Andric static_cast<const SystemZTargetCodeGenInfo &>( 261*06c3fb27SDimitry Andric CGT.getCGM().getTargetCodeGenInfo()); 262*06c3fb27SDimitry Andric Ty = getContext().getCanonicalType(Ty); 263*06c3fb27SDimitry Andric auto TyInfo = getContext().getTypeInfoInChars(Ty); 264*06c3fb27SDimitry Andric llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty); 265*06c3fb27SDimitry Andric llvm::Type *DirectTy = ArgTy; 266*06c3fb27SDimitry Andric ABIArgInfo AI = classifyArgumentType(Ty); 267*06c3fb27SDimitry Andric bool IsIndirect = AI.isIndirect(); 268*06c3fb27SDimitry Andric bool InFPRs = false; 269*06c3fb27SDimitry Andric bool IsVector = false; 270*06c3fb27SDimitry Andric CharUnits UnpaddedSize; 271*06c3fb27SDimitry Andric CharUnits DirectAlign; 272*06c3fb27SDimitry Andric SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(), 273*06c3fb27SDimitry Andric /*IsParam*/true); 274*06c3fb27SDimitry Andric if (IsIndirect) { 275*06c3fb27SDimitry Andric DirectTy = llvm::PointerType::getUnqual(DirectTy); 276*06c3fb27SDimitry Andric UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8); 277*06c3fb27SDimitry Andric } else { 278*06c3fb27SDimitry Andric if (AI.getCoerceToType()) 279*06c3fb27SDimitry Andric ArgTy = AI.getCoerceToType(); 280*06c3fb27SDimitry Andric InFPRs = (!IsSoftFloatABI && (ArgTy->isFloatTy() || ArgTy->isDoubleTy())); 281*06c3fb27SDimitry Andric IsVector = ArgTy->isVectorTy(); 282*06c3fb27SDimitry Andric UnpaddedSize = TyInfo.Width; 283*06c3fb27SDimitry Andric DirectAlign = TyInfo.Align; 284*06c3fb27SDimitry Andric } 285*06c3fb27SDimitry Andric CharUnits PaddedSize = CharUnits::fromQuantity(8); 286*06c3fb27SDimitry Andric if (IsVector && UnpaddedSize > PaddedSize) 287*06c3fb27SDimitry Andric PaddedSize = CharUnits::fromQuantity(16); 288*06c3fb27SDimitry Andric assert((UnpaddedSize <= PaddedSize) && "Invalid argument size."); 289*06c3fb27SDimitry Andric 290*06c3fb27SDimitry Andric CharUnits Padding = (PaddedSize - UnpaddedSize); 291*06c3fb27SDimitry Andric 292*06c3fb27SDimitry Andric llvm::Type *IndexTy = CGF.Int64Ty; 293*06c3fb27SDimitry Andric llvm::Value *PaddedSizeV = 294*06c3fb27SDimitry Andric llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity()); 295*06c3fb27SDimitry Andric 296*06c3fb27SDimitry Andric if (IsVector) { 297*06c3fb27SDimitry Andric // Work out the address of a vector argument on the stack. 298*06c3fb27SDimitry Andric // Vector arguments are always passed in the high bits of a 299*06c3fb27SDimitry Andric // single (8 byte) or double (16 byte) stack slot. 300*06c3fb27SDimitry Andric Address OverflowArgAreaPtr = 301*06c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr"); 302*06c3fb27SDimitry Andric Address OverflowArgArea = 303*06c3fb27SDimitry Andric Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), 304*06c3fb27SDimitry Andric CGF.Int8Ty, TyInfo.Align); 305*06c3fb27SDimitry Andric Address MemAddr = OverflowArgArea.withElementType(DirectTy); 306*06c3fb27SDimitry Andric 307*06c3fb27SDimitry Andric // Update overflow_arg_area_ptr pointer 308*06c3fb27SDimitry Andric llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( 309*06c3fb27SDimitry Andric OverflowArgArea.getElementType(), OverflowArgArea.getPointer(), 310*06c3fb27SDimitry Andric PaddedSizeV, "overflow_arg_area"); 311*06c3fb27SDimitry Andric CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); 312*06c3fb27SDimitry Andric 313*06c3fb27SDimitry Andric return MemAddr; 314*06c3fb27SDimitry Andric } 315*06c3fb27SDimitry Andric 316*06c3fb27SDimitry Andric assert(PaddedSize.getQuantity() == 8); 317*06c3fb27SDimitry Andric 318*06c3fb27SDimitry Andric unsigned MaxRegs, RegCountField, RegSaveIndex; 319*06c3fb27SDimitry Andric CharUnits RegPadding; 320*06c3fb27SDimitry Andric if (InFPRs) { 321*06c3fb27SDimitry Andric MaxRegs = 4; // Maximum of 4 FPR arguments 322*06c3fb27SDimitry Andric RegCountField = 1; // __fpr 323*06c3fb27SDimitry Andric RegSaveIndex = 16; // save offset for f0 324*06c3fb27SDimitry Andric RegPadding = CharUnits(); // floats are passed in the high bits of an FPR 325*06c3fb27SDimitry Andric } else { 326*06c3fb27SDimitry Andric MaxRegs = 5; // Maximum of 5 GPR arguments 327*06c3fb27SDimitry Andric RegCountField = 0; // __gpr 328*06c3fb27SDimitry Andric RegSaveIndex = 2; // save offset for r2 329*06c3fb27SDimitry Andric RegPadding = Padding; // values are passed in the low bits of a GPR 330*06c3fb27SDimitry Andric } 331*06c3fb27SDimitry Andric 332*06c3fb27SDimitry Andric Address RegCountPtr = 333*06c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr"); 334*06c3fb27SDimitry Andric llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count"); 335*06c3fb27SDimitry Andric llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs); 336*06c3fb27SDimitry Andric llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV, 337*06c3fb27SDimitry Andric "fits_in_regs"); 338*06c3fb27SDimitry Andric 339*06c3fb27SDimitry Andric llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); 340*06c3fb27SDimitry Andric llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem"); 341*06c3fb27SDimitry Andric llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); 342*06c3fb27SDimitry Andric CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock); 343*06c3fb27SDimitry Andric 344*06c3fb27SDimitry Andric // Emit code to load the value if it was passed in registers. 345*06c3fb27SDimitry Andric CGF.EmitBlock(InRegBlock); 346*06c3fb27SDimitry Andric 347*06c3fb27SDimitry Andric // Work out the address of an argument register. 348*06c3fb27SDimitry Andric llvm::Value *ScaledRegCount = 349*06c3fb27SDimitry Andric CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count"); 350*06c3fb27SDimitry Andric llvm::Value *RegBase = 351*06c3fb27SDimitry Andric llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity() 352*06c3fb27SDimitry Andric + RegPadding.getQuantity()); 353*06c3fb27SDimitry Andric llvm::Value *RegOffset = 354*06c3fb27SDimitry Andric CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset"); 355*06c3fb27SDimitry Andric Address RegSaveAreaPtr = 356*06c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr"); 357*06c3fb27SDimitry Andric llvm::Value *RegSaveArea = 358*06c3fb27SDimitry Andric CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area"); 359*06c3fb27SDimitry Andric Address RawRegAddr( 360*06c3fb27SDimitry Andric CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset, "raw_reg_addr"), 361*06c3fb27SDimitry Andric CGF.Int8Ty, PaddedSize); 362*06c3fb27SDimitry Andric Address RegAddr = RawRegAddr.withElementType(DirectTy); 363*06c3fb27SDimitry Andric 364*06c3fb27SDimitry Andric // Update the register count 365*06c3fb27SDimitry Andric llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1); 366*06c3fb27SDimitry Andric llvm::Value *NewRegCount = 367*06c3fb27SDimitry Andric CGF.Builder.CreateAdd(RegCount, One, "reg_count"); 368*06c3fb27SDimitry Andric CGF.Builder.CreateStore(NewRegCount, RegCountPtr); 369*06c3fb27SDimitry Andric CGF.EmitBranch(ContBlock); 370*06c3fb27SDimitry Andric 371*06c3fb27SDimitry Andric // Emit code to load the value if it was passed in memory. 372*06c3fb27SDimitry Andric CGF.EmitBlock(InMemBlock); 373*06c3fb27SDimitry Andric 374*06c3fb27SDimitry Andric // Work out the address of a stack argument. 375*06c3fb27SDimitry Andric Address OverflowArgAreaPtr = 376*06c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr"); 377*06c3fb27SDimitry Andric Address OverflowArgArea = 378*06c3fb27SDimitry Andric Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), 379*06c3fb27SDimitry Andric CGF.Int8Ty, PaddedSize); 380*06c3fb27SDimitry Andric Address RawMemAddr = 381*06c3fb27SDimitry Andric CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr"); 382*06c3fb27SDimitry Andric Address MemAddr = RawMemAddr.withElementType(DirectTy); 383*06c3fb27SDimitry Andric 384*06c3fb27SDimitry Andric // Update overflow_arg_area_ptr pointer 385*06c3fb27SDimitry Andric llvm::Value *NewOverflowArgArea = 386*06c3fb27SDimitry Andric CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), 387*06c3fb27SDimitry Andric OverflowArgArea.getPointer(), PaddedSizeV, 388*06c3fb27SDimitry Andric "overflow_arg_area"); 389*06c3fb27SDimitry Andric CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); 390*06c3fb27SDimitry Andric CGF.EmitBranch(ContBlock); 391*06c3fb27SDimitry Andric 392*06c3fb27SDimitry Andric // Return the appropriate result. 393*06c3fb27SDimitry Andric CGF.EmitBlock(ContBlock); 394*06c3fb27SDimitry Andric Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock, 395*06c3fb27SDimitry Andric "va_arg.addr"); 396*06c3fb27SDimitry Andric 397*06c3fb27SDimitry Andric if (IsIndirect) 398*06c3fb27SDimitry Andric ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"), ArgTy, 399*06c3fb27SDimitry Andric TyInfo.Align); 400*06c3fb27SDimitry Andric 401*06c3fb27SDimitry Andric return ResAddr; 402*06c3fb27SDimitry Andric } 403*06c3fb27SDimitry Andric 404*06c3fb27SDimitry Andric ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const { 405*06c3fb27SDimitry Andric if (RetTy->isVoidType()) 406*06c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 407*06c3fb27SDimitry Andric if (isVectorArgumentType(RetTy)) 408*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 409*06c3fb27SDimitry Andric if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64) 410*06c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 411*06c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 412*06c3fb27SDimitry Andric : ABIArgInfo::getDirect()); 413*06c3fb27SDimitry Andric } 414*06c3fb27SDimitry Andric 415*06c3fb27SDimitry Andric ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { 416*06c3fb27SDimitry Andric // Handle the generic C++ ABI. 417*06c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 418*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 419*06c3fb27SDimitry Andric 420*06c3fb27SDimitry Andric // Integers and enums are extended to full register width. 421*06c3fb27SDimitry Andric if (isPromotableIntegerTypeForABI(Ty)) 422*06c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 423*06c3fb27SDimitry Andric 424*06c3fb27SDimitry Andric // Handle vector types and vector-like structure types. Note that 425*06c3fb27SDimitry Andric // as opposed to float-like structure types, we do not allow any 426*06c3fb27SDimitry Andric // padding for vector-like structures, so verify the sizes match. 427*06c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 428*06c3fb27SDimitry Andric QualType SingleElementTy = GetSingleElementType(Ty); 429*06c3fb27SDimitry Andric if (isVectorArgumentType(SingleElementTy) && 430*06c3fb27SDimitry Andric getContext().getTypeSize(SingleElementTy) == Size) 431*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy)); 432*06c3fb27SDimitry Andric 433*06c3fb27SDimitry Andric // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly. 434*06c3fb27SDimitry Andric if (Size != 8 && Size != 16 && Size != 32 && Size != 64) 435*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 436*06c3fb27SDimitry Andric 437*06c3fb27SDimitry Andric // Handle small structures. 438*06c3fb27SDimitry Andric if (const RecordType *RT = Ty->getAs<RecordType>()) { 439*06c3fb27SDimitry Andric // Structures with flexible arrays have variable length, so really 440*06c3fb27SDimitry Andric // fail the size test above. 441*06c3fb27SDimitry Andric const RecordDecl *RD = RT->getDecl(); 442*06c3fb27SDimitry Andric if (RD->hasFlexibleArrayMember()) 443*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 444*06c3fb27SDimitry Andric 445*06c3fb27SDimitry Andric // The structure is passed as an unextended integer, a float, or a double. 446*06c3fb27SDimitry Andric llvm::Type *PassTy; 447*06c3fb27SDimitry Andric if (isFPArgumentType(SingleElementTy)) { 448*06c3fb27SDimitry Andric assert(Size == 32 || Size == 64); 449*06c3fb27SDimitry Andric if (Size == 32) 450*06c3fb27SDimitry Andric PassTy = llvm::Type::getFloatTy(getVMContext()); 451*06c3fb27SDimitry Andric else 452*06c3fb27SDimitry Andric PassTy = llvm::Type::getDoubleTy(getVMContext()); 453*06c3fb27SDimitry Andric } else 454*06c3fb27SDimitry Andric PassTy = llvm::IntegerType::get(getVMContext(), Size); 455*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(PassTy); 456*06c3fb27SDimitry Andric } 457*06c3fb27SDimitry Andric 458*06c3fb27SDimitry Andric // Non-structure compounds are passed indirectly. 459*06c3fb27SDimitry Andric if (isCompoundType(Ty)) 460*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 461*06c3fb27SDimitry Andric 462*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(nullptr); 463*06c3fb27SDimitry Andric } 464*06c3fb27SDimitry Andric 465*06c3fb27SDimitry Andric void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const { 466*06c3fb27SDimitry Andric const SystemZTargetCodeGenInfo &SZCGI = 467*06c3fb27SDimitry Andric static_cast<const SystemZTargetCodeGenInfo &>( 468*06c3fb27SDimitry Andric CGT.getCGM().getTargetCodeGenInfo()); 469*06c3fb27SDimitry Andric if (!getCXXABI().classifyReturnType(FI)) 470*06c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 471*06c3fb27SDimitry Andric unsigned Idx = 0; 472*06c3fb27SDimitry Andric for (auto &I : FI.arguments()) { 473*06c3fb27SDimitry Andric I.info = classifyArgumentType(I.type); 474*06c3fb27SDimitry Andric if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs()) 475*06c3fb27SDimitry Andric // Check if a vararg vector argument is passed, in which case the 476*06c3fb27SDimitry Andric // vector ABI becomes visible as the va_list could be passed on to 477*06c3fb27SDimitry Andric // other functions. 478*06c3fb27SDimitry Andric SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(), 479*06c3fb27SDimitry Andric /*IsParam*/true); 480*06c3fb27SDimitry Andric } 481*06c3fb27SDimitry Andric } 482*06c3fb27SDimitry Andric 483*06c3fb27SDimitry Andric bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, 484*06c3fb27SDimitry Andric bool IsParam) const { 485*06c3fb27SDimitry Andric if (!SeenTypes.insert(Ty).second) 486*06c3fb27SDimitry Andric return false; 487*06c3fb27SDimitry Andric 488*06c3fb27SDimitry Andric if (IsParam) { 489*06c3fb27SDimitry Andric // A narrow (<16 bytes) vector will as a parameter also expose the ABI as 490*06c3fb27SDimitry Andric // it will be passed in a vector register. A wide (>16 bytes) vector will 491*06c3fb27SDimitry Andric // be passed via "hidden" pointer where any extra alignment is not 492*06c3fb27SDimitry Andric // required (per GCC). 493*06c3fb27SDimitry Andric const Type *SingleEltTy = getABIInfo<SystemZABIInfo>() 494*06c3fb27SDimitry Andric .GetSingleElementType(QualType(Ty, 0)) 495*06c3fb27SDimitry Andric .getTypePtr(); 496*06c3fb27SDimitry Andric bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() && 497*06c3fb27SDimitry Andric Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty); 498*06c3fb27SDimitry Andric if (Ty->isVectorType() || SingleVecEltStruct) 499*06c3fb27SDimitry Andric return Ctx.getTypeSize(Ty) / 8 <= 16; 500*06c3fb27SDimitry Andric } 501*06c3fb27SDimitry Andric 502*06c3fb27SDimitry Andric // Assume pointers are dereferenced. 503*06c3fb27SDimitry Andric while (Ty->isPointerType() || Ty->isArrayType()) 504*06c3fb27SDimitry Andric Ty = Ty->getPointeeOrArrayElementType(); 505*06c3fb27SDimitry Andric 506*06c3fb27SDimitry Andric // Vectors >= 16 bytes expose the ABI through alignment requirements. 507*06c3fb27SDimitry Andric if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16) 508*06c3fb27SDimitry Andric return true; 509*06c3fb27SDimitry Andric 510*06c3fb27SDimitry Andric if (const auto *RecordTy = Ty->getAs<RecordType>()) { 511*06c3fb27SDimitry Andric const RecordDecl *RD = RecordTy->getDecl(); 512*06c3fb27SDimitry Andric if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 513*06c3fb27SDimitry Andric if (CXXRD->hasDefinition()) 514*06c3fb27SDimitry Andric for (const auto &I : CXXRD->bases()) 515*06c3fb27SDimitry Andric if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false)) 516*06c3fb27SDimitry Andric return true; 517*06c3fb27SDimitry Andric for (const auto *FD : RD->fields()) 518*06c3fb27SDimitry Andric if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false)) 519*06c3fb27SDimitry Andric return true; 520*06c3fb27SDimitry Andric } 521*06c3fb27SDimitry Andric 522*06c3fb27SDimitry Andric if (const auto *FT = Ty->getAs<FunctionType>()) 523*06c3fb27SDimitry Andric if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true)) 524*06c3fb27SDimitry Andric return true; 525*06c3fb27SDimitry Andric if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>()) 526*06c3fb27SDimitry Andric for (const auto &ParamType : Proto->getParamTypes()) 527*06c3fb27SDimitry Andric if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true)) 528*06c3fb27SDimitry Andric return true; 529*06c3fb27SDimitry Andric 530*06c3fb27SDimitry Andric return false; 531*06c3fb27SDimitry Andric } 532*06c3fb27SDimitry Andric 533*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 534*06c3fb27SDimitry Andric CodeGen::createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector, 535*06c3fb27SDimitry Andric bool SoftFloatABI) { 536*06c3fb27SDimitry Andric return std::make_unique<SystemZTargetCodeGenInfo>(CGM.getTypes(), HasVector, 537*06c3fb27SDimitry Andric SoftFloatABI); 538*06c3fb27SDimitry Andric } 539