337 lines · cpp
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-exception6//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 17using namespace llvm;18 19#define SMC_CASE(A) \20 case XCOFF::XMC_##A: \21 return #A;22StringRef 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_CASE46 }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;55StringRef 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_CASE84 85#define LANG_CASE(A) \86 case XCOFF::TracebackTable::A: \87 return #A;88 89StringRef 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_CASE111 112XCOFF::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;141StringRef 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_CASE168 169Expected<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 vector180 // parameters, the 31st bit of ParmsType is always zero even if it indicates a181 // floating point parameter. The parameter type information is lost. There182 // are only 8 GPRs used for parameters passing, the floating parameters183 // also occupy GPRs if there are available, so the 31st bit can never be a184 // fixed parameter. At the same time, we also do not know whether the zero of185 // the 31st bit indicates a float or double parameter type here. Therefore, we186 // 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 else201 // 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 221SmallString<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 246Expected<SmallString<32>>247XCOFF::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 299Expected<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