/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 | } |