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 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
classifyReturnType(QualType RetTy) const63 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
computeInfo(CGFunctionInfo & FI) const85 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:
BPFTargetCodeGenInfo(CodeGenTypes & CGT)95 BPFTargetCodeGenInfo(CodeGenTypes &CGT)
96 : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {}
97 };
98
99 }
100
101 std::unique_ptr<TargetCodeGenInfo>
createBPFTargetCodeGenInfo(CodeGenModule & CGM)102 CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) {
103 return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes());
104 }
105