1*06c3fb27SDimitry Andric //===- BPF.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 // BPF ABI Implementation 17*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 18*06c3fb27SDimitry Andric 19*06c3fb27SDimitry Andric namespace { 20*06c3fb27SDimitry Andric 21*06c3fb27SDimitry Andric class BPFABIInfo : public DefaultABIInfo { 22*06c3fb27SDimitry Andric public: BPFABIInfo(CodeGenTypes & CGT)23*06c3fb27SDimitry Andric BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 24*06c3fb27SDimitry Andric classifyArgumentType(QualType Ty) const25*06c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType Ty) const { 26*06c3fb27SDimitry Andric Ty = useFirstFieldIfTransparentUnion(Ty); 27*06c3fb27SDimitry Andric 28*06c3fb27SDimitry Andric if (isAggregateTypeForABI(Ty)) { 29*06c3fb27SDimitry Andric uint64_t Bits = getContext().getTypeSize(Ty); 30*06c3fb27SDimitry Andric if (Bits == 0) 31*06c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 32*06c3fb27SDimitry Andric 33*06c3fb27SDimitry Andric // If the aggregate needs 1 or 2 registers, do not use reference. 34*06c3fb27SDimitry Andric if (Bits <= 128) { 35*06c3fb27SDimitry Andric llvm::Type *CoerceTy; 36*06c3fb27SDimitry Andric if (Bits <= 64) { 37*06c3fb27SDimitry Andric CoerceTy = 38*06c3fb27SDimitry Andric llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8)); 39*06c3fb27SDimitry Andric } else { 40*06c3fb27SDimitry Andric llvm::Type *RegTy = llvm::IntegerType::get(getVMContext(), 64); 41*06c3fb27SDimitry Andric CoerceTy = llvm::ArrayType::get(RegTy, 2); 42*06c3fb27SDimitry Andric } 43*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(CoerceTy); 44*06c3fb27SDimitry Andric } else { 45*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty); 46*06c3fb27SDimitry Andric } 47*06c3fb27SDimitry Andric } 48*06c3fb27SDimitry Andric 49*06c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 50*06c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 51*06c3fb27SDimitry Andric 52*06c3fb27SDimitry Andric ASTContext &Context = getContext(); 53*06c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) 54*06c3fb27SDimitry Andric if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) 55*06c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty); 56*06c3fb27SDimitry Andric 57*06c3fb27SDimitry Andric return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) 58*06c3fb27SDimitry Andric : ABIArgInfo::getDirect()); 59*06c3fb27SDimitry Andric } 60*06c3fb27SDimitry Andric classifyReturnType(QualType RetTy) const61*06c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const { 62*06c3fb27SDimitry Andric if (RetTy->isVoidType()) 63*06c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 64*06c3fb27SDimitry Andric 65*06c3fb27SDimitry Andric if (isAggregateTypeForABI(RetTy)) 66*06c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 67*06c3fb27SDimitry Andric 68*06c3fb27SDimitry Andric // Treat an enum type as its underlying type. 69*06c3fb27SDimitry Andric if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 70*06c3fb27SDimitry Andric RetTy = EnumTy->getDecl()->getIntegerType(); 71*06c3fb27SDimitry Andric 72*06c3fb27SDimitry Andric ASTContext &Context = getContext(); 73*06c3fb27SDimitry Andric if (const auto *EIT = RetTy->getAs<BitIntType>()) 74*06c3fb27SDimitry Andric if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) 75*06c3fb27SDimitry Andric return getNaturalAlignIndirect(RetTy); 76*06c3fb27SDimitry Andric 77*06c3fb27SDimitry Andric // Caller will do necessary sign/zero extension. 78*06c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 79*06c3fb27SDimitry Andric } 80*06c3fb27SDimitry Andric computeInfo(CGFunctionInfo & FI) const81*06c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override { 82*06c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 83*06c3fb27SDimitry Andric for (auto &I : FI.arguments()) 84*06c3fb27SDimitry Andric I.info = classifyArgumentType(I.type); 85*06c3fb27SDimitry Andric } 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric }; 88*06c3fb27SDimitry Andric 89*06c3fb27SDimitry Andric class BPFTargetCodeGenInfo : public TargetCodeGenInfo { 90*06c3fb27SDimitry Andric public: BPFTargetCodeGenInfo(CodeGenTypes & CGT)91*06c3fb27SDimitry Andric BPFTargetCodeGenInfo(CodeGenTypes &CGT) 92*06c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {} 93*06c3fb27SDimitry Andric }; 94*06c3fb27SDimitry Andric 95*06c3fb27SDimitry Andric } 96*06c3fb27SDimitry Andric 97*06c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> createBPFTargetCodeGenInfo(CodeGenModule & CGM)98*06c3fb27SDimitry AndricCodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) { 99*06c3fb27SDimitry Andric return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes()); 100*06c3fb27SDimitry Andric } 101