xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/Targets/SystemZ.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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