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