Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/CodeGen/Targets/Lanai.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Lanai.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
// Lanai ABI Implementation
17
//===----------------------------------------------------------------------===//
18
19
namespace {
20
class LanaiABIInfo : public DefaultABIInfo {
21
  struct CCState {
22
    unsigned FreeRegs;
23
  };
24
25
public:
26
0
  LanaiABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
27
28
  bool shouldUseInReg(QualType Ty, CCState &State) const;
29
30
0
  void computeInfo(CGFunctionInfo &FI) const override {
31
0
    CCState State;
32
    // Lanai uses 4 registers to pass arguments unless the function has the
33
    // regparm attribute set.
34
0
    if (FI.getHasRegParm()) {
35
0
      State.FreeRegs = FI.getRegParm();
36
0
    } else {
37
0
      State.FreeRegs = 4;
38
0
    }
39
40
0
    if (!getCXXABI().classifyReturnType(FI))
41
0
      FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
42
0
    for (auto &I : FI.arguments())
43
0
      I.info = classifyArgumentType(I.type, State);
44
0
  }
45
46
  ABIArgInfo getIndirectResult(QualType Ty, bool ByVal, CCState &State) const;
47
  ABIArgInfo classifyArgumentType(QualType RetTy, CCState &State) const;
48
};
49
} // end anonymous namespace
50
51
0
bool LanaiABIInfo::shouldUseInReg(QualType Ty, CCState &State) const {
52
0
  unsigned Size = getContext().getTypeSize(Ty);
53
0
  unsigned SizeInRegs = llvm::alignTo(Size, 32U) / 32U;
54
55
0
  if (SizeInRegs == 0)
56
0
    return false;
57
58
0
  if (SizeInRegs > State.FreeRegs) {
59
0
    State.FreeRegs = 0;
60
0
    return false;
61
0
  }
62
63
0
  State.FreeRegs -= SizeInRegs;
64
65
0
  return true;
66
0
}
67
68
ABIArgInfo LanaiABIInfo::getIndirectResult(QualType Ty, bool ByVal,
69
0
                                           CCState &State) const {
70
0
  if (!ByVal) {
71
0
    if (State.FreeRegs) {
72
0
      --State.FreeRegs; // Non-byval indirects just use one pointer.
73
0
      return getNaturalAlignIndirectInReg(Ty);
74
0
    }
75
0
    return getNaturalAlignIndirect(Ty, false);
76
0
  }
77
78
  // Compute the byval alignment.
79
0
  const unsigned MinABIStackAlignInBytes = 4;
80
0
  unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
81
0
  return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
82
0
                                 /*Realign=*/TypeAlign >
83
0
                                     MinABIStackAlignInBytes);
84
0
}
85
86
ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,
87
0
                                              CCState &State) const {
88
  // Check with the C++ ABI first.
89
0
  const RecordType *RT = Ty->getAs<RecordType>();
90
0
  if (RT) {
91
0
    CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
92
0
    if (RAA == CGCXXABI::RAA_Indirect) {
93
0
      return getIndirectResult(Ty, /*ByVal=*/false, State);
94
0
    } else if (RAA == CGCXXABI::RAA_DirectInMemory) {
95
0
      return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
96
0
    }
97
0
  }
98
99
0
  if (isAggregateTypeForABI(Ty)) {
100
    // Structures with flexible arrays are always indirect.
101
0
    if (RT && RT->getDecl()->hasFlexibleArrayMember())
102
0
      return getIndirectResult(Ty, /*ByVal=*/true, State);
103
104
    // Ignore empty structs/unions.
105
0
    if (isEmptyRecord(getContext(), Ty, true))
106
0
      return ABIArgInfo::getIgnore();
107
108
0
    llvm::LLVMContext &LLVMContext = getVMContext();
109
0
    unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32;
110
0
    if (SizeInRegs <= State.FreeRegs) {
111
0
      llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
112
0
      SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
113
0
      llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
114
0
      State.FreeRegs -= SizeInRegs;
115
0
      return ABIArgInfo::getDirectInReg(Result);
116
0
    } else {
117
0
      State.FreeRegs = 0;
118
0
    }
119
0
    return getIndirectResult(Ty, true, State);
120
0
  }
121
122
  // Treat an enum type as its underlying type.
123
0
  if (const auto *EnumTy = Ty->getAs<EnumType>())
124
0
    Ty = EnumTy->getDecl()->getIntegerType();
125
126
0
  bool InReg = shouldUseInReg(Ty, State);
127
128
  // Don't pass >64 bit integers in registers.
129
0
  if (const auto *EIT = Ty->getAs<BitIntType>())
130
0
    if (EIT->getNumBits() > 64)
131
0
      return getIndirectResult(Ty, /*ByVal=*/true, State);
132
133
0
  if (isPromotableIntegerTypeForABI(Ty)) {
134
0
    if (InReg)
135
0
      return ABIArgInfo::getDirectInReg();
136
0
    return ABIArgInfo::getExtend(Ty);
137
0
  }
138
0
  if (InReg)
139
0
    return ABIArgInfo::getDirectInReg();
140
0
  return ABIArgInfo::getDirect();
141
0
}
142
143
namespace {
144
class LanaiTargetCodeGenInfo : public TargetCodeGenInfo {
145
public:
146
  LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
147
0
      : TargetCodeGenInfo(std::make_unique<LanaiABIInfo>(CGT)) {}
148
};
149
}
150
151
std::unique_ptr<TargetCodeGenInfo>
152
0
CodeGen::createLanaiTargetCodeGenInfo(CodeGenModule &CGM) {
153
0
  return std::make_unique<LanaiTargetCodeGenInfo>(CGM.getTypes());
154
0
}