xref: /llvm-project/llvm/lib/BinaryFormat/XCOFF.cpp (revision f31099ce581d33fdb64e35fee4b56d0a1145cab1)
10dc0572bSJason Liu //===-- llvm/BinaryFormat/XCOFF.cpp - The XCOFF file format -----*- C++/-*-===//
20dc0572bSJason Liu //
30dc0572bSJason Liu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40dc0572bSJason Liu // See https://llvm.org/LICENSE.txt for license information.
50dc0572bSJason Liu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60dc0572bSJason Liu //
70dc0572bSJason Liu //===----------------------------------------------------------------------===//
80dc0572bSJason Liu 
90dc0572bSJason Liu #include "llvm/BinaryFormat/XCOFF.h"
10997d286fSdiggerlin #include "llvm/ADT/SmallString.h"
117c5fc400SSimon Pilgrim #include "llvm/ADT/StringRef.h"
12*f31099ceSAmy Kwan #include "llvm/ADT/StringSwitch.h"
137ed515d1Szhijian #include "llvm/Support/Errc.h"
147ed515d1Szhijian #include "llvm/Support/Error.h"
15*f31099ceSAmy Kwan #include "llvm/TargetParser/PPCTargetParser.h"
160dc0572bSJason Liu 
170dc0572bSJason Liu using namespace llvm;
180dc0572bSJason Liu 
19a26a441bSdiggerlin #define SMC_CASE(A)                                                            \
20a26a441bSdiggerlin   case XCOFF::XMC_##A:                                                         \
21a26a441bSdiggerlin     return #A;
220dc0572bSJason Liu StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) {
230dc0572bSJason Liu   switch (SMC) {
24a26a441bSdiggerlin     SMC_CASE(PR)
25a26a441bSdiggerlin     SMC_CASE(RO)
26a26a441bSdiggerlin     SMC_CASE(DB)
27a26a441bSdiggerlin     SMC_CASE(GL)
28a26a441bSdiggerlin     SMC_CASE(XO)
29a26a441bSdiggerlin     SMC_CASE(SV)
30a26a441bSdiggerlin     SMC_CASE(SV64)
31a26a441bSdiggerlin     SMC_CASE(SV3264)
32a26a441bSdiggerlin     SMC_CASE(TI)
33a26a441bSdiggerlin     SMC_CASE(TB)
34a26a441bSdiggerlin     SMC_CASE(RW)
35a26a441bSdiggerlin     SMC_CASE(TC0)
36a26a441bSdiggerlin     SMC_CASE(TC)
37a26a441bSdiggerlin     SMC_CASE(TD)
38a26a441bSdiggerlin     SMC_CASE(DS)
39a26a441bSdiggerlin     SMC_CASE(UA)
40a26a441bSdiggerlin     SMC_CASE(BS)
41a26a441bSdiggerlin     SMC_CASE(UC)
42a26a441bSdiggerlin     SMC_CASE(TL)
43a26a441bSdiggerlin     SMC_CASE(UL)
44a26a441bSdiggerlin     SMC_CASE(TE)
45a26a441bSdiggerlin #undef SMC_CASE
460dc0572bSJason Liu   }
47a26a441bSdiggerlin 
48a26a441bSdiggerlin   // TODO: need to add a test case for "Unknown" and other SMC.
49a26a441bSdiggerlin   return "Unknown";
500dc0572bSJason Liu }
51d60d7d69Sjasonliu 
52d60d7d69Sjasonliu #define RELOC_CASE(A)                                                          \
53d60d7d69Sjasonliu   case XCOFF::A:                                                               \
54d60d7d69Sjasonliu     return #A;
55d60d7d69Sjasonliu StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) {
56d60d7d69Sjasonliu   switch (Type) {
57d60d7d69Sjasonliu     RELOC_CASE(R_POS)
58d60d7d69Sjasonliu     RELOC_CASE(R_RL)
59d60d7d69Sjasonliu     RELOC_CASE(R_RLA)
60d60d7d69Sjasonliu     RELOC_CASE(R_NEG)
61d60d7d69Sjasonliu     RELOC_CASE(R_REL)
62d60d7d69Sjasonliu     RELOC_CASE(R_TOC)
63d60d7d69Sjasonliu     RELOC_CASE(R_TRL)
64d60d7d69Sjasonliu     RELOC_CASE(R_TRLA)
65d60d7d69Sjasonliu     RELOC_CASE(R_GL)
66d60d7d69Sjasonliu     RELOC_CASE(R_TCL)
67d60d7d69Sjasonliu     RELOC_CASE(R_REF)
68d60d7d69Sjasonliu     RELOC_CASE(R_BA)
69d60d7d69Sjasonliu     RELOC_CASE(R_BR)
70d60d7d69Sjasonliu     RELOC_CASE(R_RBA)
71d60d7d69Sjasonliu     RELOC_CASE(R_RBR)
72d60d7d69Sjasonliu     RELOC_CASE(R_TLS)
73d60d7d69Sjasonliu     RELOC_CASE(R_TLS_IE)
74d60d7d69Sjasonliu     RELOC_CASE(R_TLS_LD)
75d60d7d69Sjasonliu     RELOC_CASE(R_TLS_LE)
76d60d7d69Sjasonliu     RELOC_CASE(R_TLSM)
77d60d7d69Sjasonliu     RELOC_CASE(R_TLSML)
78d60d7d69Sjasonliu     RELOC_CASE(R_TOCU)
79d60d7d69Sjasonliu     RELOC_CASE(R_TOCL)
80d60d7d69Sjasonliu   }
81d60d7d69Sjasonliu   return "Unknown";
82d60d7d69Sjasonliu }
837ed515d1Szhijian #undef RELOC_CASE
84997d286fSdiggerlin 
85997d286fSdiggerlin #define LANG_CASE(A)                                                           \
86997d286fSdiggerlin   case XCOFF::TracebackTable::A:                                               \
87997d286fSdiggerlin     return #A;
88997d286fSdiggerlin 
89997d286fSdiggerlin StringRef XCOFF::getNameForTracebackTableLanguageId(
90997d286fSdiggerlin     XCOFF::TracebackTable::LanguageID LangId) {
91997d286fSdiggerlin   switch (LangId) {
92997d286fSdiggerlin     LANG_CASE(C)
93997d286fSdiggerlin     LANG_CASE(Fortran)
94997d286fSdiggerlin     LANG_CASE(Pascal)
95997d286fSdiggerlin     LANG_CASE(Ada)
96997d286fSdiggerlin     LANG_CASE(PL1)
97997d286fSdiggerlin     LANG_CASE(Basic)
98997d286fSdiggerlin     LANG_CASE(Lisp)
99997d286fSdiggerlin     LANG_CASE(Cobol)
100997d286fSdiggerlin     LANG_CASE(Modula2)
101997d286fSdiggerlin     LANG_CASE(Rpg)
102997d286fSdiggerlin     LANG_CASE(PL8)
103997d286fSdiggerlin     LANG_CASE(Assembly)
104997d286fSdiggerlin     LANG_CASE(Java)
105997d286fSdiggerlin     LANG_CASE(ObjectiveC)
106997d286fSdiggerlin     LANG_CASE(CPlusPlus)
107997d286fSdiggerlin   }
108997d286fSdiggerlin   return "Unknown";
109997d286fSdiggerlin }
110997d286fSdiggerlin #undef LANG_CASE
111997d286fSdiggerlin 
112*f31099ceSAmy Kwan XCOFF::CFileCpuId XCOFF::getCpuID(StringRef CPUName) {
113*f31099ceSAmy Kwan   StringRef CPU = PPC::normalizeCPUName(CPUName);
114*f31099ceSAmy Kwan   return StringSwitch<XCOFF::CFileCpuId>(CPU)
115*f31099ceSAmy Kwan       .Cases("generic", "COM", XCOFF::TCPU_COM)
116*f31099ceSAmy Kwan       .Case("601", XCOFF::TCPU_601)
117*f31099ceSAmy Kwan       .Cases("602", "603", "603e", "603ev", XCOFF::TCPU_603)
118*f31099ceSAmy Kwan       .Cases("604", "604e", XCOFF::TCPU_604)
119*f31099ceSAmy Kwan       .Case("620", XCOFF::TCPU_620)
120*f31099ceSAmy Kwan       .Case("970", XCOFF::TCPU_970)
121*f31099ceSAmy Kwan       .Cases("a2", "g3", "g4", "g5", "e500", XCOFF::TCPU_COM)
122*f31099ceSAmy Kwan       .Cases("pwr3", "pwr4", XCOFF::TCPU_COM)
123*f31099ceSAmy Kwan       .Cases("pwr5", "PWR5", XCOFF::TCPU_PWR5)
124*f31099ceSAmy Kwan       .Cases("pwr5x", "PWR5X", XCOFF::TCPU_PWR5X)
125*f31099ceSAmy Kwan       .Cases("pwr6", "PWR6", XCOFF::TCPU_PWR6)
126*f31099ceSAmy Kwan       .Cases("pwr6x", "PWR6E", XCOFF::TCPU_PWR6E)
127*f31099ceSAmy Kwan       .Cases("pwr7", "PWR7", XCOFF::TCPU_PWR7)
128*f31099ceSAmy Kwan       .Cases("pwr8", "PWR8", XCOFF::TCPU_PWR8)
129*f31099ceSAmy Kwan       .Cases("pwr9", "PWR9", XCOFF::TCPU_PWR9)
130*f31099ceSAmy Kwan       .Cases("pwr10", "PWR10", XCOFF::TCPU_PWR10)
131*f31099ceSAmy Kwan       .Cases("ppc", "PPC", "ppc32", "ppc64", XCOFF::TCPU_COM)
132*f31099ceSAmy Kwan       .Case("ppc64le", XCOFF::TCPU_PWR8)
133*f31099ceSAmy Kwan       .Case("future", XCOFF::TCPU_PWR10)
134*f31099ceSAmy Kwan       .Cases("any", "ANY", XCOFF::TCPU_ANY)
135*f31099ceSAmy Kwan       .Default(XCOFF::TCPU_INVALID);
136*f31099ceSAmy Kwan }
137*f31099ceSAmy Kwan 
138*f31099ceSAmy Kwan #define TCPU_CASE(A)                                                           \
139*f31099ceSAmy Kwan   case XCOFF::TCPU_##A:                                                        \
140*f31099ceSAmy Kwan     return #A;
141*f31099ceSAmy Kwan StringRef XCOFF::getTCPUString(XCOFF::CFileCpuId TCPU) {
142*f31099ceSAmy Kwan   switch (TCPU) {
143*f31099ceSAmy Kwan     TCPU_CASE(INVALID)
144*f31099ceSAmy Kwan     TCPU_CASE(PPC)
145*f31099ceSAmy Kwan     TCPU_CASE(PPC64)
146*f31099ceSAmy Kwan     TCPU_CASE(COM)
147*f31099ceSAmy Kwan     TCPU_CASE(PWR)
148*f31099ceSAmy Kwan     TCPU_CASE(ANY)
149*f31099ceSAmy Kwan     TCPU_CASE(601)
150*f31099ceSAmy Kwan     TCPU_CASE(603)
151*f31099ceSAmy Kwan     TCPU_CASE(604)
152*f31099ceSAmy Kwan     TCPU_CASE(620)
153*f31099ceSAmy Kwan     TCPU_CASE(A35)
154*f31099ceSAmy Kwan     TCPU_CASE(PWR5)
155*f31099ceSAmy Kwan     TCPU_CASE(970)
156*f31099ceSAmy Kwan     TCPU_CASE(PWR6)
157*f31099ceSAmy Kwan     TCPU_CASE(PWR5X)
158*f31099ceSAmy Kwan     TCPU_CASE(PWR6E)
159*f31099ceSAmy Kwan     TCPU_CASE(PWR7)
160*f31099ceSAmy Kwan     TCPU_CASE(PWR8)
161*f31099ceSAmy Kwan     TCPU_CASE(PWR9)
162*f31099ceSAmy Kwan     TCPU_CASE(PWR10)
163*f31099ceSAmy Kwan     TCPU_CASE(PWRX)
164*f31099ceSAmy Kwan   }
165*f31099ceSAmy Kwan   return "INVALID";
166*f31099ceSAmy Kwan }
167*f31099ceSAmy Kwan #undef TCPU_CASE
168*f31099ceSAmy Kwan 
1697ed515d1Szhijian Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value,
1707ed515d1Szhijian                                                 unsigned FixedParmsNum,
1717ed515d1Szhijian                                                 unsigned FloatingParmsNum) {
172997d286fSdiggerlin   SmallString<32> ParmsType;
1737ed515d1Szhijian   int Bits = 0;
1747ed515d1Szhijian   unsigned ParsedFixedNum = 0;
1757ed515d1Szhijian   unsigned ParsedFloatingNum = 0;
1767ed515d1Szhijian   unsigned ParsedNum = 0;
1777ed515d1Szhijian   unsigned ParmsNum = FixedParmsNum + FloatingParmsNum;
1787ed515d1Szhijian 
179af06f7bcSzhijian   // In the function PPCFunctionInfo::getParmsType(), when there are no vector
180af06f7bcSzhijian   // parameters, the 31st bit of ParmsType is always zero even if it indicates a
181af06f7bcSzhijian   // floating point parameter. The parameter type information is lost. There
182af06f7bcSzhijian   // are only 8 GPRs used for parameters passing, the floating parameters
183af06f7bcSzhijian   // also occupy GPRs if there are available, so the 31st bit can never be a
184af06f7bcSzhijian   // fixed parameter. At the same time, we also do not know whether the zero of
185af06f7bcSzhijian   // the 31st bit indicates a float or double parameter type here. Therefore, we
186af06f7bcSzhijian   // ignore the 31st bit.
187af06f7bcSzhijian   while (Bits < 31 && ParsedNum < ParmsNum) {
1887ed515d1Szhijian     if (++ParsedNum > 1)
189997d286fSdiggerlin       ParmsType += ", ";
190997d286fSdiggerlin     if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) {
191997d286fSdiggerlin       // Fixed parameter type.
192997d286fSdiggerlin       ParmsType += "i";
1937ed515d1Szhijian       ++ParsedFixedNum;
194997d286fSdiggerlin       Value <<= 1;
1957ed515d1Szhijian       ++Bits;
196997d286fSdiggerlin     } else {
197997d286fSdiggerlin       if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0)
198997d286fSdiggerlin         // Float parameter type.
199997d286fSdiggerlin         ParmsType += "f";
200997d286fSdiggerlin       else
201997d286fSdiggerlin         // Double parameter type.
202997d286fSdiggerlin         ParmsType += "d";
2037ed515d1Szhijian       ++ParsedFloatingNum;
204997d286fSdiggerlin       Value <<= 2;
2057ed515d1Szhijian       Bits += 2;
206997d286fSdiggerlin     }
207997d286fSdiggerlin   }
2087ed515d1Szhijian 
2097ed515d1Szhijian   // We have more parameters than the 32 Bits could encode.
2107ed515d1Szhijian   if (ParsedNum < ParmsNum)
2117ed515d1Szhijian     ParmsType += ", ...";
2127ed515d1Szhijian 
2137ed515d1Szhijian   if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
2147ed515d1Szhijian       ParsedFloatingNum > FloatingParmsNum)
2157ed515d1Szhijian     return createStringError(errc::invalid_argument,
2167ed515d1Szhijian                              "ParmsType encodes can not map to ParmsNum "
2177ed515d1Szhijian                              "parameters in parseParmsType.");
218997d286fSdiggerlin   return ParmsType;
219997d286fSdiggerlin }
220997d286fSdiggerlin 
221a1e1dcabSdiggerlin SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) {
222a1e1dcabSdiggerlin   SmallString<32> Res;
223a1e1dcabSdiggerlin 
224a1e1dcabSdiggerlin   if (Flag & ExtendedTBTableFlag::TB_OS1)
225a1e1dcabSdiggerlin     Res += "TB_OS1 ";
226a1e1dcabSdiggerlin   if (Flag & ExtendedTBTableFlag::TB_RESERVED)
227a1e1dcabSdiggerlin     Res += "TB_RESERVED ";
228a1e1dcabSdiggerlin   if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY)
229a1e1dcabSdiggerlin     Res += "TB_SSP_CANARY ";
230a1e1dcabSdiggerlin   if (Flag & ExtendedTBTableFlag::TB_OS2)
231a1e1dcabSdiggerlin     Res += "TB_OS2 ";
232a1e1dcabSdiggerlin   if (Flag & ExtendedTBTableFlag::TB_EH_INFO)
233a1e1dcabSdiggerlin     Res += "TB_EH_INFO ";
234a1e1dcabSdiggerlin   if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2)
235a1e1dcabSdiggerlin     Res += "TB_LONGTBTABLE2 ";
236a1e1dcabSdiggerlin 
237a1e1dcabSdiggerlin   // Two of the bits that haven't got used in the mask.
238a1e1dcabSdiggerlin   if (Flag & 0x06)
239a1e1dcabSdiggerlin     Res += "Unknown ";
240a1e1dcabSdiggerlin 
241a1e1dcabSdiggerlin   // Pop the last space.
242a1e1dcabSdiggerlin   Res.pop_back();
243a1e1dcabSdiggerlin   return Res;
244a1e1dcabSdiggerlin }
245a1e1dcabSdiggerlin 
2467ed515d1Szhijian Expected<SmallString<32>>
2477ed515d1Szhijian XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum,
2487ed515d1Szhijian                                  unsigned FloatingParmsNum,
2497ed515d1Szhijian                                  unsigned VectorParmsNum) {
2507ed515d1Szhijian   SmallString<32> ParmsType;
2517ed515d1Szhijian 
2527ed515d1Szhijian   unsigned ParsedFixedNum = 0;
2537ed515d1Szhijian   unsigned ParsedFloatingNum = 0;
2547ed515d1Szhijian   unsigned ParsedVectorNum = 0;
2557ed515d1Szhijian   unsigned ParsedNum = 0;
2567ed515d1Szhijian   unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum;
2577ed515d1Szhijian 
2587ed515d1Szhijian   for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) {
2597ed515d1Szhijian     if (++ParsedNum > 1)
2607ed515d1Szhijian       ParmsType += ", ";
2617ed515d1Szhijian 
2627ed515d1Szhijian     switch (Value & TracebackTable::ParmTypeMask) {
2637ed515d1Szhijian     case TracebackTable::ParmTypeIsFixedBits:
2647ed515d1Szhijian       ParmsType += "i";
2657ed515d1Szhijian       ++ParsedFixedNum;
2667ed515d1Szhijian       break;
2677ed515d1Szhijian     case TracebackTable::ParmTypeIsVectorBits:
2687ed515d1Szhijian       ParmsType += "v";
2697ed515d1Szhijian       ++ParsedVectorNum;
2707ed515d1Szhijian       break;
2717ed515d1Szhijian     case TracebackTable::ParmTypeIsFloatingBits:
2727ed515d1Szhijian       ParmsType += "f";
2737ed515d1Szhijian       ++ParsedFloatingNum;
2747ed515d1Szhijian       break;
2757ed515d1Szhijian     case TracebackTable::ParmTypeIsDoubleBits:
2767ed515d1Szhijian       ParmsType += "d";
2777ed515d1Szhijian       ++ParsedFloatingNum;
2787ed515d1Szhijian       break;
2797ed515d1Szhijian     default:
2807ed515d1Szhijian       assert(false && "Unrecognized bits in ParmsType.");
2817ed515d1Szhijian     }
2827ed515d1Szhijian     Value <<= 2;
2837ed515d1Szhijian   }
2847ed515d1Szhijian 
2857ed515d1Szhijian   // We have more parameters than the 32 Bits could encode.
2867ed515d1Szhijian   if (ParsedNum < ParmsNum)
2877ed515d1Szhijian     ParmsType += ", ...";
2887ed515d1Szhijian 
2897ed515d1Szhijian   if (Value != 0u || ParsedFixedNum > FixedParmsNum ||
2907ed515d1Szhijian       ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum)
2917ed515d1Szhijian     return createStringError(
2927ed515d1Szhijian         errc::invalid_argument,
2937ed515d1Szhijian         "ParmsType encodes can not map to ParmsNum parameters "
2947ed515d1Szhijian         "in parseParmsTypeWithVecInfo.");
2957ed515d1Szhijian 
2967ed515d1Szhijian   return ParmsType;
2977ed515d1Szhijian }
2987ed515d1Szhijian 
2997ed515d1Szhijian Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value,
3007ed515d1Szhijian                                                       unsigned ParmsNum) {
3017ed515d1Szhijian   SmallString<32> ParmsType;
3027ed515d1Szhijian   unsigned ParsedNum = 0;
3037ed515d1Szhijian   for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) {
3047ed515d1Szhijian     if (++ParsedNum > 1)
3057ed515d1Szhijian       ParmsType += ", ";
3067ed515d1Szhijian     switch (Value & TracebackTable::ParmTypeMask) {
3077ed515d1Szhijian     case TracebackTable::ParmTypeIsVectorCharBit:
3087ed515d1Szhijian       ParmsType += "vc";
3097ed515d1Szhijian       break;
3107ed515d1Szhijian 
3117ed515d1Szhijian     case TracebackTable::ParmTypeIsVectorShortBit:
3127ed515d1Szhijian       ParmsType += "vs";
3137ed515d1Szhijian       break;
3147ed515d1Szhijian 
3157ed515d1Szhijian     case TracebackTable::ParmTypeIsVectorIntBit:
3167ed515d1Szhijian       ParmsType += "vi";
3177ed515d1Szhijian       break;
3187ed515d1Szhijian 
3197ed515d1Szhijian     case TracebackTable::ParmTypeIsVectorFloatBit:
3207ed515d1Szhijian       ParmsType += "vf";
3217ed515d1Szhijian       break;
3227ed515d1Szhijian     }
3237ed515d1Szhijian 
3247ed515d1Szhijian     Value <<= 2;
3257ed515d1Szhijian   }
3267ed515d1Szhijian 
3277ed515d1Szhijian   // We have more parameters than the 32 Bits could encode.
3287ed515d1Szhijian   if (ParsedNum < ParmsNum)
3297ed515d1Szhijian     ParmsType += ", ...";
3307ed515d1Szhijian 
3317ed515d1Szhijian   if (Value != 0u)
3327ed515d1Szhijian     return createStringError(errc::invalid_argument,
3337ed515d1Szhijian                              "ParmsType encodes more than ParmsNum parameters "
3347ed515d1Szhijian                              "in parseVectorParmsType.");
3357ed515d1Szhijian   return ParmsType;
3367ed515d1Szhijian }
337