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 | |
18 | template <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 | |
27 | bool 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>(CVT: std::move(CVT)); |
34 | break; |
35 | case LF_ENUM: |
36 | UdtOptions = getUdtOptions<EnumRecord>(CVT: std::move(CVT)); |
37 | break; |
38 | case LF_UNION: |
39 | UdtOptions = getUdtOptions<UnionRecord>(CVT: std::move(CVT)); |
40 | break; |
41 | default: |
42 | return false; |
43 | } |
44 | return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; |
45 | } |
46 | |
47 | TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) { |
48 | assert(CVT.kind() == LF_MODIFIER); |
49 | SmallVector<TypeIndex, 1> Refs; |
50 | discoverTypeIndices(Type: CVT, Indices&: Refs); |
51 | return Refs.front(); |
52 | } |
53 | |
54 | uint64_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 | |
162 | template <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 | |
171 | uint64_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>(CVT: std::move(CVT)); |
177 | case LF_UNION: |
178 | return getUdtSize<UnionRecord>(CVT: std::move(CVT)); |
179 | default: |
180 | return CVT.length(); |
181 | } |
182 | } |
183 |