================ @@ -396,12 +405,80 @@ CharUnits PPC32_SVR4_ABIInfo::getParamTypeAlignment(QualType Ty) const { return CharUnits::fromQuantity(4); } +ABIArgInfo PPC32_SVR4_ABIInfo::handleComplex(uint64_t &TypeSize) const { + llvm::Type *ElemTy; + unsigned RegsNeeded; // Registers Needed for Complex. + + // Choice of using llvm::Type::getInt64Ty(getVMContext()) for complex + // single-precision floats is based on the ABI ATR-PASS-COMPLEX-IN-GPRS + // specification. According to the specification: + // - For complex single-precision floats: If the register (gr) is even, it's + // incremented by one, and the lower-addressed word of the argument is loaded + // into gr, while the higher-addressed word is loaded into gr + 1. Then, gr is + // incremented by 2. + // - For complex double-precision floats: The words of the argument are loaded + // in memory-address order into gr, gr + 1, gr + 2, and gr + 3, with gr being + // incremented by 4. Thus, to maintain even alignment and adhere to the ABI + // specification, llvm::Type::getInt64Ty(getVMContext()) is used when TypeSize + // is 64. Powerpc backend handles this alignment requirement. Specifically, + // you can refer to the CC_PPC32_SVR4_Custom_AlignArgRegs method from + // PPCCallingconvention.cpp. For more context, refer to the previous + // discussion: https://reviews.llvm.org/D146942 and the related LLVM pull + // request: #77732 + + if (TypeSize == 64) { + ElemTy = llvm::Type::getInt64Ty(getVMContext()); + RegsNeeded = 1; + } else { + ElemTy = llvm::Type::getInt32Ty(getVMContext()); + RegsNeeded = TypeSize >> 5; + } + return ABIArgInfo::getDirect(llvm::ArrayType::get(ElemTy, RegsNeeded)); +} + +ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, + int &ArgGPRsLeft) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (!(getCodeGenOpts().getComplexInRegABI() == CodeGenOptions::CMPLX_InGPR) || + !ArgGPRsLeft) + return DefaultABIInfo::classifyArgumentType(Ty); + + assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); + ASTContext &Context = getContext(); + uint64_t TypeSize = Context.getTypeSize(Ty); + + if (Ty->isAnyComplexType()) { + // If gr is even set gr = gr + 1 for TypeSize=64. + if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; + + if (TypeSize <= RegLen * ArgGPRsLeft) { + ArgGPRsLeft -= TypeSize / RegLen; + return handleComplex(TypeSize); + } + } + + // Records with non-trivial destructors/copy-constructors should not be + // passed by value. + if (isAggregateTypeForABI(Ty)) + --ArgGPRsLeft; + else if (!Ty->isFloatingType() || (Ty->isFloatingType() && IsSoftFloatABI)) { + // For other primitive types. + if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) + --ArgGPRsLeft; // If gr is even set gr = gr + 1 for TypeSize=64. + if (TypeSize <= ArgGPRsLeft * RegLen) + ArgGPRsLeft -= TypeSize / RegLen; + } ---------------- diggerlin wrote:
the code line 467-472 is duplicated with the code 452-458 ,you rewrite the function as ``` ABIArgInfo PPC32_SVR4_ABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft) const { Ty = useFirstFieldIfTransparentUnion(Ty); if ( getCodeGenOpts().getComplexInRegABI() != CodeGenOptions::CMPLX_InGPR || !ArgGPRsLeft || (Ty->isFloatingType() && !IsSoftFloatABI) return DefaultABIInfo::classifyArgumentType(Ty); assert(ArgGPRsLeft >= 0 && "Arg GPR must be large or equal than zero"); // Records with non-trivial destructors/copy-constructors should not be // passed by value. if (isAggregateTypeForABI(Ty)) --ArgGPRsLeft; ASTContext &Context = getContext(); uint64_t TypeSize = Context.getTypeSize(Ty); // If gr is even set gr = gr + 1 for TypeSize=64. if (TypeSize == 64 && ArgGPRsLeft % 2 == 1) --ArgGPRsLeft; if (TypeSize <= RegLen * ArgGPRsLeft) { ArgGPRsLeft -= TypeSize / RegLen; return handleComplex(TypeSize); } return DefaultABIInfo::classifyArgumentType(Ty); } ``` https://github.com/llvm/llvm-project/pull/77732 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits