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/Support/Errc.h" 13 #include "llvm/Support/Error.h" 14 15 using namespace llvm; 16 17 #define SMC_CASE(A) \ 18 case XCOFF::XMC_##A: \ 19 return #A; 20 StringRef XCOFF::getMappingClassString(XCOFF::StorageMappingClass SMC) { 21 switch (SMC) { 22 SMC_CASE(PR) 23 SMC_CASE(RO) 24 SMC_CASE(DB) 25 SMC_CASE(GL) 26 SMC_CASE(XO) 27 SMC_CASE(SV) 28 SMC_CASE(SV64) 29 SMC_CASE(SV3264) 30 SMC_CASE(TI) 31 SMC_CASE(TB) 32 SMC_CASE(RW) 33 SMC_CASE(TC0) 34 SMC_CASE(TC) 35 SMC_CASE(TD) 36 SMC_CASE(DS) 37 SMC_CASE(UA) 38 SMC_CASE(BS) 39 SMC_CASE(UC) 40 SMC_CASE(TL) 41 SMC_CASE(UL) 42 SMC_CASE(TE) 43 #undef SMC_CASE 44 } 45 46 // TODO: need to add a test case for "Unknown" and other SMC. 47 return "Unknown"; 48 } 49 50 #define RELOC_CASE(A) \ 51 case XCOFF::A: \ 52 return #A; 53 StringRef XCOFF::getRelocationTypeString(XCOFF::RelocationType Type) { 54 switch (Type) { 55 RELOC_CASE(R_POS) 56 RELOC_CASE(R_RL) 57 RELOC_CASE(R_RLA) 58 RELOC_CASE(R_NEG) 59 RELOC_CASE(R_REL) 60 RELOC_CASE(R_TOC) 61 RELOC_CASE(R_TRL) 62 RELOC_CASE(R_TRLA) 63 RELOC_CASE(R_GL) 64 RELOC_CASE(R_TCL) 65 RELOC_CASE(R_REF) 66 RELOC_CASE(R_BA) 67 RELOC_CASE(R_BR) 68 RELOC_CASE(R_RBA) 69 RELOC_CASE(R_RBR) 70 RELOC_CASE(R_TLS) 71 RELOC_CASE(R_TLS_IE) 72 RELOC_CASE(R_TLS_LD) 73 RELOC_CASE(R_TLS_LE) 74 RELOC_CASE(R_TLSM) 75 RELOC_CASE(R_TLSML) 76 RELOC_CASE(R_TOCU) 77 RELOC_CASE(R_TOCL) 78 } 79 return "Unknown"; 80 } 81 #undef RELOC_CASE 82 83 #define LANG_CASE(A) \ 84 case XCOFF::TracebackTable::A: \ 85 return #A; 86 87 StringRef XCOFF::getNameForTracebackTableLanguageId( 88 XCOFF::TracebackTable::LanguageID LangId) { 89 switch (LangId) { 90 LANG_CASE(C) 91 LANG_CASE(Fortran) 92 LANG_CASE(Pascal) 93 LANG_CASE(Ada) 94 LANG_CASE(PL1) 95 LANG_CASE(Basic) 96 LANG_CASE(Lisp) 97 LANG_CASE(Cobol) 98 LANG_CASE(Modula2) 99 LANG_CASE(Rpg) 100 LANG_CASE(PL8) 101 LANG_CASE(Assembly) 102 LANG_CASE(Java) 103 LANG_CASE(ObjectiveC) 104 LANG_CASE(CPlusPlus) 105 } 106 return "Unknown"; 107 } 108 #undef LANG_CASE 109 110 Expected<SmallString<32>> XCOFF::parseParmsType(uint32_t Value, 111 unsigned FixedParmsNum, 112 unsigned FloatingParmsNum) { 113 SmallString<32> ParmsType; 114 int Bits = 0; 115 unsigned ParsedFixedNum = 0; 116 unsigned ParsedFloatingNum = 0; 117 unsigned ParsedNum = 0; 118 unsigned ParmsNum = FixedParmsNum + FloatingParmsNum; 119 120 // In the function PPCFunctionInfo::getParmsType(), when there are no vector 121 // parameters, the 31st bit of ParmsType is always zero even if it indicates a 122 // floating point parameter. The parameter type information is lost. There 123 // are only 8 GPRs used for parameters passing, the floating parameters 124 // also occupy GPRs if there are available, so the 31st bit can never be a 125 // fixed parameter. At the same time, we also do not know whether the zero of 126 // the 31st bit indicates a float or double parameter type here. Therefore, we 127 // ignore the 31st bit. 128 while (Bits < 31 && ParsedNum < ParmsNum) { 129 if (++ParsedNum > 1) 130 ParmsType += ", "; 131 if ((Value & TracebackTable::ParmTypeIsFloatingBit) == 0) { 132 // Fixed parameter type. 133 ParmsType += "i"; 134 ++ParsedFixedNum; 135 Value <<= 1; 136 ++Bits; 137 } else { 138 if ((Value & TracebackTable::ParmTypeFloatingIsDoubleBit) == 0) 139 // Float parameter type. 140 ParmsType += "f"; 141 else 142 // Double parameter type. 143 ParmsType += "d"; 144 ++ParsedFloatingNum; 145 Value <<= 2; 146 Bits += 2; 147 } 148 } 149 150 // We have more parameters than the 32 Bits could encode. 151 if (ParsedNum < ParmsNum) 152 ParmsType += ", ..."; 153 154 if (Value != 0u || ParsedFixedNum > FixedParmsNum || 155 ParsedFloatingNum > FloatingParmsNum) 156 return createStringError(errc::invalid_argument, 157 "ParmsType encodes can not map to ParmsNum " 158 "parameters in parseParmsType."); 159 return ParmsType; 160 } 161 162 SmallString<32> XCOFF::getExtendedTBTableFlagString(uint8_t Flag) { 163 SmallString<32> Res; 164 165 if (Flag & ExtendedTBTableFlag::TB_OS1) 166 Res += "TB_OS1 "; 167 if (Flag & ExtendedTBTableFlag::TB_RESERVED) 168 Res += "TB_RESERVED "; 169 if (Flag & ExtendedTBTableFlag::TB_SSP_CANARY) 170 Res += "TB_SSP_CANARY "; 171 if (Flag & ExtendedTBTableFlag::TB_OS2) 172 Res += "TB_OS2 "; 173 if (Flag & ExtendedTBTableFlag::TB_EH_INFO) 174 Res += "TB_EH_INFO "; 175 if (Flag & ExtendedTBTableFlag::TB_LONGTBTABLE2) 176 Res += "TB_LONGTBTABLE2 "; 177 178 // Two of the bits that haven't got used in the mask. 179 if (Flag & 0x06) 180 Res += "Unknown "; 181 182 // Pop the last space. 183 Res.pop_back(); 184 return Res; 185 } 186 187 Expected<SmallString<32>> 188 XCOFF::parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, 189 unsigned FloatingParmsNum, 190 unsigned VectorParmsNum) { 191 SmallString<32> ParmsType; 192 193 unsigned ParsedFixedNum = 0; 194 unsigned ParsedFloatingNum = 0; 195 unsigned ParsedVectorNum = 0; 196 unsigned ParsedNum = 0; 197 unsigned ParmsNum = FixedParmsNum + FloatingParmsNum + VectorParmsNum; 198 199 for (int Bits = 0; Bits < 32 && ParsedNum < ParmsNum; Bits += 2) { 200 if (++ParsedNum > 1) 201 ParmsType += ", "; 202 203 switch (Value & TracebackTable::ParmTypeMask) { 204 case TracebackTable::ParmTypeIsFixedBits: 205 ParmsType += "i"; 206 ++ParsedFixedNum; 207 break; 208 case TracebackTable::ParmTypeIsVectorBits: 209 ParmsType += "v"; 210 ++ParsedVectorNum; 211 break; 212 case TracebackTable::ParmTypeIsFloatingBits: 213 ParmsType += "f"; 214 ++ParsedFloatingNum; 215 break; 216 case TracebackTable::ParmTypeIsDoubleBits: 217 ParmsType += "d"; 218 ++ParsedFloatingNum; 219 break; 220 default: 221 assert(false && "Unrecognized bits in ParmsType."); 222 } 223 Value <<= 2; 224 } 225 226 // We have more parameters than the 32 Bits could encode. 227 if (ParsedNum < ParmsNum) 228 ParmsType += ", ..."; 229 230 if (Value != 0u || ParsedFixedNum > FixedParmsNum || 231 ParsedFloatingNum > FloatingParmsNum || ParsedVectorNum > VectorParmsNum) 232 return createStringError( 233 errc::invalid_argument, 234 "ParmsType encodes can not map to ParmsNum parameters " 235 "in parseParmsTypeWithVecInfo."); 236 237 return ParmsType; 238 } 239 240 Expected<SmallString<32>> XCOFF::parseVectorParmsType(uint32_t Value, 241 unsigned ParmsNum) { 242 SmallString<32> ParmsType; 243 unsigned ParsedNum = 0; 244 for (int Bits = 0; ParsedNum < ParmsNum && Bits < 32; Bits += 2) { 245 if (++ParsedNum > 1) 246 ParmsType += ", "; 247 switch (Value & TracebackTable::ParmTypeMask) { 248 case TracebackTable::ParmTypeIsVectorCharBit: 249 ParmsType += "vc"; 250 break; 251 252 case TracebackTable::ParmTypeIsVectorShortBit: 253 ParmsType += "vs"; 254 break; 255 256 case TracebackTable::ParmTypeIsVectorIntBit: 257 ParmsType += "vi"; 258 break; 259 260 case TracebackTable::ParmTypeIsVectorFloatBit: 261 ParmsType += "vf"; 262 break; 263 } 264 265 Value <<= 2; 266 } 267 268 // We have more parameters than the 32 Bits could encode. 269 if (ParsedNum < ParmsNum) 270 ParmsType += ", ..."; 271 272 if (Value != 0u) 273 return createStringError(errc::invalid_argument, 274 "ParmsType encodes more than ParmsNum parameters " 275 "in parseVectorParmsType."); 276 return ParmsType; 277 } 278