xref: /llvm-project/clang/lib/CodeGen/Targets/BPF.cpp (revision 992cb98462abb7630e87003516b75b241628f64c)
1*992cb984SSergei Barannikov //===- BPF.cpp ------------------------------------------------------------===//
2*992cb984SSergei Barannikov //
3*992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5*992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*992cb984SSergei Barannikov //
7*992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8*992cb984SSergei Barannikov 
9*992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10*992cb984SSergei Barannikov #include "TargetInfo.h"
11*992cb984SSergei Barannikov 
12*992cb984SSergei Barannikov using namespace clang;
13*992cb984SSergei Barannikov using namespace clang::CodeGen;
14*992cb984SSergei Barannikov 
15*992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
16*992cb984SSergei Barannikov // BPF ABI Implementation
17*992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
18*992cb984SSergei Barannikov 
19*992cb984SSergei Barannikov namespace {
20*992cb984SSergei Barannikov 
21*992cb984SSergei Barannikov class BPFABIInfo : public DefaultABIInfo {
22*992cb984SSergei Barannikov public:
BPFABIInfo(CodeGenTypes & CGT)23*992cb984SSergei Barannikov   BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
24*992cb984SSergei Barannikov 
classifyArgumentType(QualType Ty) const25*992cb984SSergei Barannikov   ABIArgInfo classifyArgumentType(QualType Ty) const {
26*992cb984SSergei Barannikov     Ty = useFirstFieldIfTransparentUnion(Ty);
27*992cb984SSergei Barannikov 
28*992cb984SSergei Barannikov     if (isAggregateTypeForABI(Ty)) {
29*992cb984SSergei Barannikov       uint64_t Bits = getContext().getTypeSize(Ty);
30*992cb984SSergei Barannikov       if (Bits == 0)
31*992cb984SSergei Barannikov         return ABIArgInfo::getIgnore();
32*992cb984SSergei Barannikov 
33*992cb984SSergei Barannikov       // If the aggregate needs 1 or 2 registers, do not use reference.
34*992cb984SSergei Barannikov       if (Bits <= 128) {
35*992cb984SSergei Barannikov         llvm::Type *CoerceTy;
36*992cb984SSergei Barannikov         if (Bits <= 64) {
37*992cb984SSergei Barannikov           CoerceTy =
38*992cb984SSergei Barannikov               llvm::IntegerType::get(getVMContext(), llvm::alignTo(Bits, 8));
39*992cb984SSergei Barannikov         } else {
40*992cb984SSergei Barannikov           llvm::Type *RegTy = llvm::IntegerType::get(getVMContext(), 64);
41*992cb984SSergei Barannikov           CoerceTy = llvm::ArrayType::get(RegTy, 2);
42*992cb984SSergei Barannikov         }
43*992cb984SSergei Barannikov         return ABIArgInfo::getDirect(CoerceTy);
44*992cb984SSergei Barannikov       } else {
45*992cb984SSergei Barannikov         return getNaturalAlignIndirect(Ty);
46*992cb984SSergei Barannikov       }
47*992cb984SSergei Barannikov     }
48*992cb984SSergei Barannikov 
49*992cb984SSergei Barannikov     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
50*992cb984SSergei Barannikov       Ty = EnumTy->getDecl()->getIntegerType();
51*992cb984SSergei Barannikov 
52*992cb984SSergei Barannikov     ASTContext &Context = getContext();
53*992cb984SSergei Barannikov     if (const auto *EIT = Ty->getAs<BitIntType>())
54*992cb984SSergei Barannikov       if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty))
55*992cb984SSergei Barannikov         return getNaturalAlignIndirect(Ty);
56*992cb984SSergei Barannikov 
57*992cb984SSergei Barannikov     return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty)
58*992cb984SSergei Barannikov                                               : ABIArgInfo::getDirect());
59*992cb984SSergei Barannikov   }
60*992cb984SSergei Barannikov 
classifyReturnType(QualType RetTy) const61*992cb984SSergei Barannikov   ABIArgInfo classifyReturnType(QualType RetTy) const {
62*992cb984SSergei Barannikov     if (RetTy->isVoidType())
63*992cb984SSergei Barannikov       return ABIArgInfo::getIgnore();
64*992cb984SSergei Barannikov 
65*992cb984SSergei Barannikov     if (isAggregateTypeForABI(RetTy))
66*992cb984SSergei Barannikov       return getNaturalAlignIndirect(RetTy);
67*992cb984SSergei Barannikov 
68*992cb984SSergei Barannikov     // Treat an enum type as its underlying type.
69*992cb984SSergei Barannikov     if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
70*992cb984SSergei Barannikov       RetTy = EnumTy->getDecl()->getIntegerType();
71*992cb984SSergei Barannikov 
72*992cb984SSergei Barannikov     ASTContext &Context = getContext();
73*992cb984SSergei Barannikov     if (const auto *EIT = RetTy->getAs<BitIntType>())
74*992cb984SSergei Barannikov       if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty))
75*992cb984SSergei Barannikov         return getNaturalAlignIndirect(RetTy);
76*992cb984SSergei Barannikov 
77*992cb984SSergei Barannikov     // Caller will do necessary sign/zero extension.
78*992cb984SSergei Barannikov     return ABIArgInfo::getDirect();
79*992cb984SSergei Barannikov   }
80*992cb984SSergei Barannikov 
computeInfo(CGFunctionInfo & FI) const81*992cb984SSergei Barannikov   void computeInfo(CGFunctionInfo &FI) const override {
82*992cb984SSergei Barannikov     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
83*992cb984SSergei Barannikov     for (auto &I : FI.arguments())
84*992cb984SSergei Barannikov       I.info = classifyArgumentType(I.type);
85*992cb984SSergei Barannikov   }
86*992cb984SSergei Barannikov 
87*992cb984SSergei Barannikov };
88*992cb984SSergei Barannikov 
89*992cb984SSergei Barannikov class BPFTargetCodeGenInfo : public TargetCodeGenInfo {
90*992cb984SSergei Barannikov public:
BPFTargetCodeGenInfo(CodeGenTypes & CGT)91*992cb984SSergei Barannikov   BPFTargetCodeGenInfo(CodeGenTypes &CGT)
92*992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {}
93*992cb984SSergei Barannikov };
94*992cb984SSergei Barannikov 
95*992cb984SSergei Barannikov }
96*992cb984SSergei Barannikov 
97*992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
createBPFTargetCodeGenInfo(CodeGenModule & CGM)98*992cb984SSergei Barannikov CodeGen::createBPFTargetCodeGenInfo(CodeGenModule &CGM) {
99*992cb984SSergei Barannikov   return std::make_unique<BPFTargetCodeGenInfo>(CGM.getTypes());
100*992cb984SSergei Barannikov }
101