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 | } |
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 | |
61 | ABIArgInfo classifyReturnType(QualType RetTy) const { |
62 | if (RetTy->isVoidType()) |
63 | return ABIArgInfo::getIgnore(); |
64 | |
65 | if (isAggregateTypeForABI(T: RetTy)) |
66 | return getNaturalAlignIndirect(Ty: 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(Ty: RetTy); |
76 | |
77 | // Caller will do necessary sign/zero extension. |
78 | return ABIArgInfo::getDirect(); |
79 | } |
80 | |
81 | void computeInfo(CGFunctionInfo &FI) const override { |
82 | FI.getReturnInfo() = classifyReturnType(RetTy: FI.getReturnType()); |
83 | for (auto &I : FI.arguments()) |
84 | I.info = classifyArgumentType(Ty: I.type); |
85 | } |
86 | |
87 | }; |
88 | |
89 | class BPFTargetCodeGenInfo : public TargetCodeGenInfo { |
90 | public: |
91 | BPFTargetCodeGenInfo(CodeGenTypes &CGT) |
92 | : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(args&: CGT)) {} |
93 | }; |
94 | |
95 | } |
96 | |
97 | std::unique_ptr<TargetCodeGenInfo> |
98 | CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) { |
99 | return std::make_unique<BPFTargetCodeGenInfo>(args&: CGM.getTypes()); |
100 | } |
101 |