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