106c3fb27SDimitry Andric //===- SystemZ.cpp --------------------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #include "ABIInfoImpl.h" 1006c3fb27SDimitry Andric #include "TargetInfo.h" 1106c3fb27SDimitry Andric #include "clang/Basic/Builtins.h" 1206c3fb27SDimitry Andric #include "llvm/IR/IntrinsicsS390.h" 1306c3fb27SDimitry Andric 1406c3fb27SDimitry Andric using namespace clang; 1506c3fb27SDimitry Andric using namespace clang::CodeGen; 1606c3fb27SDimitry Andric 1706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1806c3fb27SDimitry Andric // SystemZ ABI Implementation 1906c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 2006c3fb27SDimitry Andric 2106c3fb27SDimitry Andric namespace { 2206c3fb27SDimitry Andric 2306c3fb27SDimitry Andric class SystemZABIInfo : public ABIInfo { 2406c3fb27SDimitry Andric bool HasVector; 2506c3fb27SDimitry Andric bool IsSoftFloatABI; 2606c3fb27SDimitry Andric 2706c3fb27SDimitry Andric public: 2806c3fb27SDimitry Andric SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF) 2906c3fb27SDimitry Andric : ABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {} 3006c3fb27SDimitry Andric 3106c3fb27SDimitry Andric bool isPromotableIntegerTypeForABI(QualType Ty) const; 3206c3fb27SDimitry Andric bool isCompoundType(QualType Ty) const; 3306c3fb27SDimitry Andric bool isVectorArgumentType(QualType Ty) const; 3406c3fb27SDimitry Andric bool isFPArgumentType(QualType Ty) const; 3506c3fb27SDimitry Andric QualType GetSingleElementType(QualType Ty) const; 3606c3fb27SDimitry Andric 3706c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const; 3806c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType ArgTy) const; 3906c3fb27SDimitry Andric 4006c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 41*0fca6ea1SDimitry Andric RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 42*0fca6ea1SDimitry Andric AggValueSlot Slot) const override; 4306c3fb27SDimitry Andric }; 4406c3fb27SDimitry Andric 4506c3fb27SDimitry Andric class SystemZTargetCodeGenInfo : public TargetCodeGenInfo { 4606c3fb27SDimitry Andric ASTContext &Ctx; 4706c3fb27SDimitry Andric 4806c3fb27SDimitry Andric // These are used for speeding up the search for a visible vector ABI. 4906c3fb27SDimitry Andric mutable bool HasVisibleVecABIFlag = false; 5006c3fb27SDimitry Andric mutable std::set<const Type *> SeenTypes; 5106c3fb27SDimitry Andric 5206c3fb27SDimitry Andric // Returns true (the first time) if Ty is, or is found to include, a vector 5306c3fb27SDimitry Andric // type that exposes the vector ABI. This is any vector >=16 bytes which 5406c3fb27SDimitry Andric // with vector support are aligned to only 8 bytes. When IsParam is true, 5506c3fb27SDimitry Andric // the type belongs to a value as passed between functions. If it is a 5606c3fb27SDimitry Andric // vector <=16 bytes it will be passed in a vector register (if supported). 5706c3fb27SDimitry Andric bool isVectorTypeBased(const Type *Ty, bool IsParam) const; 5806c3fb27SDimitry Andric 5906c3fb27SDimitry Andric public: 6006c3fb27SDimitry Andric SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI) 6106c3fb27SDimitry Andric : TargetCodeGenInfo( 6206c3fb27SDimitry Andric std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)), 6306c3fb27SDimitry Andric Ctx(CGT.getContext()) { 6406c3fb27SDimitry Andric SwiftInfo = 6506c3fb27SDimitry Andric std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false); 6606c3fb27SDimitry Andric } 6706c3fb27SDimitry Andric 6806c3fb27SDimitry Andric // The vector ABI is different when the vector facility is present and when 6906c3fb27SDimitry Andric // a module e.g. defines an externally visible vector variable, a flag 7006c3fb27SDimitry Andric // indicating a visible vector ABI is added. Eventually this will result in 7106c3fb27SDimitry Andric // a GNU attribute indicating the vector ABI of the module. Ty is the type 7206c3fb27SDimitry Andric // of a variable or function parameter that is globally visible. 7306c3fb27SDimitry Andric void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M, 7406c3fb27SDimitry Andric bool IsParam) const { 7506c3fb27SDimitry Andric if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) { 7606c3fb27SDimitry Andric M.getModule().addModuleFlag(llvm::Module::Warning, 7706c3fb27SDimitry Andric "s390x-visible-vector-ABI", 1); 7806c3fb27SDimitry Andric HasVisibleVecABIFlag = true; 7906c3fb27SDimitry Andric } 8006c3fb27SDimitry Andric } 8106c3fb27SDimitry Andric 8206c3fb27SDimitry Andric void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 8306c3fb27SDimitry Andric CodeGen::CodeGenModule &M) const override { 8406c3fb27SDimitry Andric if (!D) 8506c3fb27SDimitry Andric return; 8606c3fb27SDimitry Andric 8706c3fb27SDimitry Andric // Check if the vector ABI becomes visible by an externally visible 8806c3fb27SDimitry Andric // variable or function. 8906c3fb27SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D)) { 9006c3fb27SDimitry Andric if (VD->isExternallyVisible()) 9106c3fb27SDimitry Andric handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M, 9206c3fb27SDimitry Andric /*IsParam*/false); 9306c3fb27SDimitry Andric } 9406c3fb27SDimitry Andric else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 9506c3fb27SDimitry Andric if (FD->isExternallyVisible()) 9606c3fb27SDimitry Andric handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M, 9706c3fb27SDimitry Andric /*IsParam*/false); 9806c3fb27SDimitry Andric } 9906c3fb27SDimitry Andric } 10006c3fb27SDimitry Andric 10106c3fb27SDimitry Andric llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID, 10206c3fb27SDimitry Andric CGBuilderTy &Builder, 10306c3fb27SDimitry Andric CodeGenModule &CGM) const override { 10406c3fb27SDimitry Andric assert(V->getType()->isFloatingPointTy() && "V should have an FP type."); 10506c3fb27SDimitry Andric // Only use TDC in constrained FP mode. 10606c3fb27SDimitry Andric if (!Builder.getIsFPConstrained()) 10706c3fb27SDimitry Andric return nullptr; 10806c3fb27SDimitry Andric 10906c3fb27SDimitry Andric llvm::Type *Ty = V->getType(); 11006c3fb27SDimitry Andric if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) { 11106c3fb27SDimitry Andric llvm::Module &M = CGM.getModule(); 11206c3fb27SDimitry Andric auto &Ctx = M.getContext(); 11306c3fb27SDimitry Andric llvm::Function *TDCFunc = 11406c3fb27SDimitry Andric llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty); 11506c3fb27SDimitry Andric unsigned TDCBits = 0; 11606c3fb27SDimitry Andric switch (BuiltinID) { 11706c3fb27SDimitry Andric case Builtin::BI__builtin_isnan: 11806c3fb27SDimitry Andric TDCBits = 0xf; 11906c3fb27SDimitry Andric break; 12006c3fb27SDimitry Andric case Builtin::BIfinite: 12106c3fb27SDimitry Andric case Builtin::BI__finite: 12206c3fb27SDimitry Andric case Builtin::BIfinitef: 12306c3fb27SDimitry Andric case Builtin::BI__finitef: 12406c3fb27SDimitry Andric case Builtin::BIfinitel: 12506c3fb27SDimitry Andric case Builtin::BI__finitel: 12606c3fb27SDimitry Andric case Builtin::BI__builtin_isfinite: 12706c3fb27SDimitry Andric TDCBits = 0xfc0; 12806c3fb27SDimitry Andric break; 12906c3fb27SDimitry Andric case Builtin::BI__builtin_isinf: 13006c3fb27SDimitry Andric TDCBits = 0x30; 13106c3fb27SDimitry Andric break; 13206c3fb27SDimitry Andric default: 13306c3fb27SDimitry Andric break; 13406c3fb27SDimitry Andric } 13506c3fb27SDimitry Andric if (TDCBits) 13606c3fb27SDimitry Andric return Builder.CreateCall( 13706c3fb27SDimitry Andric TDCFunc, 13806c3fb27SDimitry Andric {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)}); 13906c3fb27SDimitry Andric } 14006c3fb27SDimitry Andric return nullptr; 14106c3fb27SDimitry Andric } 14206c3fb27SDimitry Andric }; 14306c3fb27SDimitry Andric } 14406c3fb27SDimitry Andric 14506c3fb27SDimitry Andric bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const { 14606c3fb27SDimitry Andric // Treat an enum type as its underlying type. 14706c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 14806c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 14906c3fb27SDimitry Andric 15006c3fb27SDimitry Andric // Promotable integer types are required to be promoted by the ABI. 15106c3fb27SDimitry Andric if (ABIInfo::isPromotableIntegerTypeForABI(Ty)) 15206c3fb27SDimitry Andric return true; 15306c3fb27SDimitry Andric 15406c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) 15506c3fb27SDimitry Andric if (EIT->getNumBits() < 64) 15606c3fb27SDimitry Andric return true; 15706c3fb27SDimitry Andric 15806c3fb27SDimitry Andric // 32-bit values must also be promoted. 15906c3fb27SDimitry Andric if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) 16006c3fb27SDimitry Andric switch (BT->getKind()) { 16106c3fb27SDimitry Andric case BuiltinType::Int: 16206c3fb27SDimitry Andric case BuiltinType::UInt: 16306c3fb27SDimitry Andric return true; 16406c3fb27SDimitry Andric default: 16506c3fb27SDimitry Andric return false; 16606c3fb27SDimitry Andric } 16706c3fb27SDimitry Andric return false; 16806c3fb27SDimitry Andric } 16906c3fb27SDimitry Andric 17006c3fb27SDimitry Andric bool SystemZABIInfo::isCompoundType(QualType Ty) const { 17106c3fb27SDimitry Andric return (Ty->isAnyComplexType() || 17206c3fb27SDimitry Andric Ty->isVectorType() || 17306c3fb27SDimitry Andric isAggregateTypeForABI(Ty)); 17406c3fb27SDimitry Andric } 17506c3fb27SDimitry Andric 17606c3fb27SDimitry Andric bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const { 17706c3fb27SDimitry Andric return (HasVector && 17806c3fb27SDimitry Andric Ty->isVectorType() && 17906c3fb27SDimitry Andric getContext().getTypeSize(Ty) <= 128); 18006c3fb27SDimitry Andric } 18106c3fb27SDimitry Andric 18206c3fb27SDimitry Andric bool SystemZABIInfo::isFPArgumentType(QualType Ty) const { 18306c3fb27SDimitry Andric if (IsSoftFloatABI) 18406c3fb27SDimitry Andric return false; 18506c3fb27SDimitry Andric 18606c3fb27SDimitry Andric if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) 18706c3fb27SDimitry Andric switch (BT->getKind()) { 18806c3fb27SDimitry Andric case BuiltinType::Float: 18906c3fb27SDimitry Andric case BuiltinType::Double: 19006c3fb27SDimitry Andric return true; 19106c3fb27SDimitry Andric default: 19206c3fb27SDimitry Andric return false; 19306c3fb27SDimitry Andric } 19406c3fb27SDimitry Andric 19506c3fb27SDimitry Andric return false; 19606c3fb27SDimitry Andric } 19706c3fb27SDimitry Andric 19806c3fb27SDimitry Andric QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { 19906c3fb27SDimitry Andric const RecordType *RT = Ty->getAs<RecordType>(); 20006c3fb27SDimitry Andric 20106c3fb27SDimitry Andric if (RT && RT->isStructureOrClassType()) { 20206c3fb27SDimitry Andric const RecordDecl *RD = RT->getDecl(); 20306c3fb27SDimitry Andric QualType Found; 20406c3fb27SDimitry Andric 20506c3fb27SDimitry Andric // If this is a C++ record, check the bases first. 20606c3fb27SDimitry Andric if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 20706c3fb27SDimitry Andric if (CXXRD->hasDefinition()) 20806c3fb27SDimitry Andric for (const auto &I : CXXRD->bases()) { 20906c3fb27SDimitry Andric QualType Base = I.getType(); 21006c3fb27SDimitry Andric 21106c3fb27SDimitry Andric // Empty bases don't affect things either way. 21206c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Base, true)) 21306c3fb27SDimitry Andric continue; 21406c3fb27SDimitry Andric 21506c3fb27SDimitry Andric if (!Found.isNull()) 21606c3fb27SDimitry Andric return Ty; 21706c3fb27SDimitry Andric Found = GetSingleElementType(Base); 21806c3fb27SDimitry Andric } 21906c3fb27SDimitry Andric 22006c3fb27SDimitry Andric // Check the fields. 22106c3fb27SDimitry Andric for (const auto *FD : RD->fields()) { 22206c3fb27SDimitry Andric // Unlike isSingleElementStruct(), empty structure and array fields 22306c3fb27SDimitry Andric // do count. So do anonymous bitfields that aren't zero-sized. 22406c3fb27SDimitry Andric 22506c3fb27SDimitry Andric // Like isSingleElementStruct(), ignore C++20 empty data members. 22606c3fb27SDimitry Andric if (FD->hasAttr<NoUniqueAddressAttr>() && 22706c3fb27SDimitry Andric isEmptyRecord(getContext(), FD->getType(), true)) 22806c3fb27SDimitry Andric continue; 22906c3fb27SDimitry Andric 23006c3fb27SDimitry Andric // Unlike isSingleElementStruct(), arrays do not count. 23106c3fb27SDimitry Andric // Nested structures still do though. 23206c3fb27SDimitry Andric if (!Found.isNull()) 23306c3fb27SDimitry Andric return Ty; 23406c3fb27SDimitry Andric Found = GetSingleElementType(FD->getType()); 23506c3fb27SDimitry Andric } 23606c3fb27SDimitry Andric 23706c3fb27SDimitry Andric // Unlike isSingleElementStruct(), trailing padding is allowed. 23806c3fb27SDimitry Andric // An 8-byte aligned struct s { float f; } is passed as a double. 23906c3fb27SDimitry Andric if (!Found.isNull()) 24006c3fb27SDimitry Andric return Found; 24106c3fb27SDimitry Andric } 24206c3fb27SDimitry Andric 24306c3fb27SDimitry Andric return Ty; 24406c3fb27SDimitry Andric } 24506c3fb27SDimitry Andric 246*0fca6ea1SDimitry Andric RValue SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 247*0fca6ea1SDimitry Andric QualType Ty, AggValueSlot Slot) const { 24806c3fb27SDimitry Andric // Assume that va_list type is correct; should be pointer to LLVM type: 24906c3fb27SDimitry Andric // struct { 25006c3fb27SDimitry Andric // i64 __gpr; 25106c3fb27SDimitry Andric // i64 __fpr; 25206c3fb27SDimitry Andric // i8 *__overflow_arg_area; 25306c3fb27SDimitry Andric // i8 *__reg_save_area; 25406c3fb27SDimitry Andric // }; 25506c3fb27SDimitry Andric 25606c3fb27SDimitry Andric // Every non-vector argument occupies 8 bytes and is passed by preference 25706c3fb27SDimitry Andric // in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are 25806c3fb27SDimitry Andric // always passed on the stack. 25906c3fb27SDimitry Andric const SystemZTargetCodeGenInfo &SZCGI = 26006c3fb27SDimitry Andric static_cast<const SystemZTargetCodeGenInfo &>( 26106c3fb27SDimitry Andric CGT.getCGM().getTargetCodeGenInfo()); 26206c3fb27SDimitry Andric Ty = getContext().getCanonicalType(Ty); 26306c3fb27SDimitry Andric auto TyInfo = getContext().getTypeInfoInChars(Ty); 26406c3fb27SDimitry Andric llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty); 26506c3fb27SDimitry Andric llvm::Type *DirectTy = ArgTy; 26606c3fb27SDimitry Andric ABIArgInfo AI = classifyArgumentType(Ty); 26706c3fb27SDimitry Andric bool IsIndirect = AI.isIndirect(); 26806c3fb27SDimitry Andric bool InFPRs = false; 26906c3fb27SDimitry Andric bool IsVector = false; 27006c3fb27SDimitry Andric CharUnits UnpaddedSize; 27106c3fb27SDimitry Andric CharUnits DirectAlign; 27206c3fb27SDimitry Andric SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(), 27306c3fb27SDimitry Andric /*IsParam*/true); 27406c3fb27SDimitry Andric if (IsIndirect) { 27506c3fb27SDimitry Andric DirectTy = llvm::PointerType::getUnqual(DirectTy); 27606c3fb27SDimitry Andric UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8); 27706c3fb27SDimitry Andric } else { 27806c3fb27SDimitry Andric if (AI.getCoerceToType()) 27906c3fb27SDimitry Andric ArgTy = AI.getCoerceToType(); 28006c3fb27SDimitry Andric InFPRs = (!IsSoftFloatABI && (ArgTy->isFloatTy() || ArgTy->isDoubleTy())); 28106c3fb27SDimitry Andric IsVector = ArgTy->isVectorTy(); 28206c3fb27SDimitry Andric UnpaddedSize = TyInfo.Width; 28306c3fb27SDimitry Andric DirectAlign = TyInfo.Align; 28406c3fb27SDimitry Andric } 28506c3fb27SDimitry Andric CharUnits PaddedSize = CharUnits::fromQuantity(8); 28606c3fb27SDimitry Andric if (IsVector && UnpaddedSize > PaddedSize) 28706c3fb27SDimitry Andric PaddedSize = CharUnits::fromQuantity(16); 28806c3fb27SDimitry Andric assert((UnpaddedSize <= PaddedSize) && "Invalid argument size."); 28906c3fb27SDimitry Andric 29006c3fb27SDimitry Andric CharUnits Padding = (PaddedSize - UnpaddedSize); 29106c3fb27SDimitry Andric 29206c3fb27SDimitry Andric llvm::Type *IndexTy = CGF.Int64Ty; 29306c3fb27SDimitry Andric llvm::Value *PaddedSizeV = 29406c3fb27SDimitry Andric llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity()); 29506c3fb27SDimitry Andric 29606c3fb27SDimitry Andric if (IsVector) { 29706c3fb27SDimitry Andric // Work out the address of a vector argument on the stack. 29806c3fb27SDimitry Andric // Vector arguments are always passed in the high bits of a 29906c3fb27SDimitry Andric // single (8 byte) or double (16 byte) stack slot. 30006c3fb27SDimitry Andric Address OverflowArgAreaPtr = 30106c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr"); 30206c3fb27SDimitry Andric Address OverflowArgArea = 30306c3fb27SDimitry Andric Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), 30406c3fb27SDimitry Andric CGF.Int8Ty, TyInfo.Align); 30506c3fb27SDimitry Andric Address MemAddr = OverflowArgArea.withElementType(DirectTy); 30606c3fb27SDimitry Andric 30706c3fb27SDimitry Andric // Update overflow_arg_area_ptr pointer 30806c3fb27SDimitry Andric llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( 309*0fca6ea1SDimitry Andric OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), 31006c3fb27SDimitry Andric PaddedSizeV, "overflow_arg_area"); 31106c3fb27SDimitry Andric CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); 31206c3fb27SDimitry Andric 313*0fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(MemAddr, Ty), Slot); 31406c3fb27SDimitry Andric } 31506c3fb27SDimitry Andric 31606c3fb27SDimitry Andric assert(PaddedSize.getQuantity() == 8); 31706c3fb27SDimitry Andric 31806c3fb27SDimitry Andric unsigned MaxRegs, RegCountField, RegSaveIndex; 31906c3fb27SDimitry Andric CharUnits RegPadding; 32006c3fb27SDimitry Andric if (InFPRs) { 32106c3fb27SDimitry Andric MaxRegs = 4; // Maximum of 4 FPR arguments 32206c3fb27SDimitry Andric RegCountField = 1; // __fpr 32306c3fb27SDimitry Andric RegSaveIndex = 16; // save offset for f0 32406c3fb27SDimitry Andric RegPadding = CharUnits(); // floats are passed in the high bits of an FPR 32506c3fb27SDimitry Andric } else { 32606c3fb27SDimitry Andric MaxRegs = 5; // Maximum of 5 GPR arguments 32706c3fb27SDimitry Andric RegCountField = 0; // __gpr 32806c3fb27SDimitry Andric RegSaveIndex = 2; // save offset for r2 32906c3fb27SDimitry Andric RegPadding = Padding; // values are passed in the low bits of a GPR 33006c3fb27SDimitry Andric } 33106c3fb27SDimitry Andric 33206c3fb27SDimitry Andric Address RegCountPtr = 33306c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr"); 33406c3fb27SDimitry Andric llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count"); 33506c3fb27SDimitry Andric llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs); 33606c3fb27SDimitry Andric llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV, 33706c3fb27SDimitry Andric "fits_in_regs"); 33806c3fb27SDimitry Andric 33906c3fb27SDimitry Andric llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); 34006c3fb27SDimitry Andric llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem"); 34106c3fb27SDimitry Andric llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); 34206c3fb27SDimitry Andric CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock); 34306c3fb27SDimitry Andric 34406c3fb27SDimitry Andric // Emit code to load the value if it was passed in registers. 34506c3fb27SDimitry Andric CGF.EmitBlock(InRegBlock); 34606c3fb27SDimitry Andric 34706c3fb27SDimitry Andric // Work out the address of an argument register. 34806c3fb27SDimitry Andric llvm::Value *ScaledRegCount = 34906c3fb27SDimitry Andric CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count"); 35006c3fb27SDimitry Andric llvm::Value *RegBase = 35106c3fb27SDimitry Andric llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity() 35206c3fb27SDimitry Andric + RegPadding.getQuantity()); 35306c3fb27SDimitry Andric llvm::Value *RegOffset = 35406c3fb27SDimitry Andric CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset"); 35506c3fb27SDimitry Andric Address RegSaveAreaPtr = 35606c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr"); 35706c3fb27SDimitry Andric llvm::Value *RegSaveArea = 35806c3fb27SDimitry Andric CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area"); 35906c3fb27SDimitry Andric Address RawRegAddr( 36006c3fb27SDimitry Andric CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset, "raw_reg_addr"), 36106c3fb27SDimitry Andric CGF.Int8Ty, PaddedSize); 36206c3fb27SDimitry Andric Address RegAddr = RawRegAddr.withElementType(DirectTy); 36306c3fb27SDimitry Andric 36406c3fb27SDimitry Andric // Update the register count 36506c3fb27SDimitry Andric llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1); 36606c3fb27SDimitry Andric llvm::Value *NewRegCount = 36706c3fb27SDimitry Andric CGF.Builder.CreateAdd(RegCount, One, "reg_count"); 36806c3fb27SDimitry Andric CGF.Builder.CreateStore(NewRegCount, RegCountPtr); 36906c3fb27SDimitry Andric CGF.EmitBranch(ContBlock); 37006c3fb27SDimitry Andric 37106c3fb27SDimitry Andric // Emit code to load the value if it was passed in memory. 37206c3fb27SDimitry Andric CGF.EmitBlock(InMemBlock); 37306c3fb27SDimitry Andric 37406c3fb27SDimitry Andric // Work out the address of a stack argument. 37506c3fb27SDimitry Andric Address OverflowArgAreaPtr = 37606c3fb27SDimitry Andric CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr"); 37706c3fb27SDimitry Andric Address OverflowArgArea = 37806c3fb27SDimitry Andric Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"), 37906c3fb27SDimitry Andric CGF.Int8Ty, PaddedSize); 38006c3fb27SDimitry Andric Address RawMemAddr = 38106c3fb27SDimitry Andric CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr"); 38206c3fb27SDimitry Andric Address MemAddr = RawMemAddr.withElementType(DirectTy); 38306c3fb27SDimitry Andric 38406c3fb27SDimitry Andric // Update overflow_arg_area_ptr pointer 385*0fca6ea1SDimitry Andric llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( 386*0fca6ea1SDimitry Andric OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), 387*0fca6ea1SDimitry Andric PaddedSizeV, "overflow_arg_area"); 38806c3fb27SDimitry Andric CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); 38906c3fb27SDimitry Andric CGF.EmitBranch(ContBlock); 39006c3fb27SDimitry Andric 39106c3fb27SDimitry Andric // Return the appropriate result. 39206c3fb27SDimitry Andric CGF.EmitBlock(ContBlock); 39306c3fb27SDimitry Andric Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock, 39406c3fb27SDimitry Andric "va_arg.addr"); 39506c3fb27SDimitry Andric 39606c3fb27SDimitry Andric if (IsIndirect) 39706c3fb27SDimitry Andric ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"), ArgTy, 39806c3fb27SDimitry Andric TyInfo.Align); 39906c3fb27SDimitry Andric 400*0fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(ResAddr, Ty), Slot); 40106c3fb27SDimitry Andric } 40206c3fb27SDimitry Andric 40306c3fb27SDimitry Andric ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const { 40406c3fb27SDimitry Andric if (RetTy->isVoidType()) 40506c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 40606c3fb27SDimitry Andric if (isVectorArgumentType(RetTy)) 40706c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 40806c3fb27SDimitry Andric if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64) 40906c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 41006c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 41106c3fb27SDimitry Andric : ABIArgInfo::getDirect()); 41206c3fb27SDimitry Andric } 41306c3fb27SDimitry Andric 41406c3fb27SDimitry Andric ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { 415*0fca6ea1SDimitry Andric // Handle transparent union types. 416*0fca6ea1SDimitry Andric Ty = useFirstFieldIfTransparentUnion(Ty); 417*0fca6ea1SDimitry Andric 41806c3fb27SDimitry Andric // Handle the generic C++ ABI. 41906c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 42006c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 42106c3fb27SDimitry Andric 42206c3fb27SDimitry Andric // Integers and enums are extended to full register width. 42306c3fb27SDimitry Andric if (isPromotableIntegerTypeForABI(Ty)) 424*0fca6ea1SDimitry Andric return ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)); 42506c3fb27SDimitry Andric 42606c3fb27SDimitry Andric // Handle vector types and vector-like structure types. Note that 42706c3fb27SDimitry Andric // as opposed to float-like structure types, we do not allow any 42806c3fb27SDimitry Andric // padding for vector-like structures, so verify the sizes match. 42906c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 43006c3fb27SDimitry Andric QualType SingleElementTy = GetSingleElementType(Ty); 43106c3fb27SDimitry Andric if (isVectorArgumentType(SingleElementTy) && 43206c3fb27SDimitry Andric getContext().getTypeSize(SingleElementTy) == Size) 43306c3fb27SDimitry Andric return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy)); 43406c3fb27SDimitry Andric 43506c3fb27SDimitry Andric // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly. 43606c3fb27SDimitry Andric if (Size != 8 && Size != 16 && Size != 32 && Size != 64) 43706c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 43806c3fb27SDimitry Andric 43906c3fb27SDimitry Andric // Handle small structures. 44006c3fb27SDimitry Andric if (const RecordType *RT = Ty->getAs<RecordType>()) { 44106c3fb27SDimitry Andric // Structures with flexible arrays have variable length, so really 44206c3fb27SDimitry Andric // fail the size test above. 44306c3fb27SDimitry Andric const RecordDecl *RD = RT->getDecl(); 44406c3fb27SDimitry Andric if (RD->hasFlexibleArrayMember()) 44506c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 44606c3fb27SDimitry Andric 44706c3fb27SDimitry Andric // The structure is passed as an unextended integer, a float, or a double. 44806c3fb27SDimitry Andric llvm::Type *PassTy; 44906c3fb27SDimitry Andric if (isFPArgumentType(SingleElementTy)) { 45006c3fb27SDimitry Andric assert(Size == 32 || Size == 64); 45106c3fb27SDimitry Andric if (Size == 32) 45206c3fb27SDimitry Andric PassTy = llvm::Type::getFloatTy(getVMContext()); 45306c3fb27SDimitry Andric else 45406c3fb27SDimitry Andric PassTy = llvm::Type::getDoubleTy(getVMContext()); 45506c3fb27SDimitry Andric } else 45606c3fb27SDimitry Andric PassTy = llvm::IntegerType::get(getVMContext(), Size); 45706c3fb27SDimitry Andric return ABIArgInfo::getDirect(PassTy); 45806c3fb27SDimitry Andric } 45906c3fb27SDimitry Andric 46006c3fb27SDimitry Andric // Non-structure compounds are passed indirectly. 46106c3fb27SDimitry Andric if (isCompoundType(Ty)) 46206c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 46306c3fb27SDimitry Andric 46406c3fb27SDimitry Andric return ABIArgInfo::getDirect(nullptr); 46506c3fb27SDimitry Andric } 46606c3fb27SDimitry Andric 46706c3fb27SDimitry Andric void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const { 46806c3fb27SDimitry Andric const SystemZTargetCodeGenInfo &SZCGI = 46906c3fb27SDimitry Andric static_cast<const SystemZTargetCodeGenInfo &>( 47006c3fb27SDimitry Andric CGT.getCGM().getTargetCodeGenInfo()); 47106c3fb27SDimitry Andric if (!getCXXABI().classifyReturnType(FI)) 47206c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 47306c3fb27SDimitry Andric unsigned Idx = 0; 47406c3fb27SDimitry Andric for (auto &I : FI.arguments()) { 47506c3fb27SDimitry Andric I.info = classifyArgumentType(I.type); 47606c3fb27SDimitry Andric if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs()) 47706c3fb27SDimitry Andric // Check if a vararg vector argument is passed, in which case the 47806c3fb27SDimitry Andric // vector ABI becomes visible as the va_list could be passed on to 47906c3fb27SDimitry Andric // other functions. 48006c3fb27SDimitry Andric SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(), 48106c3fb27SDimitry Andric /*IsParam*/true); 48206c3fb27SDimitry Andric } 48306c3fb27SDimitry Andric } 48406c3fb27SDimitry Andric 48506c3fb27SDimitry Andric bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, 48606c3fb27SDimitry Andric bool IsParam) const { 48706c3fb27SDimitry Andric if (!SeenTypes.insert(Ty).second) 48806c3fb27SDimitry Andric return false; 48906c3fb27SDimitry Andric 49006c3fb27SDimitry Andric if (IsParam) { 49106c3fb27SDimitry Andric // A narrow (<16 bytes) vector will as a parameter also expose the ABI as 49206c3fb27SDimitry Andric // it will be passed in a vector register. A wide (>16 bytes) vector will 49306c3fb27SDimitry Andric // be passed via "hidden" pointer where any extra alignment is not 49406c3fb27SDimitry Andric // required (per GCC). 49506c3fb27SDimitry Andric const Type *SingleEltTy = getABIInfo<SystemZABIInfo>() 49606c3fb27SDimitry Andric .GetSingleElementType(QualType(Ty, 0)) 49706c3fb27SDimitry Andric .getTypePtr(); 49806c3fb27SDimitry Andric bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() && 49906c3fb27SDimitry Andric Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty); 50006c3fb27SDimitry Andric if (Ty->isVectorType() || SingleVecEltStruct) 50106c3fb27SDimitry Andric return Ctx.getTypeSize(Ty) / 8 <= 16; 50206c3fb27SDimitry Andric } 50306c3fb27SDimitry Andric 50406c3fb27SDimitry Andric // Assume pointers are dereferenced. 50506c3fb27SDimitry Andric while (Ty->isPointerType() || Ty->isArrayType()) 50606c3fb27SDimitry Andric Ty = Ty->getPointeeOrArrayElementType(); 50706c3fb27SDimitry Andric 50806c3fb27SDimitry Andric // Vectors >= 16 bytes expose the ABI through alignment requirements. 50906c3fb27SDimitry Andric if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16) 51006c3fb27SDimitry Andric return true; 51106c3fb27SDimitry Andric 51206c3fb27SDimitry Andric if (const auto *RecordTy = Ty->getAs<RecordType>()) { 51306c3fb27SDimitry Andric const RecordDecl *RD = RecordTy->getDecl(); 51406c3fb27SDimitry Andric if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) 51506c3fb27SDimitry Andric if (CXXRD->hasDefinition()) 51606c3fb27SDimitry Andric for (const auto &I : CXXRD->bases()) 51706c3fb27SDimitry Andric if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false)) 51806c3fb27SDimitry Andric return true; 51906c3fb27SDimitry Andric for (const auto *FD : RD->fields()) 52006c3fb27SDimitry Andric if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false)) 52106c3fb27SDimitry Andric return true; 52206c3fb27SDimitry Andric } 52306c3fb27SDimitry Andric 52406c3fb27SDimitry Andric if (const auto *FT = Ty->getAs<FunctionType>()) 52506c3fb27SDimitry Andric if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true)) 52606c3fb27SDimitry Andric return true; 52706c3fb27SDimitry Andric if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>()) 52806c3fb27SDimitry Andric for (const auto &ParamType : Proto->getParamTypes()) 52906c3fb27SDimitry Andric if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true)) 53006c3fb27SDimitry Andric return true; 53106c3fb27SDimitry Andric 53206c3fb27SDimitry Andric return false; 53306c3fb27SDimitry Andric } 53406c3fb27SDimitry Andric 53506c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 53606c3fb27SDimitry Andric CodeGen::createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector, 53706c3fb27SDimitry Andric bool SoftFloatABI) { 53806c3fb27SDimitry Andric return std::make_unique<SystemZTargetCodeGenInfo>(CGM.getTypes(), HasVector, 53906c3fb27SDimitry Andric SoftFloatABI); 54006c3fb27SDimitry Andric } 541