1992cb984SSergei Barannikov //===- SystemZ.cpp --------------------------------------------------------===// 2992cb984SSergei Barannikov // 3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information. 5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6992cb984SSergei Barannikov // 7992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 8992cb984SSergei Barannikov 9992cb984SSergei Barannikov #include "ABIInfoImpl.h" 10992cb984SSergei Barannikov #include "TargetInfo.h" 11992cb984SSergei Barannikov #include "clang/Basic/Builtins.h" 12992cb984SSergei Barannikov #include "llvm/IR/IntrinsicsS390.h" 13992cb984SSergei Barannikov 14992cb984SSergei Barannikov using namespace clang; 15992cb984SSergei Barannikov using namespace clang::CodeGen; 16992cb984SSergei Barannikov 17992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 18992cb984SSergei Barannikov // SystemZ ABI Implementation 19992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 20992cb984SSergei Barannikov 21992cb984SSergei Barannikov namespace { 22992cb984SSergei Barannikov 23992cb984SSergei Barannikov class SystemZABIInfo : public ABIInfo { 24992cb984SSergei Barannikov bool HasVector; 25992cb984SSergei Barannikov bool IsSoftFloatABI; 26992cb984SSergei Barannikov 27992cb984SSergei Barannikov public: 28992cb984SSergei Barannikov SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF) 29992cb984SSergei Barannikov : ABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {} 30992cb984SSergei Barannikov 31992cb984SSergei Barannikov bool isPromotableIntegerTypeForABI(QualType Ty) const; 32992cb984SSergei Barannikov bool isCompoundType(QualType Ty) const; 33992cb984SSergei Barannikov bool isVectorArgumentType(QualType Ty) const; 34992cb984SSergei Barannikov bool isFPArgumentType(QualType Ty) const; 35992cb984SSergei Barannikov QualType GetSingleElementType(QualType Ty) const; 36992cb984SSergei Barannikov 37992cb984SSergei Barannikov ABIArgInfo classifyReturnType(QualType RetTy) const; 38992cb984SSergei Barannikov ABIArgInfo classifyArgumentType(QualType ArgTy) const; 39992cb984SSergei Barannikov 40992cb984SSergei Barannikov void computeInfo(CGFunctionInfo &FI) const override; 416d973b45SMariya Podchishchaeva RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 426d973b45SMariya Podchishchaeva AggValueSlot Slot) const override; 43992cb984SSergei Barannikov }; 44992cb984SSergei Barannikov 45992cb984SSergei Barannikov class SystemZTargetCodeGenInfo : public TargetCodeGenInfo { 46992cb984SSergei Barannikov ASTContext &Ctx; 47992cb984SSergei Barannikov 48992cb984SSergei Barannikov // These are used for speeding up the search for a visible vector ABI. 49992cb984SSergei Barannikov mutable bool HasVisibleVecABIFlag = false; 50992cb984SSergei Barannikov mutable std::set<const Type *> SeenTypes; 51992cb984SSergei Barannikov 52992cb984SSergei Barannikov // Returns true (the first time) if Ty is, or is found to include, a vector 53992cb984SSergei Barannikov // type that exposes the vector ABI. This is any vector >=16 bytes which 54992cb984SSergei Barannikov // with vector support are aligned to only 8 bytes. When IsParam is true, 55992cb984SSergei Barannikov // the type belongs to a value as passed between functions. If it is a 56992cb984SSergei Barannikov // vector <=16 bytes it will be passed in a vector register (if supported). 57992cb984SSergei Barannikov bool isVectorTypeBased(const Type *Ty, bool IsParam) const; 58992cb984SSergei Barannikov 59992cb984SSergei Barannikov public: 60992cb984SSergei Barannikov SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI) 61992cb984SSergei Barannikov : TargetCodeGenInfo( 62992cb984SSergei Barannikov std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)), 63992cb984SSergei Barannikov Ctx(CGT.getContext()) { 64992cb984SSergei Barannikov SwiftInfo = 65992cb984SSergei Barannikov std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false); 66992cb984SSergei Barannikov } 67992cb984SSergei Barannikov 68992cb984SSergei Barannikov // The vector ABI is different when the vector facility is present and when 69992cb984SSergei Barannikov // a module e.g. defines an externally visible vector variable, a flag 70992cb984SSergei Barannikov // indicating a visible vector ABI is added. Eventually this will result in 71992cb984SSergei Barannikov // a GNU attribute indicating the vector ABI of the module. Ty is the type 72992cb984SSergei Barannikov // of a variable or function parameter that is globally visible. 73992cb984SSergei Barannikov void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M, 74992cb984SSergei Barannikov bool IsParam) const { 75992cb984SSergei Barannikov if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) { 76992cb984SSergei Barannikov M.getModule().addModuleFlag(llvm::Module::Warning, 77992cb984SSergei Barannikov "s390x-visible-vector-ABI", 1); 78992cb984SSergei Barannikov HasVisibleVecABIFlag = true; 79992cb984SSergei Barannikov } 80992cb984SSergei Barannikov } 81992cb984SSergei Barannikov 82992cb984SSergei Barannikov void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 83992cb984SSergei Barannikov CodeGen::CodeGenModule &M) const override { 84992cb984SSergei Barannikov if (!D) 85992cb984SSergei Barannikov return; 86992cb984SSergei Barannikov 87992cb984SSergei Barannikov // Check if the vector ABI becomes visible by an externally visible 88992cb984SSergei Barannikov // variable or function. 89992cb984SSergei Barannikov if (const auto *VD = dyn_cast<VarDecl>(D)) { 90992cb984SSergei Barannikov if (VD->isExternallyVisible()) 91992cb984SSergei Barannikov handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M, 92992cb984SSergei Barannikov /*IsParam*/false); 93992cb984SSergei Barannikov } 94992cb984SSergei Barannikov else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 95992cb984SSergei Barannikov if (FD->isExternallyVisible()) 96992cb984SSergei Barannikov handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M, 97992cb984SSergei Barannikov /*IsParam*/false); 98992cb984SSergei Barannikov } 99992cb984SSergei Barannikov } 100992cb984SSergei Barannikov 101992cb984SSergei Barannikov llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID, 102992cb984SSergei Barannikov CGBuilderTy &Builder, 103992cb984SSergei Barannikov CodeGenModule &CGM) const override { 104992cb984SSergei Barannikov assert(V->getType()->isFloatingPointTy() && "V should have an FP type."); 105992cb984SSergei Barannikov // Only use TDC in constrained FP mode. 106992cb984SSergei Barannikov if (!Builder.getIsFPConstrained()) 107992cb984SSergei Barannikov return nullptr; 108992cb984SSergei Barannikov 109992cb984SSergei Barannikov llvm::Type *Ty = V->getType(); 110992cb984SSergei Barannikov if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) { 111992cb984SSergei Barannikov llvm::Module &M = CGM.getModule(); 112992cb984SSergei Barannikov auto &Ctx = M.getContext(); 113*fa789dffSRahul Joshi llvm::Function *TDCFunc = llvm::Intrinsic::getOrInsertDeclaration( 114*fa789dffSRahul Joshi &M, llvm::Intrinsic::s390_tdc, Ty); 115992cb984SSergei Barannikov unsigned TDCBits = 0; 116992cb984SSergei Barannikov switch (BuiltinID) { 117992cb984SSergei Barannikov case Builtin::BI__builtin_isnan: 118992cb984SSergei Barannikov TDCBits = 0xf; 119992cb984SSergei Barannikov break; 120992cb984SSergei Barannikov case Builtin::BIfinite: 121992cb984SSergei Barannikov case Builtin::BI__finite: 122992cb984SSergei Barannikov case Builtin::BIfinitef: 123992cb984SSergei Barannikov case Builtin::BI__finitef: 124992cb984SSergei Barannikov case Builtin::BIfinitel: 125992cb984SSergei Barannikov case Builtin::BI__finitel: 126992cb984SSergei Barannikov case Builtin::BI__builtin_isfinite: 127992cb984SSergei Barannikov TDCBits = 0xfc0; 128992cb984SSergei Barannikov break; 129992cb984SSergei Barannikov case Builtin::BI__builtin_isinf: 130992cb984SSergei Barannikov TDCBits = 0x30; 131992cb984SSergei Barannikov break; 132992cb984SSergei Barannikov default: 133992cb984SSergei Barannikov break; 134992cb984SSergei Barannikov } 135992cb984SSergei Barannikov if (TDCBits) 136992cb984SSergei Barannikov return Builder.CreateCall( 137992cb984SSergei Barannikov TDCFunc, 138992cb984SSergei Barannikov {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)}); 139992cb984SSergei Barannikov } 140992cb984SSergei Barannikov return nullptr; 141992cb984SSergei Barannikov } 142992cb984SSergei Barannikov }; 143992cb984SSergei Barannikov } 144992cb984SSergei Barannikov 145992cb984SSergei Barannikov bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const { 146992cb984SSergei Barannikov // Treat an enum type as its underlying type. 147992cb984SSergei Barannikov if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 148992cb984SSergei Barannikov Ty = EnumTy->getDecl()->getIntegerType(); 149992cb984SSergei Barannikov 150992cb984SSergei Barannikov // Promotable integer types are required to be promoted by the ABI. 151992cb984SSergei Barannikov if (ABIInfo::isPromotableIntegerTypeForABI(Ty)) 152992cb984SSergei Barannikov return true; 153992cb984SSergei Barannikov 154992cb984SSergei Barannikov if (const auto *EIT = Ty->getAs<BitIntType>()) 155992cb984SSergei Barannikov if (EIT->getNumBits() < 64) 156992cb984SSergei Barannikov return true; 157992cb984SSergei Barannikov 158992cb984SSergei Barannikov // 32-bit values must also be promoted. 159992cb984SSergei Barannikov if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) 160992cb984SSergei Barannikov switch (BT->getKind()) { 161992cb984SSergei Barannikov case BuiltinType::Int: 162992cb984SSergei Barannikov case BuiltinType::UInt: 163992cb984SSergei Barannikov return true; 164992cb984SSergei Barannikov default: 165992cb984SSergei Barannikov return false; 166992cb984SSergei Barannikov } 167992cb984SSergei Barannikov return false; 168992cb984SSergei Barannikov } 169992cb984SSergei Barannikov 170992cb984SSergei Barannikov bool SystemZABIInfo::isCompoundType(QualType Ty) const { 171992cb984SSergei Barannikov return (Ty->isAnyComplexType() || 172992cb984SSergei Barannikov Ty->isVectorType() || 173992cb984SSergei Barannikov isAggregateTypeForABI(Ty)); 174992cb984SSergei Barannikov } 175992cb984SSergei Barannikov 176992cb984SSergei Barannikov bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const { 177992cb984SSergei Barannikov return (HasVector && 178992cb984SSergei Barannikov Ty->isVectorType() && 179992cb984SSergei Barannikov getContext().getTypeSize(Ty) <= 128); 180992cb984SSergei Barannikov } 181992cb984SSergei Barannikov 182992cb984SSergei Barannikov bool SystemZABIInfo::isFPArgumentType(QualType Ty) const { 183992cb984SSergei Barannikov if (IsSoftFloatABI) 184992cb984SSergei Barannikov return false; 185992cb984SSergei Barannikov 186992cb984SSergei Barannikov if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) 187992cb984SSergei Barannikov switch (BT->getKind()) { 188992cb984SSergei Barannikov case BuiltinType::Float: 189992cb984SSergei Barannikov case BuiltinType::Double: 190992cb984SSergei Barannikov return true; 191992cb984SSergei Barannikov default: 192992cb984SSergei Barannikov return false; 193992cb984SSergei Barannikov } 194992cb984SSergei Barannikov 195992cb984SSergei Barannikov return false; 196992cb984SSergei Barannikov } 197992cb984SSergei Barannikov 198992cb984SSergei Barannikov QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { 199992cb984SSergei Barannikov const RecordType *RT = Ty->getAs<RecordType>(); 200992cb984SSergei Barannikov 201992cb984SSergei Barannikov if (RT && RT->isStructureOrClassType()) { 202992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 203992cb984SSergei Barannikov QualType Found; 204992cb984SSergei Barannikov 205992cb984SSergei Barannikov // If this is a C++ record, check the bases first. 206992cb984SSergei Barannikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 207992cb984SSergei Barannikov if (CXXRD->hasDefinition()) 208992cb984SSergei Barannikov for (const auto &I : CXXRD->bases()) { 209992cb984SSergei Barannikov QualType Base = I.getType(); 210992cb984SSergei Barannikov 211992cb984SSergei Barannikov // Empty bases don't affect things either way. 212992cb984SSergei Barannikov if (isEmptyRecord(getContext(), Base, true)) 213992cb984SSergei Barannikov continue; 214992cb984SSergei Barannikov 215992cb984SSergei Barannikov if (!Found.isNull()) 216992cb984SSergei Barannikov return Ty; 217992cb984SSergei Barannikov Found = GetSingleElementType(Base); 218992cb984SSergei Barannikov } 219992cb984SSergei Barannikov 220992cb984SSergei Barannikov // Check the fields. 221992cb984SSergei Barannikov for (const auto *FD : RD->fields()) { 222992cb984SSergei Barannikov // Unlike isSingleElementStruct(), empty structure and array fields 223992cb984SSergei Barannikov // do count. So do anonymous bitfields that aren't zero-sized. 224992cb984SSergei Barannikov 225992cb984SSergei Barannikov // Like isSingleElementStruct(), ignore C++20 empty data members. 226992cb984SSergei Barannikov if (FD->hasAttr<NoUniqueAddressAttr>() && 227992cb984SSergei Barannikov isEmptyRecord(getContext(), FD->getType(), true)) 228992cb984SSergei Barannikov continue; 229992cb984SSergei Barannikov 230992cb984SSergei Barannikov // Unlike isSingleElementStruct(), arrays do not count. 231992cb984SSergei Barannikov // Nested structures still do though. 232992cb984SSergei Barannikov if (!Found.isNull()) 233992cb984SSergei Barannikov return Ty; 234992cb984SSergei Barannikov Found = GetSingleElementType(FD->getType()); 235992cb984SSergei Barannikov } 236992cb984SSergei Barannikov 237992cb984SSergei Barannikov // Unlike isSingleElementStruct(), trailing padding is allowed. 238992cb984SSergei Barannikov // An 8-byte aligned struct s { float f; } is passed as a double. 239992cb984SSergei Barannikov if (!Found.isNull()) 240992cb984SSergei Barannikov return Found; 241992cb984SSergei Barannikov } 242992cb984SSergei Barannikov 243992cb984SSergei Barannikov return Ty; 244992cb984SSergei Barannikov } 245992cb984SSergei Barannikov 2466d973b45SMariya Podchishchaeva RValue SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 2476d973b45SMariya Podchishchaeva QualType Ty, AggValueSlot Slot) const { 248992cb984SSergei Barannikov // Assume that va_list type is correct; should be pointer to LLVM type: 249992cb984SSergei Barannikov // struct { 250992cb984SSergei Barannikov // i64 __gpr; 251992cb984SSergei Barannikov // i64 __fpr; 252992cb984SSergei Barannikov // i8 *__overflow_arg_area; 253992cb984SSergei Barannikov // i8 *__reg_save_area; 254992cb984SSergei Barannikov // }; 255992cb984SSergei Barannikov 256992cb984SSergei Barannikov // Every non-vector argument occupies 8 bytes and is passed by preference 257992cb984SSergei Barannikov // in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are 258992cb984SSergei Barannikov // always passed on the stack. 259992cb984SSergei Barannikov const SystemZTargetCodeGenInfo &SZCGI = 260992cb984SSergei Barannikov static_cast<const SystemZTargetCodeGenInfo &>( 261992cb984SSergei Barannikov CGT.getCGM().getTargetCodeGenInfo()); 262992cb984SSergei Barannikov Ty = getContext().getCanonicalType(Ty); 263992cb984SSergei Barannikov auto TyInfo = getContext().getTypeInfoInChars(Ty); 264992cb984SSergei Barannikov llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty); 265992cb984SSergei Barannikov llvm::Type *DirectTy = ArgTy; 266992cb984SSergei Barannikov ABIArgInfo AI = classifyArgumentType(Ty); 267992cb984SSergei Barannikov bool IsIndirect = AI.isIndirect(); 268992cb984SSergei Barannikov bool InFPRs = false; 269992cb984SSergei Barannikov bool IsVector = false; 270992cb984SSergei Barannikov CharUnits UnpaddedSize; 271992cb984SSergei Barannikov CharUnits DirectAlign; 272992cb984SSergei Barannikov SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(), 273992cb984SSergei Barannikov /*IsParam*/true); 274992cb984SSergei Barannikov if (IsIndirect) { 275992cb984SSergei Barannikov DirectTy = llvm::PointerType::getUnqual(DirectTy); 276992cb984SSergei Barannikov UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8); 277992cb984SSergei Barannikov } else { 278992cb984SSergei Barannikov if (AI.getCoerceToType()) 279992cb984SSergei Barannikov ArgTy = AI.getCoerceToType(); 280992cb984SSergei Barannikov InFPRs = (!IsSoftFloatABI && (ArgTy->isFloatTy() || ArgTy->isDoubleTy())); 281992cb984SSergei Barannikov IsVector = ArgTy->isVectorTy(); 282992cb984SSergei Barannikov UnpaddedSize = TyInfo.Width; 283992cb984SSergei Barannikov DirectAlign = TyInfo.Align; 284992cb984SSergei Barannikov } 285992cb984SSergei Barannikov CharUnits PaddedSize = CharUnits::fromQuantity(8); 286992cb984SSergei Barannikov if (IsVector && UnpaddedSize > PaddedSize) 287992cb984SSergei Barannikov PaddedSize = CharUnits::fromQuantity(16); 288992cb984SSergei Barannikov assert((UnpaddedSize <= PaddedSize) && "Invalid argument size."); 289992cb984SSergei Barannikov 290992cb984SSergei Barannikov CharUnits Padding = (PaddedSize - UnpaddedSize); 291992cb984SSergei Barannikov 292992cb984SSergei Barannikov llvm::Type *IndexTy = CGF.Int64Ty; 293992cb984SSergei Barannikov llvm::Value *PaddedSizeV = 294992cb984SSergei Barannikov llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity()); 295992cb984SSergei Barannikov 296992cb984SSergei Barannikov if (IsVector) { 297992cb984SSergei Barannikov // Work out the address of a vector argument on the stack. 298992cb984SSergei Barannikov // Vector arguments are always passed in the high bits of a 299992cb984SSergei Barannikov // single (8 byte) or double (16 byte) stack slot. 300992cb984SSergei Barannikov Address OverflowArgAreaPtr = 301992cb984SSergei Barannikov CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr"); 302992cb984SSergei Barannikov Address OverflowArgArea = 303992cb984SSergei Barannikov Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), 304992cb984SSergei Barannikov CGF.Int8Ty, TyInfo.Align); 30544e63ffeSYoungsuk Kim Address MemAddr = OverflowArgArea.withElementType(DirectTy); 306992cb984SSergei Barannikov 307992cb984SSergei Barannikov // Update overflow_arg_area_ptr pointer 308992cb984SSergei Barannikov llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( 30984780af4SAkira Hatanaka OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), 310992cb984SSergei Barannikov PaddedSizeV, "overflow_arg_area"); 311992cb984SSergei Barannikov CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); 312992cb984SSergei Barannikov 3136d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(MemAddr, Ty), Slot); 314992cb984SSergei Barannikov } 315992cb984SSergei Barannikov 316992cb984SSergei Barannikov assert(PaddedSize.getQuantity() == 8); 317992cb984SSergei Barannikov 318992cb984SSergei Barannikov unsigned MaxRegs, RegCountField, RegSaveIndex; 319992cb984SSergei Barannikov CharUnits RegPadding; 320992cb984SSergei Barannikov if (InFPRs) { 321992cb984SSergei Barannikov MaxRegs = 4; // Maximum of 4 FPR arguments 322992cb984SSergei Barannikov RegCountField = 1; // __fpr 323992cb984SSergei Barannikov RegSaveIndex = 16; // save offset for f0 324992cb984SSergei Barannikov RegPadding = CharUnits(); // floats are passed in the high bits of an FPR 325992cb984SSergei Barannikov } else { 326992cb984SSergei Barannikov MaxRegs = 5; // Maximum of 5 GPR arguments 327992cb984SSergei Barannikov RegCountField = 0; // __gpr 328992cb984SSergei Barannikov RegSaveIndex = 2; // save offset for r2 329992cb984SSergei Barannikov RegPadding = Padding; // values are passed in the low bits of a GPR 330992cb984SSergei Barannikov } 331992cb984SSergei Barannikov 332992cb984SSergei Barannikov Address RegCountPtr = 333992cb984SSergei Barannikov CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr"); 334992cb984SSergei Barannikov llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count"); 335992cb984SSergei Barannikov llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs); 336992cb984SSergei Barannikov llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV, 337992cb984SSergei Barannikov "fits_in_regs"); 338992cb984SSergei Barannikov 339992cb984SSergei Barannikov llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); 340992cb984SSergei Barannikov llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem"); 341992cb984SSergei Barannikov llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); 342992cb984SSergei Barannikov CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock); 343992cb984SSergei Barannikov 344992cb984SSergei Barannikov // Emit code to load the value if it was passed in registers. 345992cb984SSergei Barannikov CGF.EmitBlock(InRegBlock); 346992cb984SSergei Barannikov 347992cb984SSergei Barannikov // Work out the address of an argument register. 348992cb984SSergei Barannikov llvm::Value *ScaledRegCount = 349992cb984SSergei Barannikov CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count"); 350992cb984SSergei Barannikov llvm::Value *RegBase = 351992cb984SSergei Barannikov llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity() 352992cb984SSergei Barannikov + RegPadding.getQuantity()); 353992cb984SSergei Barannikov llvm::Value *RegOffset = 354992cb984SSergei Barannikov CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset"); 355992cb984SSergei Barannikov Address RegSaveAreaPtr = 356992cb984SSergei Barannikov CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr"); 357992cb984SSergei Barannikov llvm::Value *RegSaveArea = 358992cb984SSergei Barannikov CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area"); 359992cb984SSergei Barannikov Address RawRegAddr( 360992cb984SSergei Barannikov CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset, "raw_reg_addr"), 361992cb984SSergei Barannikov CGF.Int8Ty, PaddedSize); 36244e63ffeSYoungsuk Kim Address RegAddr = RawRegAddr.withElementType(DirectTy); 363992cb984SSergei Barannikov 364992cb984SSergei Barannikov // Update the register count 365992cb984SSergei Barannikov llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1); 366992cb984SSergei Barannikov llvm::Value *NewRegCount = 367992cb984SSergei Barannikov CGF.Builder.CreateAdd(RegCount, One, "reg_count"); 368992cb984SSergei Barannikov CGF.Builder.CreateStore(NewRegCount, RegCountPtr); 369992cb984SSergei Barannikov CGF.EmitBranch(ContBlock); 370992cb984SSergei Barannikov 371992cb984SSergei Barannikov // Emit code to load the value if it was passed in memory. 372992cb984SSergei Barannikov CGF.EmitBlock(InMemBlock); 373992cb984SSergei Barannikov 374992cb984SSergei Barannikov // Work out the address of a stack argument. 375992cb984SSergei Barannikov Address OverflowArgAreaPtr = 376992cb984SSergei Barannikov CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr"); 377992cb984SSergei Barannikov Address OverflowArgArea = 378992cb984SSergei Barannikov Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), 379992cb984SSergei Barannikov CGF.Int8Ty, PaddedSize); 380992cb984SSergei Barannikov Address RawMemAddr = 381992cb984SSergei Barannikov CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr"); 38244e63ffeSYoungsuk Kim Address MemAddr = RawMemAddr.withElementType(DirectTy); 383992cb984SSergei Barannikov 384992cb984SSergei Barannikov // Update overflow_arg_area_ptr pointer 38584780af4SAkira Hatanaka llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( 38684780af4SAkira Hatanaka OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), 38784780af4SAkira Hatanaka PaddedSizeV, "overflow_arg_area"); 388992cb984SSergei Barannikov CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); 389992cb984SSergei Barannikov CGF.EmitBranch(ContBlock); 390992cb984SSergei Barannikov 391992cb984SSergei Barannikov // Return the appropriate result. 392992cb984SSergei Barannikov CGF.EmitBlock(ContBlock); 393992cb984SSergei Barannikov Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock, 394992cb984SSergei Barannikov "va_arg.addr"); 395992cb984SSergei Barannikov 396992cb984SSergei Barannikov if (IsIndirect) 397992cb984SSergei Barannikov ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"), ArgTy, 398992cb984SSergei Barannikov TyInfo.Align); 399992cb984SSergei Barannikov 4006d973b45SMariya Podchishchaeva return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(ResAddr, Ty), Slot); 401992cb984SSergei Barannikov } 402992cb984SSergei Barannikov 403992cb984SSergei Barannikov ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const { 404992cb984SSergei Barannikov if (RetTy->isVoidType()) 405992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 406992cb984SSergei Barannikov if (isVectorArgumentType(RetTy)) 407992cb984SSergei Barannikov return ABIArgInfo::getDirect(); 408992cb984SSergei Barannikov if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64) 409992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 410992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 411992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 412992cb984SSergei Barannikov } 413992cb984SSergei Barannikov 414992cb984SSergei Barannikov ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { 4159af3628cSUlrich Weigand // Handle transparent union types. 4169af3628cSUlrich Weigand Ty = useFirstFieldIfTransparentUnion(Ty); 4179af3628cSUlrich Weigand 418992cb984SSergei Barannikov // Handle the generic C++ ABI. 419992cb984SSergei Barannikov if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 420992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 421992cb984SSergei Barannikov 422992cb984SSergei Barannikov // Integers and enums are extended to full register width. 423992cb984SSergei Barannikov if (isPromotableIntegerTypeForABI(Ty)) 4249af3628cSUlrich Weigand return ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)); 425992cb984SSergei Barannikov 426992cb984SSergei Barannikov // Handle vector types and vector-like structure types. Note that 427992cb984SSergei Barannikov // as opposed to float-like structure types, we do not allow any 428992cb984SSergei Barannikov // padding for vector-like structures, so verify the sizes match. 429992cb984SSergei Barannikov uint64_t Size = getContext().getTypeSize(Ty); 430992cb984SSergei Barannikov QualType SingleElementTy = GetSingleElementType(Ty); 431992cb984SSergei Barannikov if (isVectorArgumentType(SingleElementTy) && 432992cb984SSergei Barannikov getContext().getTypeSize(SingleElementTy) == Size) 433992cb984SSergei Barannikov return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy)); 434992cb984SSergei Barannikov 435992cb984SSergei Barannikov // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly. 436992cb984SSergei Barannikov if (Size != 8 && Size != 16 && Size != 32 && Size != 64) 437992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 438992cb984SSergei Barannikov 439992cb984SSergei Barannikov // Handle small structures. 440992cb984SSergei Barannikov if (const RecordType *RT = Ty->getAs<RecordType>()) { 441992cb984SSergei Barannikov // Structures with flexible arrays have variable length, so really 442992cb984SSergei Barannikov // fail the size test above. 443992cb984SSergei Barannikov const RecordDecl *RD = RT->getDecl(); 444992cb984SSergei Barannikov if (RD->hasFlexibleArrayMember()) 445992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 446992cb984SSergei Barannikov 447992cb984SSergei Barannikov // The structure is passed as an unextended integer, a float, or a double. 448992cb984SSergei Barannikov if (isFPArgumentType(SingleElementTy)) { 449992cb984SSergei Barannikov assert(Size == 32 || Size == 64); 45014120227SJonas Paulsson return ABIArgInfo::getDirect( 45114120227SJonas Paulsson Size == 32 ? llvm::Type::getFloatTy(getVMContext()) 45214120227SJonas Paulsson : llvm::Type::getDoubleTy(getVMContext())); 45314120227SJonas Paulsson } else { 45414120227SJonas Paulsson llvm::IntegerType *PassTy = llvm::IntegerType::get(getVMContext(), Size); 45514120227SJonas Paulsson return Size <= 32 ? ABIArgInfo::getNoExtend(PassTy) 45614120227SJonas Paulsson : ABIArgInfo::getDirect(PassTy); 45714120227SJonas Paulsson } 458992cb984SSergei Barannikov } 459992cb984SSergei Barannikov 460992cb984SSergei Barannikov // Non-structure compounds are passed indirectly. 461992cb984SSergei Barannikov if (isCompoundType(Ty)) 462992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 463992cb984SSergei Barannikov 464992cb984SSergei Barannikov return ABIArgInfo::getDirect(nullptr); 465992cb984SSergei Barannikov } 466992cb984SSergei Barannikov 467992cb984SSergei Barannikov void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const { 468992cb984SSergei Barannikov const SystemZTargetCodeGenInfo &SZCGI = 469992cb984SSergei Barannikov static_cast<const SystemZTargetCodeGenInfo &>( 470992cb984SSergei Barannikov CGT.getCGM().getTargetCodeGenInfo()); 471992cb984SSergei Barannikov if (!getCXXABI().classifyReturnType(FI)) 472992cb984SSergei Barannikov FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 473992cb984SSergei Barannikov unsigned Idx = 0; 474992cb984SSergei Barannikov for (auto &I : FI.arguments()) { 475992cb984SSergei Barannikov I.info = classifyArgumentType(I.type); 476992cb984SSergei Barannikov if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs()) 477992cb984SSergei Barannikov // Check if a vararg vector argument is passed, in which case the 478992cb984SSergei Barannikov // vector ABI becomes visible as the va_list could be passed on to 479992cb984SSergei Barannikov // other functions. 480992cb984SSergei Barannikov SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(), 481992cb984SSergei Barannikov /*IsParam*/true); 482992cb984SSergei Barannikov } 483992cb984SSergei Barannikov } 484992cb984SSergei Barannikov 485992cb984SSergei Barannikov bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, 486992cb984SSergei Barannikov bool IsParam) const { 487992cb984SSergei Barannikov if (!SeenTypes.insert(Ty).second) 488992cb984SSergei Barannikov return false; 489992cb984SSergei Barannikov 490992cb984SSergei Barannikov if (IsParam) { 491992cb984SSergei Barannikov // A narrow (<16 bytes) vector will as a parameter also expose the ABI as 492992cb984SSergei Barannikov // it will be passed in a vector register. A wide (>16 bytes) vector will 493992cb984SSergei Barannikov // be passed via "hidden" pointer where any extra alignment is not 494992cb984SSergei Barannikov // required (per GCC). 495992cb984SSergei Barannikov const Type *SingleEltTy = getABIInfo<SystemZABIInfo>() 496992cb984SSergei Barannikov .GetSingleElementType(QualType(Ty, 0)) 497992cb984SSergei Barannikov .getTypePtr(); 498992cb984SSergei Barannikov bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() && 499992cb984SSergei Barannikov Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty); 500992cb984SSergei Barannikov if (Ty->isVectorType() || SingleVecEltStruct) 501992cb984SSergei Barannikov return Ctx.getTypeSize(Ty) / 8 <= 16; 502992cb984SSergei Barannikov } 503992cb984SSergei Barannikov 504992cb984SSergei Barannikov // Assume pointers are dereferenced. 505992cb984SSergei Barannikov while (Ty->isPointerType() || Ty->isArrayType()) 506992cb984SSergei Barannikov Ty = Ty->getPointeeOrArrayElementType(); 507992cb984SSergei Barannikov 508992cb984SSergei Barannikov // Vectors >= 16 bytes expose the ABI through alignment requirements. 509992cb984SSergei Barannikov if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16) 510992cb984SSergei Barannikov return true; 511992cb984SSergei Barannikov 512992cb984SSergei Barannikov if (const auto *RecordTy = Ty->getAs<RecordType>()) { 513992cb984SSergei Barannikov const RecordDecl *RD = RecordTy->getDecl(); 514992cb984SSergei Barannikov if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 515992cb984SSergei Barannikov if (CXXRD->hasDefinition()) 516992cb984SSergei Barannikov for (const auto &I : CXXRD->bases()) 517992cb984SSergei Barannikov if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false)) 518992cb984SSergei Barannikov return true; 519992cb984SSergei Barannikov for (const auto *FD : RD->fields()) 520992cb984SSergei Barannikov if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false)) 521992cb984SSergei Barannikov return true; 522992cb984SSergei Barannikov } 523992cb984SSergei Barannikov 524992cb984SSergei Barannikov if (const auto *FT = Ty->getAs<FunctionType>()) 525992cb984SSergei Barannikov if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true)) 526992cb984SSergei Barannikov return true; 527992cb984SSergei Barannikov if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>()) 528992cb984SSergei Barannikov for (const auto &ParamType : Proto->getParamTypes()) 529992cb984SSergei Barannikov if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true)) 530992cb984SSergei Barannikov return true; 531992cb984SSergei Barannikov 532992cb984SSergei Barannikov return false; 533992cb984SSergei Barannikov } 534992cb984SSergei Barannikov 535992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo> 536992cb984SSergei Barannikov CodeGen::createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector, 537992cb984SSergei Barannikov bool SoftFloatABI) { 538992cb984SSergei Barannikov return std::make_unique<SystemZTargetCodeGenInfo>(CGM.getTypes(), HasVector, 539992cb984SSergei Barannikov SoftFloatABI); 540992cb984SSergei Barannikov } 541