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