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(T: Ty)) { |
29 | uint64_t Bits = getContext().getTypeSize(T: 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(C&: getVMContext(), NumBits: llvm::alignTo(Value: Bits, Align: 8)); |
39 | } else { |
40 | llvm::Type *RegTy = llvm::IntegerType::get(C&: getVMContext(), NumBits: 64); |
41 | CoerceTy = llvm::ArrayType::get(ElementType: RegTy, NumElements: 2); |
42 | } |
43 | return ABIArgInfo::getDirect(T: CoerceTy); |
44 | } else { |
45 | return getNaturalAlignIndirect(Ty, |
46 | AddrSpace: 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(T: Context.Int128Ty)) |
56 | return getNaturalAlignIndirect(Ty, |
57 | AddrSpace: 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(T: RetTy)) |
68 | return getNaturalAlignIndirect(Ty: RetTy, |
69 | AddrSpace: 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(T: Context.Int128Ty)) |
78 | return getNaturalAlignIndirect(Ty: RetTy, |
79 | AddrSpace: 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(RetTy: FI.getReturnType()); |
87 | for (auto &I : FI.arguments()) |
88 | I.info = classifyArgumentType(Ty: I.type); |
89 | } |
90 | |
91 | }; |
92 | |
93 | class BPFTargetCodeGenInfo : public TargetCodeGenInfo { |
94 | public: |
95 | BPFTargetCodeGenInfo(CodeGenTypes &CGT) |
96 | : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(args&: CGT)) {} |
97 | }; |
98 | |
99 | } |
100 | |
101 | std::unique_ptr<TargetCodeGenInfo> |
102 | CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) { |
103 | return std::make_unique<BPFTargetCodeGenInfo>(args&: CGM.getTypes()); |
104 | } |
105 | |