//===- BPF.cpp ------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "ABIInfoImpl.h" #include "TargetInfo.h" using namespace clang; using namespace clang::CodeGen; //===----------------------------------------------------------------------===// // BPF ABI Implementation //===----------------------------------------------------------------------===// namespace { class BPFABIInfo : public DefaultABIInfo { public: BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} ABIArgInfo classifyArgumentType(QualType Ty) const { Ty = useFirstFieldIfTransparentUnion(Ty); if (isAggregateTypeForABI(Ty)) { uint64_t Bits = getContext().getTypeSize(Ty); if (Bits == 0) return ABIArgInfo::getIgnore(); // If the aggregate needs 1 or 2 registers, do not use reference. if (Bits <= 128) { llvm::Type *CoerceTy; if (Bits <= 64) { CoerceTy = llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8)); } else { llvm::Type *RegTy = llvm::IntegerType::get(getVMContext(), 64); CoerceTy = llvm::ArrayType::get(RegTy, 2); } return ABIArgInfo::getDirect(CoerceTy); } else { return getNaturalAlignIndirect(Ty); } } if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); ASTContext &Context = getContext(); if (const auto *EIT = Ty->getAs()) if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) return getNaturalAlignIndirect(Ty); return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) : ABIArgInfo::getDirect()); } ABIArgInfo classifyReturnType(QualType RetTy) const { if (RetTy->isVoidType()) return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy)) return getNaturalAlignIndirect(RetTy); // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) RetTy = EnumTy->getDecl()->getIntegerType(); ASTContext &Context = getContext(); if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) return getNaturalAlignIndirect(RetTy); // Caller will do necessary sign/zero extension. return ABIArgInfo::getDirect(); } void computeInfo(CGFunctionInfo &FI) const override { FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (auto &I : FI.arguments()) I.info = classifyArgumentType(I.type); } }; class BPFTargetCodeGenInfo : public TargetCodeGenInfo { public: BPFTargetCodeGenInfo(CodeGenTypes &CGT) : TargetCodeGenInfo(std::make_unique(CGT)) {} }; } std::unique_ptr CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) { return std::make_unique(CGM.getTypes()); }