1*992cb984SSergei Barannikov //===- BPF.cpp ------------------------------------------------------------===// 2*992cb984SSergei Barannikov // 3*992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information. 5*992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*992cb984SSergei Barannikov // 7*992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 8*992cb984SSergei Barannikov 9*992cb984SSergei Barannikov #include "ABIInfoImpl.h" 10*992cb984SSergei Barannikov #include "TargetInfo.h" 11*992cb984SSergei Barannikov 12*992cb984SSergei Barannikov using namespace clang; 13*992cb984SSergei Barannikov using namespace clang::CodeGen; 14*992cb984SSergei Barannikov 15*992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 16*992cb984SSergei Barannikov // BPF ABI Implementation 17*992cb984SSergei Barannikov //===----------------------------------------------------------------------===// 18*992cb984SSergei Barannikov 19*992cb984SSergei Barannikov namespace { 20*992cb984SSergei Barannikov 21*992cb984SSergei Barannikov class BPFABIInfo : public DefaultABIInfo { 22*992cb984SSergei Barannikov public: BPFABIInfo(CodeGenTypes & CGT)23*992cb984SSergei Barannikov BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 24*992cb984SSergei Barannikov classifyArgumentType(QualType Ty) const25*992cb984SSergei Barannikov ABIArgInfo classifyArgumentType(QualType Ty) const { 26*992cb984SSergei Barannikov Ty = useFirstFieldIfTransparentUnion(Ty); 27*992cb984SSergei Barannikov 28*992cb984SSergei Barannikov if (isAggregateTypeForABI(Ty)) { 29*992cb984SSergei Barannikov uint64_t Bits = getContext().getTypeSize(Ty); 30*992cb984SSergei Barannikov if (Bits == 0) 31*992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 32*992cb984SSergei Barannikov 33*992cb984SSergei Barannikov // If the aggregate needs 1 or 2 registers, do not use reference. 34*992cb984SSergei Barannikov if (Bits <= 128) { 35*992cb984SSergei Barannikov llvm::Type *CoerceTy; 36*992cb984SSergei Barannikov if (Bits <= 64) { 37*992cb984SSergei Barannikov CoerceTy = 38*992cb984SSergei Barannikov llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8)); 39*992cb984SSergei Barannikov } else { 40*992cb984SSergei Barannikov llvm::Type *RegTy = llvm::IntegerType::get(getVMContext(), 64); 41*992cb984SSergei Barannikov CoerceTy = llvm::ArrayType::get(RegTy, 2); 42*992cb984SSergei Barannikov } 43*992cb984SSergei Barannikov return ABIArgInfo::getDirect(CoerceTy); 44*992cb984SSergei Barannikov } else { 45*992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty); 46*992cb984SSergei Barannikov } 47*992cb984SSergei Barannikov } 48*992cb984SSergei Barannikov 49*992cb984SSergei Barannikov if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 50*992cb984SSergei Barannikov Ty = EnumTy->getDecl()->getIntegerType(); 51*992cb984SSergei Barannikov 52*992cb984SSergei Barannikov ASTContext &Context = getContext(); 53*992cb984SSergei Barannikov if (const auto *EIT = Ty->getAs<BitIntType>()) 54*992cb984SSergei Barannikov if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) 55*992cb984SSergei Barannikov return getNaturalAlignIndirect(Ty); 56*992cb984SSergei Barannikov 57*992cb984SSergei Barannikov return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) 58*992cb984SSergei Barannikov : ABIArgInfo::getDirect()); 59*992cb984SSergei Barannikov } 60*992cb984SSergei Barannikov classifyReturnType(QualType RetTy) const61*992cb984SSergei Barannikov ABIArgInfo classifyReturnType(QualType RetTy) const { 62*992cb984SSergei Barannikov if (RetTy->isVoidType()) 63*992cb984SSergei Barannikov return ABIArgInfo::getIgnore(); 64*992cb984SSergei Barannikov 65*992cb984SSergei Barannikov if (isAggregateTypeForABI(RetTy)) 66*992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 67*992cb984SSergei Barannikov 68*992cb984SSergei Barannikov // Treat an enum type as its underlying type. 69*992cb984SSergei Barannikov if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 70*992cb984SSergei Barannikov RetTy = EnumTy->getDecl()->getIntegerType(); 71*992cb984SSergei Barannikov 72*992cb984SSergei Barannikov ASTContext &Context = getContext(); 73*992cb984SSergei Barannikov if (const auto *EIT = RetTy->getAs<BitIntType>()) 74*992cb984SSergei Barannikov if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) 75*992cb984SSergei Barannikov return getNaturalAlignIndirect(RetTy); 76*992cb984SSergei Barannikov 77*992cb984SSergei Barannikov // Caller will do necessary sign/zero extension. 78*992cb984SSergei Barannikov return ABIArgInfo::getDirect(); 79*992cb984SSergei Barannikov } 80*992cb984SSergei Barannikov computeInfo(CGFunctionInfo & FI) const81*992cb984SSergei Barannikov void computeInfo(CGFunctionInfo &FI) const override { 82*992cb984SSergei Barannikov FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 83*992cb984SSergei Barannikov for (auto &I : FI.arguments()) 84*992cb984SSergei Barannikov I.info = classifyArgumentType(I.type); 85*992cb984SSergei Barannikov } 86*992cb984SSergei Barannikov 87*992cb984SSergei Barannikov }; 88*992cb984SSergei Barannikov 89*992cb984SSergei Barannikov class BPFTargetCodeGenInfo : public TargetCodeGenInfo { 90*992cb984SSergei Barannikov public: BPFTargetCodeGenInfo(CodeGenTypes & CGT)91*992cb984SSergei Barannikov BPFTargetCodeGenInfo(CodeGenTypes &CGT) 92*992cb984SSergei Barannikov : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {} 93*992cb984SSergei Barannikov }; 94*992cb984SSergei Barannikov 95*992cb984SSergei Barannikov } 96*992cb984SSergei Barannikov 97*992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo> createBPFTargetCodeGenInfo(CodeGenModule & CGM)98*992cb984SSergei BarannikovCodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) { 99*992cb984SSergei Barannikov return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes()); 100*992cb984SSergei Barannikov } 101