| 1 | //===-- TypeIndex.cpp - CodeView type index ---------------------*- 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/DebugInfo/CodeView/TypeIndex.h" |
| 10 | |
| 11 | #include "llvm/DebugInfo/CodeView/TypeCollection.h" |
| 12 | #include "llvm/Support/ScopedPrinter.h" |
| 13 | |
| 14 | using namespace llvm; |
| 15 | using namespace llvm::codeview; |
| 16 | |
| 17 | namespace { |
| 18 | struct SimpleTypeEntry { |
| 19 | StringRef Name; |
| 20 | SimpleTypeKind Kind; |
| 21 | }; |
| 22 | |
| 23 | /// The names here all end in "*". If the simple type is a pointer type, we |
| 24 | /// return the whole name. Otherwise we lop off the last character in our |
| 25 | /// StringRef. |
| 26 | static const SimpleTypeEntry SimpleTypeNames[] = { |
| 27 | {.Name: "void*" , .Kind: SimpleTypeKind::Void}, |
| 28 | {.Name: "<not translated>*" , .Kind: SimpleTypeKind::NotTranslated}, |
| 29 | {.Name: "HRESULT*" , .Kind: SimpleTypeKind::HResult}, |
| 30 | {.Name: "signed char*" , .Kind: SimpleTypeKind::SignedCharacter}, |
| 31 | {.Name: "unsigned char*" , .Kind: SimpleTypeKind::UnsignedCharacter}, |
| 32 | {.Name: "char*" , .Kind: SimpleTypeKind::NarrowCharacter}, |
| 33 | {.Name: "wchar_t*" , .Kind: SimpleTypeKind::WideCharacter}, |
| 34 | {.Name: "char16_t*" , .Kind: SimpleTypeKind::Character16}, |
| 35 | {.Name: "char32_t*" , .Kind: SimpleTypeKind::Character32}, |
| 36 | {.Name: "char8_t*" , .Kind: SimpleTypeKind::Character8}, |
| 37 | {.Name: "__int8*" , .Kind: SimpleTypeKind::SByte}, |
| 38 | {.Name: "unsigned __int8*" , .Kind: SimpleTypeKind::Byte}, |
| 39 | {.Name: "short*" , .Kind: SimpleTypeKind::Int16Short}, |
| 40 | {.Name: "unsigned short*" , .Kind: SimpleTypeKind::UInt16Short}, |
| 41 | {.Name: "__int16*" , .Kind: SimpleTypeKind::Int16}, |
| 42 | {.Name: "unsigned __int16*" , .Kind: SimpleTypeKind::UInt16}, |
| 43 | {.Name: "long*" , .Kind: SimpleTypeKind::Int32Long}, |
| 44 | {.Name: "unsigned long*" , .Kind: SimpleTypeKind::UInt32Long}, |
| 45 | {.Name: "int*" , .Kind: SimpleTypeKind::Int32}, |
| 46 | {.Name: "unsigned*" , .Kind: SimpleTypeKind::UInt32}, |
| 47 | {.Name: "__int64*" , .Kind: SimpleTypeKind::Int64Quad}, |
| 48 | {.Name: "unsigned __int64*" , .Kind: SimpleTypeKind::UInt64Quad}, |
| 49 | {.Name: "__int64*" , .Kind: SimpleTypeKind::Int64}, |
| 50 | {.Name: "unsigned __int64*" , .Kind: SimpleTypeKind::UInt64}, |
| 51 | {.Name: "__int128*" , .Kind: SimpleTypeKind::Int128}, |
| 52 | {.Name: "unsigned __int128*" , .Kind: SimpleTypeKind::UInt128}, |
| 53 | {.Name: "__half*" , .Kind: SimpleTypeKind::Float16}, |
| 54 | {.Name: "float*" , .Kind: SimpleTypeKind::Float32}, |
| 55 | {.Name: "float*" , .Kind: SimpleTypeKind::Float32PartialPrecision}, |
| 56 | {.Name: "__float48*" , .Kind: SimpleTypeKind::Float48}, |
| 57 | {.Name: "double*" , .Kind: SimpleTypeKind::Float64}, |
| 58 | {.Name: "long double*" , .Kind: SimpleTypeKind::Float80}, |
| 59 | {.Name: "__float128*" , .Kind: SimpleTypeKind::Float128}, |
| 60 | {.Name: "_Complex float*" , .Kind: SimpleTypeKind::Complex32}, |
| 61 | {.Name: "_Complex double*" , .Kind: SimpleTypeKind::Complex64}, |
| 62 | {.Name: "_Complex long double*" , .Kind: SimpleTypeKind::Complex80}, |
| 63 | {.Name: "_Complex __float128*" , .Kind: SimpleTypeKind::Complex128}, |
| 64 | {.Name: "bool*" , .Kind: SimpleTypeKind::Boolean8}, |
| 65 | {.Name: "__bool16*" , .Kind: SimpleTypeKind::Boolean16}, |
| 66 | {.Name: "__bool32*" , .Kind: SimpleTypeKind::Boolean32}, |
| 67 | {.Name: "__bool64*" , .Kind: SimpleTypeKind::Boolean64}, |
| 68 | }; |
| 69 | } // namespace |
| 70 | |
| 71 | StringRef TypeIndex::simpleTypeName(TypeIndex TI) { |
| 72 | assert(TI.isNoneType() || TI.isSimple()); |
| 73 | |
| 74 | if (TI.isNoneType()) |
| 75 | return "<no type>" ; |
| 76 | |
| 77 | if (TI == TypeIndex::NullptrT()) |
| 78 | return "std::nullptr_t" ; |
| 79 | |
| 80 | // This is a simple type. |
| 81 | for (const auto &SimpleTypeName : SimpleTypeNames) { |
| 82 | if (SimpleTypeName.Kind == TI.getSimpleKind()) { |
| 83 | if (TI.getSimpleMode() == SimpleTypeMode::Direct) |
| 84 | return SimpleTypeName.Name.drop_back(N: 1); |
| 85 | // Otherwise, this is a pointer type. We gloss over the distinction |
| 86 | // between near, far, 64, 32, etc, and just give a pointer type. |
| 87 | return SimpleTypeName.Name; |
| 88 | } |
| 89 | } |
| 90 | return "<unknown simple type>" ; |
| 91 | } |
| 92 | |
| 93 | void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, |
| 94 | TypeIndex TI, TypeCollection &Types) { |
| 95 | StringRef TypeName; |
| 96 | if (!TI.isNoneType()) { |
| 97 | if (TI.isSimple()) |
| 98 | TypeName = TypeIndex::simpleTypeName(TI); |
| 99 | else |
| 100 | TypeName = Types.getTypeName(Index: TI); |
| 101 | } |
| 102 | |
| 103 | if (!TypeName.empty()) |
| 104 | Printer.printHex(Label: FieldName, Str: TypeName, Value: TI.getIndex()); |
| 105 | else |
| 106 | Printer.printHex(Label: FieldName, Value: TI.getIndex()); |
| 107 | } |
| 108 | |