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(errc::invalid_argument,
157                              "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         errc::invalid_argument,
234         "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(errc::invalid_argument,
274                              "ParmsType encodes more than ParmsNum parameters "
275                              "in parseVectorParmsType.");
276   return ParmsType;
277 }
278