10b57cec5SDimitry Andric //===- TypeRecordHelpers.cpp ------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
120b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
13bdd1243dSDimitry Andric #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric using namespace llvm;
160b57cec5SDimitry Andric using namespace llvm::codeview;
170b57cec5SDimitry Andric 
getUdtOptions(CVType CVT)180b57cec5SDimitry Andric template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) {
190b57cec5SDimitry Andric   RecordT Record;
200b57cec5SDimitry Andric   if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
210b57cec5SDimitry Andric     consumeError(std::move(EC));
220b57cec5SDimitry Andric     return ClassOptions::None;
230b57cec5SDimitry Andric   }
240b57cec5SDimitry Andric   return Record.getOptions();
250b57cec5SDimitry Andric }
260b57cec5SDimitry Andric 
isUdtForwardRef(CVType CVT)270b57cec5SDimitry Andric bool llvm::codeview::isUdtForwardRef(CVType CVT) {
280b57cec5SDimitry Andric   ClassOptions UdtOptions = ClassOptions::None;
290b57cec5SDimitry Andric   switch (CVT.kind()) {
300b57cec5SDimitry Andric   case LF_STRUCTURE:
310b57cec5SDimitry Andric   case LF_CLASS:
320b57cec5SDimitry Andric   case LF_INTERFACE:
330b57cec5SDimitry Andric     UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));
340b57cec5SDimitry Andric     break;
350b57cec5SDimitry Andric   case LF_ENUM:
360b57cec5SDimitry Andric     UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));
370b57cec5SDimitry Andric     break;
380b57cec5SDimitry Andric   case LF_UNION:
390b57cec5SDimitry Andric     UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));
400b57cec5SDimitry Andric     break;
410b57cec5SDimitry Andric   default:
420b57cec5SDimitry Andric     return false;
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric   return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None;
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
getModifiedType(const CVType & CVT)470b57cec5SDimitry Andric TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) {
480b57cec5SDimitry Andric   assert(CVT.kind() == LF_MODIFIER);
490b57cec5SDimitry Andric   SmallVector<TypeIndex, 1> Refs;
500b57cec5SDimitry Andric   discoverTypeIndices(CVT, Refs);
510b57cec5SDimitry Andric   return Refs.front();
520b57cec5SDimitry Andric }
53bdd1243dSDimitry Andric 
getSizeInBytesForTypeIndex(TypeIndex TI)54bdd1243dSDimitry Andric uint64_t llvm::codeview::getSizeInBytesForTypeIndex(TypeIndex TI) {
55bdd1243dSDimitry Andric   if (!TI.isSimple())
56bdd1243dSDimitry Andric     return 0;
57bdd1243dSDimitry Andric   if (TI.getSimpleMode() != SimpleTypeMode::Direct) {
58bdd1243dSDimitry Andric     // We have a native pointer.
59bdd1243dSDimitry Andric     switch (TI.getSimpleMode()) {
60bdd1243dSDimitry Andric     case SimpleTypeMode::NearPointer:
61bdd1243dSDimitry Andric     case SimpleTypeMode::FarPointer:
62bdd1243dSDimitry Andric     case SimpleTypeMode::HugePointer:
63bdd1243dSDimitry Andric       return 2;
64bdd1243dSDimitry Andric     case SimpleTypeMode::NearPointer32:
65bdd1243dSDimitry Andric     case SimpleTypeMode::FarPointer32:
66bdd1243dSDimitry Andric       return 4;
67bdd1243dSDimitry Andric     case SimpleTypeMode::NearPointer64:
68bdd1243dSDimitry Andric       return 8;
69bdd1243dSDimitry Andric     case SimpleTypeMode::NearPointer128:
70bdd1243dSDimitry Andric       return 16;
71bdd1243dSDimitry Andric     default:
72bdd1243dSDimitry Andric       assert(false && "invalid simple type mode!");
73bdd1243dSDimitry Andric     }
74bdd1243dSDimitry Andric   }
75bdd1243dSDimitry Andric   switch (TI.getSimpleKind()) {
76bdd1243dSDimitry Andric   case SimpleTypeKind::None:
77bdd1243dSDimitry Andric   case SimpleTypeKind::Void:
78bdd1243dSDimitry Andric     return 0;
79bdd1243dSDimitry Andric   case SimpleTypeKind::HResult:
80bdd1243dSDimitry Andric     return 4;
81bdd1243dSDimitry Andric   case SimpleTypeKind::SByte:
82bdd1243dSDimitry Andric   case SimpleTypeKind::Byte:
83bdd1243dSDimitry Andric     return 1;
84bdd1243dSDimitry Andric 
85bdd1243dSDimitry Andric   // Signed/unsigned integer.
86bdd1243dSDimitry Andric   case SimpleTypeKind::Int16Short:
87bdd1243dSDimitry Andric   case SimpleTypeKind::UInt16Short:
88bdd1243dSDimitry Andric   case SimpleTypeKind::Int16:
89bdd1243dSDimitry Andric   case SimpleTypeKind::UInt16:
90bdd1243dSDimitry Andric     return 2;
91bdd1243dSDimitry Andric   case SimpleTypeKind::Int32Long:
92bdd1243dSDimitry Andric   case SimpleTypeKind::UInt32Long:
93bdd1243dSDimitry Andric   case SimpleTypeKind::Int32:
94bdd1243dSDimitry Andric   case SimpleTypeKind::UInt32:
95bdd1243dSDimitry Andric     return 4;
96bdd1243dSDimitry Andric   case SimpleTypeKind::Int64Quad:
97bdd1243dSDimitry Andric   case SimpleTypeKind::UInt64Quad:
98bdd1243dSDimitry Andric   case SimpleTypeKind::Int64:
99bdd1243dSDimitry Andric   case SimpleTypeKind::UInt64:
100bdd1243dSDimitry Andric     return 8;
101bdd1243dSDimitry Andric   case SimpleTypeKind::Int128Oct:
102bdd1243dSDimitry Andric   case SimpleTypeKind::UInt128Oct:
103bdd1243dSDimitry Andric   case SimpleTypeKind::Int128:
104bdd1243dSDimitry Andric   case SimpleTypeKind::UInt128:
105bdd1243dSDimitry Andric     return 16;
106bdd1243dSDimitry Andric 
107bdd1243dSDimitry Andric   // Signed/Unsigned character.
108bdd1243dSDimitry Andric   case SimpleTypeKind::Character8:
109bdd1243dSDimitry Andric   case SimpleTypeKind::SignedCharacter:
110bdd1243dSDimitry Andric   case SimpleTypeKind::UnsignedCharacter:
111bdd1243dSDimitry Andric   case SimpleTypeKind::NarrowCharacter:
112bdd1243dSDimitry Andric     return 1;
113bdd1243dSDimitry Andric   case SimpleTypeKind::WideCharacter:
114bdd1243dSDimitry Andric   case SimpleTypeKind::Character16:
115bdd1243dSDimitry Andric     return 2;
116bdd1243dSDimitry Andric   case SimpleTypeKind::Character32:
117bdd1243dSDimitry Andric     return 4;
118bdd1243dSDimitry Andric 
119bdd1243dSDimitry Andric   // Float.
120bdd1243dSDimitry Andric   case SimpleTypeKind::Float16:
121bdd1243dSDimitry Andric     return 2;
122bdd1243dSDimitry Andric   case SimpleTypeKind::Float32:
123bdd1243dSDimitry Andric     return 4;
124bdd1243dSDimitry Andric   case SimpleTypeKind::Float48:
125bdd1243dSDimitry Andric     return 6;
126bdd1243dSDimitry Andric   case SimpleTypeKind::Float64:
127bdd1243dSDimitry Andric     return 8;
128bdd1243dSDimitry Andric   case SimpleTypeKind::Float80:
129bdd1243dSDimitry Andric     return 10;
130bdd1243dSDimitry Andric   case SimpleTypeKind::Float128:
131bdd1243dSDimitry Andric     return 16;
132bdd1243dSDimitry Andric 
133bdd1243dSDimitry Andric   // Boolean.
134bdd1243dSDimitry Andric   case SimpleTypeKind::Boolean8:
135bdd1243dSDimitry Andric     return 1;
136bdd1243dSDimitry Andric   case SimpleTypeKind::Boolean16:
137bdd1243dSDimitry Andric     return 2;
138bdd1243dSDimitry Andric   case SimpleTypeKind::Boolean32:
139bdd1243dSDimitry Andric     return 4;
140bdd1243dSDimitry Andric   case SimpleTypeKind::Boolean64:
141bdd1243dSDimitry Andric     return 8;
142bdd1243dSDimitry Andric   case SimpleTypeKind::Boolean128:
143bdd1243dSDimitry Andric     return 16;
144bdd1243dSDimitry Andric 
145bdd1243dSDimitry Andric   // Complex float.
146bdd1243dSDimitry Andric   case SimpleTypeKind::Complex16:
147bdd1243dSDimitry Andric     return 4;
14806c3fb27SDimitry Andric   case SimpleTypeKind::Complex32:
149bdd1243dSDimitry Andric     return 8;
15006c3fb27SDimitry Andric   case SimpleTypeKind::Complex64:
151bdd1243dSDimitry Andric     return 16;
15206c3fb27SDimitry Andric   case SimpleTypeKind::Complex80:
15306c3fb27SDimitry Andric     return 20;
15406c3fb27SDimitry Andric   case SimpleTypeKind::Complex128:
15506c3fb27SDimitry Andric     return 32;
156bdd1243dSDimitry Andric 
157bdd1243dSDimitry Andric   default:
158bdd1243dSDimitry Andric     return 0;
159bdd1243dSDimitry Andric   }
160bdd1243dSDimitry Andric }
161bdd1243dSDimitry Andric 
getUdtSize(CVType CVT)162bdd1243dSDimitry Andric template <typename RecordT> static uint64_t getUdtSize(CVType CVT) {
163bdd1243dSDimitry Andric   RecordT Record;
164bdd1243dSDimitry Andric   if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
165bdd1243dSDimitry Andric     consumeError(std::move(EC));
166bdd1243dSDimitry Andric     return 0;
167bdd1243dSDimitry Andric   }
168bdd1243dSDimitry Andric   return Record.getSize();
169bdd1243dSDimitry Andric }
170bdd1243dSDimitry Andric 
getSizeInBytesForTypeRecord(CVType CVT)171bdd1243dSDimitry Andric uint64_t llvm::codeview::getSizeInBytesForTypeRecord(CVType CVT) {
172bdd1243dSDimitry Andric   switch (CVT.kind()) {
173bdd1243dSDimitry Andric   case LF_STRUCTURE:
174bdd1243dSDimitry Andric   case LF_CLASS:
175bdd1243dSDimitry Andric   case LF_INTERFACE:
176bdd1243dSDimitry Andric     return getUdtSize<ClassRecord>(std::move(CVT));
177bdd1243dSDimitry Andric   case LF_UNION:
178bdd1243dSDimitry Andric     return getUdtSize<UnionRecord>(std::move(CVT));
179bdd1243dSDimitry Andric   default:
180bdd1243dSDimitry Andric     return CVT.length();
181bdd1243dSDimitry Andric   }
182bdd1243dSDimitry Andric }
183