xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/Targets/BPF.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
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                                        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(Context.Int128Ty))
56         return getNaturalAlignIndirect(Ty,
57                                        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(RetTy))
68       return getNaturalAlignIndirect(RetTy,
69                                      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(Context.Int128Ty))
78         return getNaturalAlignIndirect(RetTy,
79                                        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(FI.getReturnType());
87     for (auto &I : FI.arguments())
88       I.info = classifyArgumentType(I.type);
89   }
90 
91 };
92 
93 class BPFTargetCodeGenInfo : public TargetCodeGenInfo {
94 public:
95   BPFTargetCodeGenInfo(CodeGenTypes &CGT)
96       : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {}
97 };
98 
99 }
100 
101 std::unique_ptr<TargetCodeGenInfo>
102 CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) {
103   return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes());
104 }
105