xref: /llvm-project/llvm/lib/BinaryFormat/XCOFF.cpp (revision f31099ce581d33fdb64e35fee4b56d0a1145cab1)
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("generic", "COM", XCOFF::TCPU_COM)
116       .Case("601", XCOFF::TCPU_601)
117       .Cases("602", "603", "603e", "603ev", XCOFF::TCPU_603)
118       .Cases("604", "604e", XCOFF::TCPU_604)
119       .Case("620", XCOFF::TCPU_620)
120       .Case("970", XCOFF::TCPU_970)
121       .Cases("a2", "g3", "g4", "g5", "e500", XCOFF::TCPU_COM)
122       .Cases("pwr3", "pwr4", XCOFF::TCPU_COM)
123       .Cases("pwr5", "PWR5", XCOFF::TCPU_PWR5)
124       .Cases("pwr5x", "PWR5X", XCOFF::TCPU_PWR5X)
125       .Cases("pwr6", "PWR6", XCOFF::TCPU_PWR6)
126       .Cases("pwr6x", "PWR6E", XCOFF::TCPU_PWR6E)
127       .Cases("pwr7", "PWR7", XCOFF::TCPU_PWR7)
128       .Cases("pwr8", "PWR8", XCOFF::TCPU_PWR8)
129       .Cases("pwr9", "PWR9", XCOFF::TCPU_PWR9)
130       .Cases("pwr10", "PWR10", XCOFF::TCPU_PWR10)
131       .Cases("ppc", "PPC", "ppc32", "ppc64", XCOFF::TCPU_COM)
132       .Case("ppc64le", XCOFF::TCPU_PWR8)
133       .Case("future", XCOFF::TCPU_PWR10)
134       .Cases("any", "ANY", XCOFF::TCPU_ANY)
135       .Default(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(errc::invalid_argument,
216                              "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         errc::invalid_argument,
293         "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(errc::invalid_argument,
333                              "ParmsType encodes more than ParmsNum parameters "
334                              "in parseVectorParmsType.");
335   return ParmsType;
336 }
337