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
12using namespace clang;
13using namespace clang::CodeGen;
14
15//===----------------------------------------------------------------------===//
16// BPF ABI Implementation
17//===----------------------------------------------------------------------===//
18
19namespace {
20
21class BPFABIInfo : public DefaultABIInfo {
22public:
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
93class BPFTargetCodeGenInfo : public TargetCodeGenInfo {
94public:
95 BPFTargetCodeGenInfo(CodeGenTypes &CGT)
96 : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(args&: CGT)) {}
97};
98
99}
100
101std::unique_ptr<TargetCodeGenInfo>
102CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) {
103 return std::make_unique<BPFTargetCodeGenInfo>(args&: CGM.getTypes());
104}
105