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
15using namespace llvm;
16
17#define SMC_CASE(A) \
18 case XCOFF::XMC_##A: \
19 return #A;
20StringRef 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;
53StringRef 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
87StringRef 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
110Expected<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
162SmallString<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
187Expected<SmallString<32>>
188XCOFF::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
240Expected<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