1 | //===-- llvm/BinaryFormat/XCOFF.cpp - The XCOFF file format -----*- C++/-*-===// |
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 "llvm/BinaryFormat/XCOFF.h" |
10 | #include "llvm/ADT/SmallString.h" |
11 | #include "llvm/ADT/StringRef.h" |
12 | #include "llvm/Support/Errc.h" |
13 | #include "llvm/Support/Error.h" |
14 | |
15 | using namespace llvm; |
16 | |
17 | #define SMC_CASE(A) \ |
18 | case XCOFF::XMC_##A: \ |
19 | return #A; |
20 | StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) { |
21 | switch (SMC) { |
22 | SMC_CASE(PR) |
23 | SMC_CASE(RO) |
24 | SMC_CASE(DB) |
25 | SMC_CASE(GL) |
26 | SMC_CASE(XO) |
27 | SMC_CASE(SV) |
28 | SMC_CASE(SV64) |
29 | SMC_CASE(SV3264) |
30 | SMC_CASE(TI) |
31 | SMC_CASE(TB) |
32 | SMC_CASE(RW) |
33 | SMC_CASE(TC0) |
34 | SMC_CASE(TC) |
35 | SMC_CASE(TD) |
36 | SMC_CASE(DS) |
37 | SMC_CASE(UA) |
38 | SMC_CASE(BS) |
39 | SMC_CASE(UC) |
40 | SMC_CASE(TL) |
41 | SMC_CASE(UL) |
42 | SMC_CASE(TE) |
43 | #undef SMC_CASE |
44 | } |
45 | |
46 | // TODO: need to add a test case for "Unknown" and other SMC. |
47 | return "Unknown" ; |
48 | } |
49 | |
50 | #define RELOC_CASE(A) \ |
51 | case XCOFF::A: \ |
52 | return #A; |
53 | StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) { |
54 | switch (Type) { |
55 | RELOC_CASE(R_POS) |
56 | RELOC_CASE(R_RL) |
57 | RELOC_CASE(R_RLA) |
58 | RELOC_CASE(R_NEG) |
59 | RELOC_CASE(R_REL) |
60 | RELOC_CASE(R_TOC) |
61 | RELOC_CASE(R_TRL) |
62 | RELOC_CASE(R_TRLA) |
63 | RELOC_CASE(R_GL) |
64 | RELOC_CASE(R_TCL) |
65 | RELOC_CASE(R_REF) |
66 | RELOC_CASE(R_BA) |
67 | RELOC_CASE(R_BR) |
68 | RELOC_CASE(R_RBA) |
69 | RELOC_CASE(R_RBR) |
70 | RELOC_CASE(R_TLS) |
71 | RELOC_CASE(R_TLS_IE) |
72 | RELOC_CASE(R_TLS_LD) |
73 | RELOC_CASE(R_TLS_LE) |
74 | RELOC_CASE(R_TLSM) |
75 | RELOC_CASE(R_TLSML) |
76 | RELOC_CASE(R_TOCU) |
77 | RELOC_CASE(R_TOCL) |
78 | } |
79 | return "Unknown" ; |
80 | } |
81 | #undef RELOC_CASE |
82 | |
83 | #define LANG_CASE(A) \ |
84 | case XCOFF::TracebackTable::A: \ |
85 | return #A; |
86 | |
87 | StringRef XCOFF::getNameForTracebackTableLanguageId( |
88 | XCOFF::TracebackTable::LanguageID LangId) { |
89 | switch (LangId) { |
90 | LANG_CASE(C) |
91 | LANG_CASE(Fortran) |
92 | LANG_CASE(Pascal) |
93 | LANG_CASE(Ada) |
94 | LANG_CASE(PL1) |
95 | LANG_CASE(Basic) |
96 | LANG_CASE(Lisp) |
97 | LANG_CASE(Cobol) |
98 | LANG_CASE(Modula2) |
99 | LANG_CASE(Rpg) |
100 | LANG_CASE(PL8) |
101 | LANG_CASE(Assembly) |
102 | LANG_CASE(Java) |
103 | LANG_CASE(ObjectiveC) |
104 | LANG_CASE(CPlusPlus) |
105 | } |
106 | return "Unknown" ; |
107 | } |
108 | #undef LANG_CASE |
109 | |
110 | Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value, |
111 | unsigned FixedParmsNum, |
112 | unsigned FloatingParmsNum) { |
113 | SmallString<32> ParmsType; |
114 | int Bits = 0; |
115 | unsigned ParsedFixedNum = 0; |
116 | unsigned ParsedFloatingNum = 0; |
117 | unsigned ParsedNum = 0; |
118 | unsigned ParmsNum = FixedParmsNum + FloatingParmsNum; |
119 | |
120 | // In the function PPCFunctionInfo::getParmsType(), when there are no vector |
121 | // parameters, the 31st bit of ParmsType is always zero even if it indicates a |
122 | // floating point parameter. The parameter type information is lost. There |
123 | // are only 8 GPRs used for parameters passing, the floating parameters |
124 | // also occupy GPRs if there are available, so the 31st bit can never be a |
125 | // fixed parameter. At the same time, we also do not know whether the zero of |
126 | // the 31st bit indicates a float or double parameter type here. Therefore, we |
127 | // ignore the 31st bit. |
128 | while (Bits < 31 && ParsedNum < ParmsNum) { |
129 | if (++ParsedNum > 1) |
130 | ParmsType += ", " ; |
131 | if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) { |
132 | // Fixed parameter type. |
133 | ParmsType += "i" ; |
134 | ++ParsedFixedNum; |
135 | Value <<= 1; |
136 | ++Bits; |
137 | } else { |
138 | if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0) |
139 | // Float parameter type. |
140 | ParmsType += "f" ; |
141 | else |
142 | // Double parameter type. |
143 | ParmsType += "d" ; |
144 | ++ParsedFloatingNum; |
145 | Value <<= 2; |
146 | Bits += 2; |
147 | } |
148 | } |
149 | |
150 | // We have more parameters than the 32 Bits could encode. |
151 | if (ParsedNum < ParmsNum) |
152 | ParmsType += ", ..." ; |
153 | |
154 | if (Value != 0u || ParsedFixedNum > FixedParmsNum || |
155 | ParsedFloatingNum > FloatingParmsNum) |
156 | return createStringError(EC: errc::invalid_argument, |
157 | S: "ParmsType encodes can not map to ParmsNum " |
158 | "parameters in parseParmsType." ); |
159 | return ParmsType; |
160 | } |
161 | |
162 | SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) { |
163 | SmallString<32> Res; |
164 | |
165 | if (Flag & ExtendedTBTableFlag::TB_OS1) |
166 | Res += "TB_OS1 " ; |
167 | if (Flag & ExtendedTBTableFlag::TB_RESERVED) |
168 | Res += "TB_RESERVED " ; |
169 | if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY) |
170 | Res += "TB_SSP_CANARY " ; |
171 | if (Flag & ExtendedTBTableFlag::TB_OS2) |
172 | Res += "TB_OS2 " ; |
173 | if (Flag & ExtendedTBTableFlag::TB_EH_INFO) |
174 | Res += "TB_EH_INFO " ; |
175 | if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2) |
176 | Res += "TB_LONGTBTABLE2 " ; |
177 | |
178 | // Two of the bits that haven't got used in the mask. |
179 | if (Flag & 0x06) |
180 | Res += "Unknown " ; |
181 | |
182 | // Pop the last space. |
183 | Res.pop_back(); |
184 | return Res; |
185 | } |
186 | |
187 | Expected<SmallString<32>> |
188 | XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, |
189 | unsigned FloatingParmsNum, |
190 | unsigned VectorParmsNum) { |
191 | SmallString<32> ParmsType; |
192 | |
193 | unsigned ParsedFixedNum = 0; |
194 | unsigned ParsedFloatingNum = 0; |
195 | unsigned ParsedVectorNum = 0; |
196 | unsigned ParsedNum = 0; |
197 | unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum; |
198 | |
199 | for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) { |
200 | if (++ParsedNum > 1) |
201 | ParmsType += ", " ; |
202 | |
203 | switch (Value & TracebackTable::ParmTypeMask) { |
204 | case TracebackTable::ParmTypeIsFixedBits: |
205 | ParmsType += "i" ; |
206 | ++ParsedFixedNum; |
207 | break; |
208 | case TracebackTable::ParmTypeIsVectorBits: |
209 | ParmsType += "v" ; |
210 | ++ParsedVectorNum; |
211 | break; |
212 | case TracebackTable::ParmTypeIsFloatingBits: |
213 | ParmsType += "f" ; |
214 | ++ParsedFloatingNum; |
215 | break; |
216 | case TracebackTable::ParmTypeIsDoubleBits: |
217 | ParmsType += "d" ; |
218 | ++ParsedFloatingNum; |
219 | break; |
220 | default: |
221 | assert(false && "Unrecognized bits in ParmsType." ); |
222 | } |
223 | Value <<= 2; |
224 | } |
225 | |
226 | // We have more parameters than the 32 Bits could encode. |
227 | if (ParsedNum < ParmsNum) |
228 | ParmsType += ", ..." ; |
229 | |
230 | if (Value != 0u || ParsedFixedNum > FixedParmsNum || |
231 | ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum) |
232 | return createStringError( |
233 | EC: errc::invalid_argument, |
234 | S: "ParmsType encodes can not map to ParmsNum parameters " |
235 | "in parseParmsTypeWithVecInfo." ); |
236 | |
237 | return ParmsType; |
238 | } |
239 | |
240 | Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value, |
241 | unsigned ParmsNum) { |
242 | SmallString<32> ParmsType; |
243 | unsigned ParsedNum = 0; |
244 | for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) { |
245 | if (++ParsedNum > 1) |
246 | ParmsType += ", " ; |
247 | switch (Value & TracebackTable::ParmTypeMask) { |
248 | case TracebackTable::ParmTypeIsVectorCharBit: |
249 | ParmsType += "vc" ; |
250 | break; |
251 | |
252 | case TracebackTable::ParmTypeIsVectorShortBit: |
253 | ParmsType += "vs" ; |
254 | break; |
255 | |
256 | case TracebackTable::ParmTypeIsVectorIntBit: |
257 | ParmsType += "vi" ; |
258 | break; |
259 | |
260 | case TracebackTable::ParmTypeIsVectorFloatBit: |
261 | ParmsType += "vf" ; |
262 | break; |
263 | } |
264 | |
265 | Value <<= 2; |
266 | } |
267 | |
268 | // We have more parameters than the 32 Bits could encode. |
269 | if (ParsedNum < ParmsNum) |
270 | ParmsType += ", ..." ; |
271 | |
272 | if (Value != 0u) |
273 | return createStringError(EC: errc::invalid_argument, |
274 | S: "ParmsType encodes more than ParmsNum parameters " |
275 | "in parseVectorParmsType." ); |
276 | return ParmsType; |
277 | } |
278 | |