Coverage Report

Created: 2024-01-17 10:31

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