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