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/ADT/StringSwitch.h" |
13 | #include "llvm/Support/Errc.h" |
14 | #include "llvm/Support/Error.h" |
15 | #include "llvm/TargetParser/PPCTargetParser.h" |
16 | |
17 | using namespace llvm; |
18 | |
19 | #define SMC_CASE(A) \ |
20 | case XCOFF::XMC_##A: \ |
21 | return #A; |
22 | StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) { |
23 | switch (SMC) { |
24 | SMC_CASE(PR) |
25 | SMC_CASE(RO) |
26 | SMC_CASE(DB) |
27 | SMC_CASE(GL) |
28 | SMC_CASE(XO) |
29 | SMC_CASE(SV) |
30 | SMC_CASE(SV64) |
31 | SMC_CASE(SV3264) |
32 | SMC_CASE(TI) |
33 | SMC_CASE(TB) |
34 | SMC_CASE(RW) |
35 | SMC_CASE(TC0) |
36 | SMC_CASE(TC) |
37 | SMC_CASE(TD) |
38 | SMC_CASE(DS) |
39 | SMC_CASE(UA) |
40 | SMC_CASE(BS) |
41 | SMC_CASE(UC) |
42 | SMC_CASE(TL) |
43 | SMC_CASE(UL) |
44 | SMC_CASE(TE) |
45 | #undef SMC_CASE |
46 | } |
47 | |
48 | // TODO: need to add a test case for "Unknown" and other SMC. |
49 | return "Unknown" ; |
50 | } |
51 | |
52 | #define RELOC_CASE(A) \ |
53 | case XCOFF::A: \ |
54 | return #A; |
55 | StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) { |
56 | switch (Type) { |
57 | RELOC_CASE(R_POS) |
58 | RELOC_CASE(R_RL) |
59 | RELOC_CASE(R_RLA) |
60 | RELOC_CASE(R_NEG) |
61 | RELOC_CASE(R_REL) |
62 | RELOC_CASE(R_TOC) |
63 | RELOC_CASE(R_TRL) |
64 | RELOC_CASE(R_TRLA) |
65 | RELOC_CASE(R_GL) |
66 | RELOC_CASE(R_TCL) |
67 | RELOC_CASE(R_REF) |
68 | RELOC_CASE(R_BA) |
69 | RELOC_CASE(R_BR) |
70 | RELOC_CASE(R_RBA) |
71 | RELOC_CASE(R_RBR) |
72 | RELOC_CASE(R_TLS) |
73 | RELOC_CASE(R_TLS_IE) |
74 | RELOC_CASE(R_TLS_LD) |
75 | RELOC_CASE(R_TLS_LE) |
76 | RELOC_CASE(R_TLSM) |
77 | RELOC_CASE(R_TLSML) |
78 | RELOC_CASE(R_TOCU) |
79 | RELOC_CASE(R_TOCL) |
80 | } |
81 | return "Unknown" ; |
82 | } |
83 | #undef RELOC_CASE |
84 | |
85 | #define LANG_CASE(A) \ |
86 | case XCOFF::TracebackTable::A: \ |
87 | return #A; |
88 | |
89 | StringRef XCOFF::getNameForTracebackTableLanguageId( |
90 | XCOFF::TracebackTable::LanguageID LangId) { |
91 | switch (LangId) { |
92 | LANG_CASE(C) |
93 | LANG_CASE(Fortran) |
94 | LANG_CASE(Pascal) |
95 | LANG_CASE(Ada) |
96 | LANG_CASE(PL1) |
97 | LANG_CASE(Basic) |
98 | LANG_CASE(Lisp) |
99 | LANG_CASE(Cobol) |
100 | LANG_CASE(Modula2) |
101 | LANG_CASE(Rpg) |
102 | LANG_CASE(PL8) |
103 | LANG_CASE(Assembly) |
104 | LANG_CASE(Java) |
105 | LANG_CASE(ObjectiveC) |
106 | LANG_CASE(CPlusPlus) |
107 | } |
108 | return "Unknown" ; |
109 | } |
110 | #undef LANG_CASE |
111 | |
112 | XCOFF::CFileCpuId XCOFF::getCpuID(StringRef CPUName) { |
113 | StringRef CPU = PPC::normalizeCPUName(CPUName); |
114 | return StringSwitch<XCOFF::CFileCpuId>(CPU) |
115 | .Cases(S0: "generic" , S1: "COM" , Value: XCOFF::TCPU_COM) |
116 | .Case(S: "601" , Value: XCOFF::TCPU_601) |
117 | .Cases(S0: "602" , S1: "603" , S2: "603e" , S3: "603ev" , Value: XCOFF::TCPU_603) |
118 | .Cases(S0: "604" , S1: "604e" , Value: XCOFF::TCPU_604) |
119 | .Case(S: "620" , Value: XCOFF::TCPU_620) |
120 | .Case(S: "970" , Value: XCOFF::TCPU_970) |
121 | .Cases(S0: "a2" , S1: "g3" , S2: "g4" , S3: "g5" , S4: "e500" , Value: XCOFF::TCPU_COM) |
122 | .Cases(S0: "pwr3" , S1: "pwr4" , Value: XCOFF::TCPU_COM) |
123 | .Cases(S0: "pwr5" , S1: "PWR5" , Value: XCOFF::TCPU_PWR5) |
124 | .Cases(S0: "pwr5x" , S1: "PWR5X" , Value: XCOFF::TCPU_PWR5X) |
125 | .Cases(S0: "pwr6" , S1: "PWR6" , Value: XCOFF::TCPU_PWR6) |
126 | .Cases(S0: "pwr6x" , S1: "PWR6E" , Value: XCOFF::TCPU_PWR6E) |
127 | .Cases(S0: "pwr7" , S1: "PWR7" , Value: XCOFF::TCPU_PWR7) |
128 | .Cases(S0: "pwr8" , S1: "PWR8" , Value: XCOFF::TCPU_PWR8) |
129 | .Cases(S0: "pwr9" , S1: "PWR9" , Value: XCOFF::TCPU_PWR9) |
130 | .Cases(S0: "pwr10" , S1: "PWR10" , Value: XCOFF::TCPU_PWR10) |
131 | .Cases(S0: "ppc" , S1: "PPC" , S2: "ppc32" , S3: "ppc64" , Value: XCOFF::TCPU_COM) |
132 | .Case(S: "ppc64le" , Value: XCOFF::TCPU_PWR8) |
133 | .Case(S: "future" , Value: XCOFF::TCPU_PWR10) |
134 | .Cases(S0: "any" , S1: "ANY" , Value: XCOFF::TCPU_ANY) |
135 | .Default(Value: XCOFF::TCPU_INVALID); |
136 | } |
137 | |
138 | #define TCPU_CASE(A) \ |
139 | case XCOFF::TCPU_##A: \ |
140 | return #A; |
141 | StringRef XCOFF::getTCPUString(XCOFF::CFileCpuId TCPU) { |
142 | switch (TCPU) { |
143 | TCPU_CASE(INVALID) |
144 | TCPU_CASE(PPC) |
145 | TCPU_CASE(PPC64) |
146 | TCPU_CASE(COM) |
147 | TCPU_CASE(PWR) |
148 | TCPU_CASE(ANY) |
149 | TCPU_CASE(601) |
150 | TCPU_CASE(603) |
151 | TCPU_CASE(604) |
152 | TCPU_CASE(620) |
153 | TCPU_CASE(A35) |
154 | TCPU_CASE(PWR5) |
155 | TCPU_CASE(970) |
156 | TCPU_CASE(PWR6) |
157 | TCPU_CASE(PWR5X) |
158 | TCPU_CASE(PWR6E) |
159 | TCPU_CASE(PWR7) |
160 | TCPU_CASE(PWR8) |
161 | TCPU_CASE(PWR9) |
162 | TCPU_CASE(PWR10) |
163 | TCPU_CASE(PWRX) |
164 | } |
165 | return "INVALID" ; |
166 | } |
167 | #undef TCPU_CASE |
168 | |
169 | Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value, |
170 | unsigned FixedParmsNum, |
171 | unsigned FloatingParmsNum) { |
172 | SmallString<32> ParmsType; |
173 | int Bits = 0; |
174 | unsigned ParsedFixedNum = 0; |
175 | unsigned ParsedFloatingNum = 0; |
176 | unsigned ParsedNum = 0; |
177 | unsigned ParmsNum = FixedParmsNum + FloatingParmsNum; |
178 | |
179 | // In the function PPCFunctionInfo::getParmsType(), when there are no vector |
180 | // parameters, the 31st bit of ParmsType is always zero even if it indicates a |
181 | // floating point parameter. The parameter type information is lost. There |
182 | // are only 8 GPRs used for parameters passing, the floating parameters |
183 | // also occupy GPRs if there are available, so the 31st bit can never be a |
184 | // fixed parameter. At the same time, we also do not know whether the zero of |
185 | // the 31st bit indicates a float or double parameter type here. Therefore, we |
186 | // ignore the 31st bit. |
187 | while (Bits < 31 && ParsedNum < ParmsNum) { |
188 | if (++ParsedNum > 1) |
189 | ParmsType += ", " ; |
190 | if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) { |
191 | // Fixed parameter type. |
192 | ParmsType += "i" ; |
193 | ++ParsedFixedNum; |
194 | Value <<= 1; |
195 | ++Bits; |
196 | } else { |
197 | if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0) |
198 | // Float parameter type. |
199 | ParmsType += "f" ; |
200 | else |
201 | // Double parameter type. |
202 | ParmsType += "d" ; |
203 | ++ParsedFloatingNum; |
204 | Value <<= 2; |
205 | Bits += 2; |
206 | } |
207 | } |
208 | |
209 | // We have more parameters than the 32 Bits could encode. |
210 | if (ParsedNum < ParmsNum) |
211 | ParmsType += ", ..." ; |
212 | |
213 | if (Value != 0u || ParsedFixedNum > FixedParmsNum || |
214 | ParsedFloatingNum > FloatingParmsNum) |
215 | return createStringError(EC: errc::invalid_argument, |
216 | S: "ParmsType encodes can not map to ParmsNum " |
217 | "parameters in parseParmsType." ); |
218 | return ParmsType; |
219 | } |
220 | |
221 | SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) { |
222 | SmallString<32> Res; |
223 | |
224 | if (Flag & ExtendedTBTableFlag::TB_OS1) |
225 | Res += "TB_OS1 " ; |
226 | if (Flag & ExtendedTBTableFlag::TB_RESERVED) |
227 | Res += "TB_RESERVED " ; |
228 | if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY) |
229 | Res += "TB_SSP_CANARY " ; |
230 | if (Flag & ExtendedTBTableFlag::TB_OS2) |
231 | Res += "TB_OS2 " ; |
232 | if (Flag & ExtendedTBTableFlag::TB_EH_INFO) |
233 | Res += "TB_EH_INFO " ; |
234 | if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2) |
235 | Res += "TB_LONGTBTABLE2 " ; |
236 | |
237 | // Two of the bits that haven't got used in the mask. |
238 | if (Flag & 0x06) |
239 | Res += "Unknown " ; |
240 | |
241 | // Pop the last space. |
242 | Res.pop_back(); |
243 | return Res; |
244 | } |
245 | |
246 | Expected<SmallString<32>> |
247 | XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, |
248 | unsigned FloatingParmsNum, |
249 | unsigned VectorParmsNum) { |
250 | SmallString<32> ParmsType; |
251 | |
252 | unsigned ParsedFixedNum = 0; |
253 | unsigned ParsedFloatingNum = 0; |
254 | unsigned ParsedVectorNum = 0; |
255 | unsigned ParsedNum = 0; |
256 | unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum; |
257 | |
258 | for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) { |
259 | if (++ParsedNum > 1) |
260 | ParmsType += ", " ; |
261 | |
262 | switch (Value & TracebackTable::ParmTypeMask) { |
263 | case TracebackTable::ParmTypeIsFixedBits: |
264 | ParmsType += "i" ; |
265 | ++ParsedFixedNum; |
266 | break; |
267 | case TracebackTable::ParmTypeIsVectorBits: |
268 | ParmsType += "v" ; |
269 | ++ParsedVectorNum; |
270 | break; |
271 | case TracebackTable::ParmTypeIsFloatingBits: |
272 | ParmsType += "f" ; |
273 | ++ParsedFloatingNum; |
274 | break; |
275 | case TracebackTable::ParmTypeIsDoubleBits: |
276 | ParmsType += "d" ; |
277 | ++ParsedFloatingNum; |
278 | break; |
279 | default: |
280 | assert(false && "Unrecognized bits in ParmsType." ); |
281 | } |
282 | Value <<= 2; |
283 | } |
284 | |
285 | // We have more parameters than the 32 Bits could encode. |
286 | if (ParsedNum < ParmsNum) |
287 | ParmsType += ", ..." ; |
288 | |
289 | if (Value != 0u || ParsedFixedNum > FixedParmsNum || |
290 | ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum) |
291 | return createStringError( |
292 | EC: errc::invalid_argument, |
293 | S: "ParmsType encodes can not map to ParmsNum parameters " |
294 | "in parseParmsTypeWithVecInfo." ); |
295 | |
296 | return ParmsType; |
297 | } |
298 | |
299 | Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value, |
300 | unsigned ParmsNum) { |
301 | SmallString<32> ParmsType; |
302 | unsigned ParsedNum = 0; |
303 | for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) { |
304 | if (++ParsedNum > 1) |
305 | ParmsType += ", " ; |
306 | switch (Value & TracebackTable::ParmTypeMask) { |
307 | case TracebackTable::ParmTypeIsVectorCharBit: |
308 | ParmsType += "vc" ; |
309 | break; |
310 | |
311 | case TracebackTable::ParmTypeIsVectorShortBit: |
312 | ParmsType += "vs" ; |
313 | break; |
314 | |
315 | case TracebackTable::ParmTypeIsVectorIntBit: |
316 | ParmsType += "vi" ; |
317 | break; |
318 | |
319 | case TracebackTable::ParmTypeIsVectorFloatBit: |
320 | ParmsType += "vf" ; |
321 | break; |
322 | } |
323 | |
324 | Value <<= 2; |
325 | } |
326 | |
327 | // We have more parameters than the 32 Bits could encode. |
328 | if (ParsedNum < ParmsNum) |
329 | ParmsType += ", ..." ; |
330 | |
331 | if (Value != 0u) |
332 | return createStringError(EC: errc::invalid_argument, |
333 | S: "ParmsType encodes more than ParmsNum parameters " |
334 | "in parseVectorParmsType." ); |
335 | return ParmsType; |
336 | } |
337 | |