1*06c3fb27SDimitry Andric //===- PNaCl.cpp ----------------------------------------------------------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #include "ABIInfoImpl.h" 10*06c3fb27SDimitry Andric #include "TargetInfo.h" 11*06c3fb27SDimitry Andric 12*06c3fb27SDimitry Andric using namespace clang; 13*06c3fb27SDimitry Andric using namespace clang::CodeGen; 14*06c3fb27SDimitry Andric 15*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 16*06c3fb27SDimitry Andric // le32/PNaCl bitcode ABI Implementation 17*06c3fb27SDimitry Andric // 18*06c3fb27SDimitry Andric // This is a simplified version of the x86_32 ABI. Arguments and return values 19*06c3fb27SDimitry Andric // are always passed on the stack. 20*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 21*06c3fb27SDimitry Andric 22*06c3fb27SDimitry Andric class PNaClABIInfo : public ABIInfo { 23*06c3fb27SDimitry Andric public: 24*06c3fb27SDimitry Andric PNaClABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {} 25*06c3fb27SDimitry Andric 26*06c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const; 27*06c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType RetTy) const; 28*06c3fb27SDimitry Andric 29*06c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 30*06c3fb27SDimitry Andric Address EmitVAArg(CodeGenFunction &CGF, 31*06c3fb27SDimitry Andric Address VAListAddr, QualType Ty) const override; 32*06c3fb27SDimitry Andric }; 33*06c3fb27SDimitry Andric 34*06c3fb27SDimitry Andric class PNaClTargetCodeGenInfo : public TargetCodeGenInfo { 35*06c3fb27SDimitry Andric public: 36*06c3fb27SDimitry Andric PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) 37*06c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<PNaClABIInfo>(CGT)) {} 38*06c3fb27SDimitry Andric }; 39*06c3fb27SDimitry Andric 40*06c3fb27SDimitry Andric void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const { 41*06c3fb27SDimitry Andric if (!getCXXABI().classifyReturnType(FI)) 42*06c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 43*06c3fb27SDimitry Andric 44*06c3fb27SDimitry Andric for (auto &I : FI.arguments()) 45*06c3fb27SDimitry Andric I.info = classifyArgumentType(I.type); 46*06c3fb27SDimitry Andric } 47*06c3fb27SDimitry Andric 48*06c3fb27SDimitry Andric Address PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 49*06c3fb27SDimitry Andric QualType Ty) const { 50*06c3fb27SDimitry Andric // The PNaCL ABI is a bit odd, in that varargs don't use normal 51*06c3fb27SDimitry Andric // function classification. Structs get passed directly for varargs 52*06c3fb27SDimitry Andric // functions, through a rewriting transform in 53*06c3fb27SDimitry Andric // pnacl-llvm/lib/Transforms/NaCl/ExpandVarArgs.cpp, which allows 54*06c3fb27SDimitry Andric // this target to actually support a va_arg instructions with an 55*06c3fb27SDimitry Andric // aggregate type, unlike other targets. 56*06c3fb27SDimitry Andric return EmitVAArgInstr(CGF, VAListAddr, Ty, ABIArgInfo::getDirect()); 57*06c3fb27SDimitry Andric } 58*06c3fb27SDimitry Andric 59*06c3fb27SDimitry Andric /// Classify argument of given type \p Ty. 60*06c3fb27SDimitry Andric ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const { 61*06c3fb27SDimitry Andric if (isAggregateTypeForABI(Ty)) { 62*06c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 63*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); 64*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty); 65*06c3fb27SDimitry Andric } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) { 66*06c3fb27SDimitry Andric // Treat an enum type as its underlying type. 67*06c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 68*06c3fb27SDimitry Andric } else if (Ty->isFloatingType()) { 69*06c3fb27SDimitry Andric // Floating-point types don't go inreg. 70*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 71*06c3fb27SDimitry Andric } else if (const auto *EIT = Ty->getAs<BitIntType>()) { 72*06c3fb27SDimitry Andric // Treat bit-precise integers as integers if <= 64, otherwise pass 73*06c3fb27SDimitry Andric // indirectly. 74*06c3fb27SDimitry Andric if (EIT->getNumBits() > 64) 75*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty); 76*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 77*06c3fb27SDimitry Andric } 78*06c3fb27SDimitry Andric 79*06c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) 80*06c3fb27SDimitry Andric : ABIArgInfo::getDirect()); 81*06c3fb27SDimitry Andric } 82*06c3fb27SDimitry Andric 83*06c3fb27SDimitry Andric ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const { 84*06c3fb27SDimitry Andric if (RetTy->isVoidType()) 85*06c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric // In the PNaCl ABI we always return records/structures on the stack. 88*06c3fb27SDimitry Andric if (isAggregateTypeForABI(RetTy)) 89*06c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 90*06c3fb27SDimitry Andric 91*06c3fb27SDimitry Andric // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly. 92*06c3fb27SDimitry Andric if (const auto *EIT = RetTy->getAs<BitIntType>()) { 93*06c3fb27SDimitry Andric if (EIT->getNumBits() > 64) 94*06c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 95*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 96*06c3fb27SDimitry Andric } 97*06c3fb27SDimitry Andric 98*06c3fb27SDimitry Andric // Treat an enum type as its underlying type. 99*06c3fb27SDimitry Andric if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 100*06c3fb27SDimitry Andric RetTy = EnumTy->getDecl()->getIntegerType(); 101*06c3fb27SDimitry Andric 102*06c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 103*06c3fb27SDimitry Andric : ABIArgInfo::getDirect()); 104*06c3fb27SDimitry Andric } 105*06c3fb27SDimitry Andric 106*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 107*06c3fb27SDimitry Andric CodeGen::createPNaClTargetCodeGenInfo(CodeGenModule &CGM) { 108*06c3fb27SDimitry Andric return std::make_unique<PNaClTargetCodeGenInfo>(CGM.getTypes()); 109*06c3fb27SDimitry Andric } 110