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: 23 BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 24 25 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 getDataLayout().getAllocaAddrSpace()); 47 } 48 } 49 50 if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 51 Ty = EnumTy->getDecl()->getIntegerType(); 52 53 ASTContext &Context = getContext(); 54 if (const auto *EIT = Ty->getAs<BitIntType>()) 55 if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) 56 return getNaturalAlignIndirect(Ty, 57 getDataLayout().getAllocaAddrSpace()); 58 59 return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) 60 : ABIArgInfo::getDirect()); 61 } 62 63 ABIArgInfo classifyReturnType(QualType RetTy) const { 64 if (RetTy->isVoidType()) 65 return ABIArgInfo::getIgnore(); 66 67 if (isAggregateTypeForABI(RetTy)) 68 return getNaturalAlignIndirect(RetTy, 69 getDataLayout().getAllocaAddrSpace()); 70 71 // Treat an enum type as its underlying type. 72 if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 73 RetTy = EnumTy->getDecl()->getIntegerType(); 74 75 ASTContext &Context = getContext(); 76 if (const auto *EIT = RetTy->getAs<BitIntType>()) 77 if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) 78 return getNaturalAlignIndirect(RetTy, 79 getDataLayout().getAllocaAddrSpace()); 80 81 // Caller will do necessary sign/zero extension. 82 return ABIArgInfo::getDirect(); 83 } 84 85 void computeInfo(CGFunctionInfo &FI) const override { 86 FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 87 for (auto &I : FI.arguments()) 88 I.info = classifyArgumentType(I.type); 89 } 90 91 }; 92 93 class BPFTargetCodeGenInfo : public TargetCodeGenInfo { 94 public: 95 BPFTargetCodeGenInfo(CodeGenTypes &CGT) 96 : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {} 97 }; 98 99 } 100 101 std::unique_ptr<TargetCodeGenInfo> 102 CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) { 103 return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes()); 104 } 105