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>(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 
47 TypeIndex 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 
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 2;
148   case SimpleTypeKind::Complex32:
149     return 4;
150   case SimpleTypeKind::Complex64:
151     return 8;
152   case SimpleTypeKind::Complex80:
153     return 10;
154   case SimpleTypeKind::Complex128:
155     return 16;
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>(std::move(CVT));
177   case LF_UNION:
178     return getUdtSize<UnionRecord>(std::move(CVT));
179   default:
180     return CVT.length();
181   }
182 }
183