1 //===- TypeRecordHelpers.cpp ------------------------------------*- 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/TypeRecordHelpers.h" 10 11 #include "llvm/ADT/SmallVector.h" 12 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 13 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" 14 15 using namespace llvm; 16 using namespace llvm::codeview; 17 getUdtOptions(CVType CVT)18template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) { 19 RecordT Record; 20 if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { 21 consumeError(std::move(EC)); 22 return ClassOptions::None; 23 } 24 return Record.getOptions(); 25 } 26 isUdtForwardRef(CVType CVT)27bool llvm::codeview::isUdtForwardRef(CVType CVT) { 28 ClassOptions UdtOptions = ClassOptions::None; 29 switch (CVT.kind()) { 30 case LF_STRUCTURE: 31 case LF_CLASS: 32 case LF_INTERFACE: 33 UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT)); 34 break; 35 case LF_ENUM: 36 UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT)); 37 break; 38 case LF_UNION: 39 UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT)); 40 break; 41 default: 42 return false; 43 } 44 return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; 45 } 46 getModifiedType(const CVType & CVT)47TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) { 48 assert(CVT.kind() == LF_MODIFIER); 49 SmallVector<TypeIndex, 1> Refs; 50 discoverTypeIndices(CVT, Refs); 51 return Refs.front(); 52 } 53 getSizeInBytesForTypeIndex(TypeIndex TI)54uint64_t llvm::codeview::getSizeInBytesForTypeIndex(TypeIndex TI) { 55 if (!TI.isSimple()) 56 return 0; 57 if (TI.getSimpleMode() != SimpleTypeMode::Direct) { 58 // We have a native pointer. 59 switch (TI.getSimpleMode()) { 60 case SimpleTypeMode::NearPointer: 61 case SimpleTypeMode::FarPointer: 62 case SimpleTypeMode::HugePointer: 63 return 2; 64 case SimpleTypeMode::NearPointer32: 65 case SimpleTypeMode::FarPointer32: 66 return 4; 67 case SimpleTypeMode::NearPointer64: 68 return 8; 69 case SimpleTypeMode::NearPointer128: 70 return 16; 71 default: 72 assert(false && "invalid simple type mode!"); 73 } 74 } 75 switch (TI.getSimpleKind()) { 76 case SimpleTypeKind::None: 77 case SimpleTypeKind::Void: 78 return 0; 79 case SimpleTypeKind::HResult: 80 return 4; 81 case SimpleTypeKind::SByte: 82 case SimpleTypeKind::Byte: 83 return 1; 84 85 // Signed/unsigned integer. 86 case SimpleTypeKind::Int16Short: 87 case SimpleTypeKind::UInt16Short: 88 case SimpleTypeKind::Int16: 89 case SimpleTypeKind::UInt16: 90 return 2; 91 case SimpleTypeKind::Int32Long: 92 case SimpleTypeKind::UInt32Long: 93 case SimpleTypeKind::Int32: 94 case SimpleTypeKind::UInt32: 95 return 4; 96 case SimpleTypeKind::Int64Quad: 97 case SimpleTypeKind::UInt64Quad: 98 case SimpleTypeKind::Int64: 99 case SimpleTypeKind::UInt64: 100 return 8; 101 case SimpleTypeKind::Int128Oct: 102 case SimpleTypeKind::UInt128Oct: 103 case SimpleTypeKind::Int128: 104 case SimpleTypeKind::UInt128: 105 return 16; 106 107 // Signed/Unsigned character. 108 case SimpleTypeKind::Character8: 109 case SimpleTypeKind::SignedCharacter: 110 case SimpleTypeKind::UnsignedCharacter: 111 case SimpleTypeKind::NarrowCharacter: 112 return 1; 113 case SimpleTypeKind::WideCharacter: 114 case SimpleTypeKind::Character16: 115 return 2; 116 case SimpleTypeKind::Character32: 117 return 4; 118 119 // Float. 120 case SimpleTypeKind::Float16: 121 return 2; 122 case SimpleTypeKind::Float32: 123 return 4; 124 case SimpleTypeKind::Float48: 125 return 6; 126 case SimpleTypeKind::Float64: 127 return 8; 128 case SimpleTypeKind::Float80: 129 return 10; 130 case SimpleTypeKind::Float128: 131 return 16; 132 133 // Boolean. 134 case SimpleTypeKind::Boolean8: 135 return 1; 136 case SimpleTypeKind::Boolean16: 137 return 2; 138 case SimpleTypeKind::Boolean32: 139 return 4; 140 case SimpleTypeKind::Boolean64: 141 return 8; 142 case SimpleTypeKind::Boolean128: 143 return 16; 144 145 // Complex float. 146 case SimpleTypeKind::Complex16: 147 return 4; 148 case SimpleTypeKind::Complex32: 149 return 8; 150 case SimpleTypeKind::Complex64: 151 return 16; 152 case SimpleTypeKind::Complex80: 153 return 20; 154 case SimpleTypeKind::Complex128: 155 return 32; 156 157 default: 158 return 0; 159 } 160 } 161 getUdtSize(CVType CVT)162template <typename RecordT> static uint64_t getUdtSize(CVType CVT) { 163 RecordT Record; 164 if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { 165 consumeError(std::move(EC)); 166 return 0; 167 } 168 return Record.getSize(); 169 } 170 getSizeInBytesForTypeRecord(CVType CVT)171uint64_t llvm::codeview::getSizeInBytesForTypeRecord(CVType CVT) { 172 switch (CVT.kind()) { 173 case LF_STRUCTURE: 174 case LF_CLASS: 175 case LF_INTERFACE: 176 return getUdtSize<ClassRecord>(std::move(CVT)); 177 case LF_UNION: 178 return getUdtSize<UnionRecord>(std::move(CVT)); 179 default: 180 return CVT.length(); 181 } 182 } 183