|  | //===-- llvm/BinaryFormat/XCOFF.cpp - The XCOFF file format -----*- C++/-*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/BinaryFormat/XCOFF.h" | 
|  | #include "llvm/ADT/SmallString.h" | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/Support/Errc.h" | 
|  | #include "llvm/Support/Error.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define SMC_CASE(A)                                                            \ | 
|  | case XCOFF::XMC_##A:                                                         \ | 
|  | return #A; | 
|  | StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) { | 
|  | switch (SMC) { | 
|  | SMC_CASE(PR) | 
|  | SMC_CASE(RO) | 
|  | SMC_CASE(DB) | 
|  | SMC_CASE(GL) | 
|  | SMC_CASE(XO) | 
|  | SMC_CASE(SV) | 
|  | SMC_CASE(SV64) | 
|  | SMC_CASE(SV3264) | 
|  | SMC_CASE(TI) | 
|  | SMC_CASE(TB) | 
|  | SMC_CASE(RW) | 
|  | SMC_CASE(TC0) | 
|  | SMC_CASE(TC) | 
|  | SMC_CASE(TD) | 
|  | SMC_CASE(DS) | 
|  | SMC_CASE(UA) | 
|  | SMC_CASE(BS) | 
|  | SMC_CASE(UC) | 
|  | SMC_CASE(TL) | 
|  | SMC_CASE(UL) | 
|  | SMC_CASE(TE) | 
|  | #undef SMC_CASE | 
|  | } | 
|  |  | 
|  | // TODO: need to add a test case for "Unknown" and other SMC. | 
|  | return "Unknown"; | 
|  | } | 
|  |  | 
|  | #define RELOC_CASE(A)                                                          \ | 
|  | case XCOFF::A:                                                               \ | 
|  | return #A; | 
|  | StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) { | 
|  | switch (Type) { | 
|  | RELOC_CASE(R_POS) | 
|  | RELOC_CASE(R_RL) | 
|  | RELOC_CASE(R_RLA) | 
|  | RELOC_CASE(R_NEG) | 
|  | RELOC_CASE(R_REL) | 
|  | RELOC_CASE(R_TOC) | 
|  | RELOC_CASE(R_TRL) | 
|  | RELOC_CASE(R_TRLA) | 
|  | RELOC_CASE(R_GL) | 
|  | RELOC_CASE(R_TCL) | 
|  | RELOC_CASE(R_REF) | 
|  | RELOC_CASE(R_BA) | 
|  | RELOC_CASE(R_BR) | 
|  | RELOC_CASE(R_RBA) | 
|  | RELOC_CASE(R_RBR) | 
|  | RELOC_CASE(R_TLS) | 
|  | RELOC_CASE(R_TLS_IE) | 
|  | RELOC_CASE(R_TLS_LD) | 
|  | RELOC_CASE(R_TLS_LE) | 
|  | RELOC_CASE(R_TLSM) | 
|  | RELOC_CASE(R_TLSML) | 
|  | RELOC_CASE(R_TOCU) | 
|  | RELOC_CASE(R_TOCL) | 
|  | } | 
|  | return "Unknown"; | 
|  | } | 
|  | #undef RELOC_CASE | 
|  |  | 
|  | #define LANG_CASE(A)                                                           \ | 
|  | case XCOFF::TracebackTable::A:                                               \ | 
|  | return #A; | 
|  |  | 
|  | StringRef XCOFF::getNameForTracebackTableLanguageId( | 
|  | XCOFF::TracebackTable::LanguageID LangId) { | 
|  | switch (LangId) { | 
|  | LANG_CASE(C) | 
|  | LANG_CASE(Fortran) | 
|  | LANG_CASE(Pascal) | 
|  | LANG_CASE(Ada) | 
|  | LANG_CASE(PL1) | 
|  | LANG_CASE(Basic) | 
|  | LANG_CASE(Lisp) | 
|  | LANG_CASE(Cobol) | 
|  | LANG_CASE(Modula2) | 
|  | LANG_CASE(Rpg) | 
|  | LANG_CASE(PL8) | 
|  | LANG_CASE(Assembly) | 
|  | LANG_CASE(Java) | 
|  | LANG_CASE(ObjectiveC) | 
|  | LANG_CASE(CPlusPlus) | 
|  | } | 
|  | return "Unknown"; | 
|  | } | 
|  | #undef LANG_CASE | 
|  |  | 
|  | Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value, | 
|  | unsigned FixedParmsNum, | 
|  | unsigned FloatingParmsNum) { | 
|  | SmallString<32> ParmsType; | 
|  | int Bits = 0; | 
|  | unsigned ParsedFixedNum = 0; | 
|  | unsigned ParsedFloatingNum = 0; | 
|  | unsigned ParsedNum = 0; | 
|  | unsigned ParmsNum = FixedParmsNum + FloatingParmsNum; | 
|  |  | 
|  | // In the function PPCFunctionInfo::getParmsType(), when there are no vector | 
|  | // parameters, the 31st bit of ParmsType is always zero even if it indicates a | 
|  | // floating point parameter. The parameter type information is lost. There | 
|  | // are only 8 GPRs used for parameters passing, the floating parameters | 
|  | // also occupy GPRs if there are available, so the 31st bit can never be a | 
|  | // fixed parameter. At the same time, we also do not know whether the zero of | 
|  | // the 31st bit indicates a float or double parameter type here. Therefore, we | 
|  | // ignore the 31st bit. | 
|  | while (Bits < 31 && ParsedNum < ParmsNum) { | 
|  | if (++ParsedNum > 1) | 
|  | ParmsType += ", "; | 
|  | if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) { | 
|  | // Fixed parameter type. | 
|  | ParmsType += "i"; | 
|  | ++ParsedFixedNum; | 
|  | Value <<= 1; | 
|  | ++Bits; | 
|  | } else { | 
|  | if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0) | 
|  | // Float parameter type. | 
|  | ParmsType += "f"; | 
|  | else | 
|  | // Double parameter type. | 
|  | ParmsType += "d"; | 
|  | ++ParsedFloatingNum; | 
|  | Value <<= 2; | 
|  | Bits += 2; | 
|  | } | 
|  | } | 
|  |  | 
|  | // We have more parameters than the 32 Bits could encode. | 
|  | if (ParsedNum < ParmsNum) | 
|  | ParmsType += ", ..."; | 
|  |  | 
|  | if (Value != 0u || ParsedFixedNum > FixedParmsNum || | 
|  | ParsedFloatingNum > FloatingParmsNum) | 
|  | return createStringError(errc::invalid_argument, | 
|  | "ParmsType encodes can not map to ParmsNum " | 
|  | "parameters in parseParmsType."); | 
|  | return ParmsType; | 
|  | } | 
|  |  | 
|  | SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) { | 
|  | SmallString<32> Res; | 
|  |  | 
|  | if (Flag & ExtendedTBTableFlag::TB_OS1) | 
|  | Res += "TB_OS1 "; | 
|  | if (Flag & ExtendedTBTableFlag::TB_RESERVED) | 
|  | Res += "TB_RESERVED "; | 
|  | if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY) | 
|  | Res += "TB_SSP_CANARY "; | 
|  | if (Flag & ExtendedTBTableFlag::TB_OS2) | 
|  | Res += "TB_OS2 "; | 
|  | if (Flag & ExtendedTBTableFlag::TB_EH_INFO) | 
|  | Res += "TB_EH_INFO "; | 
|  | if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2) | 
|  | Res += "TB_LONGTBTABLE2 "; | 
|  |  | 
|  | // Two of the bits that haven't got used in the mask. | 
|  | if (Flag & 0x06) | 
|  | Res += "Unknown "; | 
|  |  | 
|  | // Pop the last space. | 
|  | Res.pop_back(); | 
|  | return Res; | 
|  | } | 
|  |  | 
|  | Expected<SmallString<32>> | 
|  | XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, | 
|  | unsigned FloatingParmsNum, | 
|  | unsigned VectorParmsNum) { | 
|  | SmallString<32> ParmsType; | 
|  |  | 
|  | unsigned ParsedFixedNum = 0; | 
|  | unsigned ParsedFloatingNum = 0; | 
|  | unsigned ParsedVectorNum = 0; | 
|  | unsigned ParsedNum = 0; | 
|  | unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum; | 
|  |  | 
|  | for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) { | 
|  | if (++ParsedNum > 1) | 
|  | ParmsType += ", "; | 
|  |  | 
|  | switch (Value & TracebackTable::ParmTypeMask) { | 
|  | case TracebackTable::ParmTypeIsFixedBits: | 
|  | ParmsType += "i"; | 
|  | ++ParsedFixedNum; | 
|  | break; | 
|  | case TracebackTable::ParmTypeIsVectorBits: | 
|  | ParmsType += "v"; | 
|  | ++ParsedVectorNum; | 
|  | break; | 
|  | case TracebackTable::ParmTypeIsFloatingBits: | 
|  | ParmsType += "f"; | 
|  | ++ParsedFloatingNum; | 
|  | break; | 
|  | case TracebackTable::ParmTypeIsDoubleBits: | 
|  | ParmsType += "d"; | 
|  | ++ParsedFloatingNum; | 
|  | break; | 
|  | default: | 
|  | assert(false && "Unrecognized bits in ParmsType."); | 
|  | } | 
|  | Value <<= 2; | 
|  | } | 
|  |  | 
|  | // We have more parameters than the 32 Bits could encode. | 
|  | if (ParsedNum < ParmsNum) | 
|  | ParmsType += ", ..."; | 
|  |  | 
|  | if (Value != 0u || ParsedFixedNum > FixedParmsNum || | 
|  | ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum) | 
|  | return createStringError( | 
|  | errc::invalid_argument, | 
|  | "ParmsType encodes can not map to ParmsNum parameters " | 
|  | "in parseParmsTypeWithVecInfo."); | 
|  |  | 
|  | return ParmsType; | 
|  | } | 
|  |  | 
|  | Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value, | 
|  | unsigned ParmsNum) { | 
|  | SmallString<32> ParmsType; | 
|  | unsigned ParsedNum = 0; | 
|  | for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) { | 
|  | if (++ParsedNum > 1) | 
|  | ParmsType += ", "; | 
|  | switch (Value & TracebackTable::ParmTypeMask) { | 
|  | case TracebackTable::ParmTypeIsVectorCharBit: | 
|  | ParmsType += "vc"; | 
|  | break; | 
|  |  | 
|  | case TracebackTable::ParmTypeIsVectorShortBit: | 
|  | ParmsType += "vs"; | 
|  | break; | 
|  |  | 
|  | case TracebackTable::ParmTypeIsVectorIntBit: | 
|  | ParmsType += "vi"; | 
|  | break; | 
|  |  | 
|  | case TracebackTable::ParmTypeIsVectorFloatBit: | 
|  | ParmsType += "vf"; | 
|  | break; | 
|  | } | 
|  |  | 
|  | Value <<= 2; | 
|  | } | 
|  |  | 
|  | // We have more parameters than the 32 Bits could encode. | 
|  | if (ParsedNum < ParmsNum) | 
|  | ParmsType += ", ..."; | 
|  |  | 
|  | if (Value != 0u) | 
|  | return createStringError(errc::invalid_argument, | 
|  | "ParmsType encodes more than ParmsNum parameters " | 
|  | "in parseVectorParmsType."); | 
|  | return ParmsType; | 
|  | } |