1//===- BPF.cpp - BPF ABI Implementation ----------------------------------===//
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 "llvm/ABI/FunctionInfo.h"
10#include "llvm/ABI/TargetInfo.h"
11#include "llvm/ABI/Types.h"
12#include "llvm/Support/Alignment.h"
13#include "llvm/Support/Casting.h"
14
15namespace llvm::abi {
16
17class BPFTargetInfo : public TargetInfo {
18private:
19 TypeBuilder &TB;
20
21 ArgInfo classifyReturnType(const Type *RetTy) const {
22 if (RetTy->isVoid())
23 return ArgInfo::getIgnore();
24
25 if (isAggregateTypeForABI(Ty: RetTy)) {
26 if (RetTy->isZeroSize())
27 return ArgInfo::getIgnore();
28 return getNaturalAlignIndirect(Ty: RetTy, /*ByVal=*/false);
29 }
30
31 if (const auto *IntTy = dyn_cast<IntegerType>(Val: RetTy)) {
32 if (IntTy->isBitInt() && IntTy->getSizeInBits().getFixedValue() > 128)
33 return getNaturalAlignIndirect(Ty: RetTy, /*ByVal=*/false);
34 }
35
36 return ArgInfo::getDirect();
37 }
38
39 ArgInfo classifyArgumentType(const Type *ArgTy) const {
40 if (const auto *RT = dyn_cast<RecordType>(Val: ArgTy))
41 if (RT->isTransparentUnion() && RT->getNumFields() > 0)
42 ArgTy = RT->getFields()[0].FieldType;
43
44 if (isAggregateTypeForABI(Ty: ArgTy)) {
45 if (ArgTy->isZeroSize())
46 return ArgInfo::getIgnore();
47
48 auto SizeInBits = ArgTy->getSizeInBits().getFixedValue();
49 if (SizeInBits <= 128) {
50 const Type *CoerceTy;
51 if (SizeInBits <= 64) {
52 CoerceTy = TB.getIntegerType(BitWidth: alignTo(Value: SizeInBits, Align: 8), Align: Align(8), Signed: false);
53 } else {
54 const Type *RegTy = TB.getIntegerType(BitWidth: 64, Align: Align(8), Signed: false);
55 CoerceTy = TB.getArrayType(ElementType: RegTy, NumElements: 2, SizeInBits: 128);
56 }
57 return ArgInfo::getDirect(T: CoerceTy);
58 }
59
60 return getNaturalAlignIndirect(Ty: ArgTy, /*ByVal=*/true);
61 }
62
63 if (const auto *IntTy = dyn_cast<IntegerType>(Val: ArgTy)) {
64 if (IntTy->isBitInt() && IntTy->getSizeInBits().getFixedValue() > 128)
65 return getNaturalAlignIndirect(Ty: ArgTy, /*ByVal=*/true);
66
67 if (isPromotableInteger(IT: IntTy))
68 return ArgInfo::getExtend(T: ArgTy);
69 }
70
71 return ArgInfo::getDirect();
72 }
73
74public:
75 BPFTargetInfo(TypeBuilder &TB) : TB(TB) {}
76
77 void computeInfo(FunctionInfo &FI) const override {
78 FI.getReturnInfo() = classifyReturnType(RetTy: FI.getReturnType());
79 for (auto &I : FI.arguments())
80 I.Info = classifyArgumentType(ArgTy: I.ABIType);
81 }
82};
83
84std::unique_ptr<TargetInfo> createBPFTargetInfo(TypeBuilder &TB) {
85 return std::make_unique<BPFTargetInfo>(args&: TB);
86}
87
88} // namespace llvm::abi
89