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