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(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       }
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(RetTy))
66       return getNaturalAlignIndirect(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(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(FI.getReturnType());
83     for (auto &I : FI.arguments())
84       I.info = classifyArgumentType(I.type);
85   }
86 
87 };
88 
89 class BPFTargetCodeGenInfo : public TargetCodeGenInfo {
90 public:
91   BPFTargetCodeGenInfo(CodeGenTypes &CGT)
92       : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {}
93 };
94 
95 }
96 
97 std::unique_ptr<TargetCodeGenInfo>
98 CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) {
99   return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes());
100 }
101