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
17using namespace llvm;
18
19#define SMC_CASE(A) \
20 case XCOFF::XMC_##A: \
21 return #A;
22StringRef 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;
55StringRef 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
89StringRef 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
112XCOFF::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;
141StringRef 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
169Expected<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
221SmallString<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
246Expected<SmallString<32>>
247XCOFF::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
299Expected<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