1 //===-- PdbSymUid.cpp -----------------------------------------------------===//
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 "PdbSymUid.h"
10 
11 using namespace lldb_private;
12 using namespace lldb_private::npdb;
13 using namespace llvm::codeview;
14 
15 namespace {
16 struct GenericIdRepr {
17   uint64_t tag : 4;
18   uint64_t data : 60;
19 };
20 
21 struct CompilandIdRepr {
22   uint64_t tag : 4;
23   uint64_t modi : 16;
24   uint64_t unused : 44;
25 };
26 
27 struct CompilandSymIdRepr {
28   uint64_t tag : 4;
29   uint64_t modi : 16;
30   uint64_t offset : 32;
31   uint64_t unused : 12;
32 };
33 
34 struct GlobalSymIdRepr {
35   uint64_t tag : 4;
36   uint64_t offset : 32;
37   uint64_t pub : 1;
38   uint64_t unused : 27;
39 };
40 
41 struct TypeSymIdRepr {
42   uint64_t tag : 4;
43   uint64_t index : 32;
44   uint64_t ipi : 1;
45   uint64_t unused : 27;
46 };
47 
48 struct FieldListMemberIdRepr {
49   uint64_t tag : 4;
50   uint64_t index : 32;
51   uint64_t offset : 16;
52   uint64_t unused : 12;
53 };
54 
55 static_assert(sizeof(CompilandIdRepr) == 8, "Invalid structure size!");
56 static_assert(sizeof(CompilandSymIdRepr) == 8, "Invalid structure size!");
57 static_assert(sizeof(GlobalSymIdRepr) == 8, "Invalid structure size!");
58 static_assert(sizeof(TypeSymIdRepr) == 8, "Invalid structure size!");
59 static_assert(sizeof(FieldListMemberIdRepr) == 8, "Invalid structure size!");
60 } // namespace
61 
repr_cast(const InT & value)62 template <typename OutT, typename InT> static OutT repr_cast(const InT &value) {
63   OutT result;
64   ::memcpy(&result, &value, sizeof(value));
65   return result;
66 }
67 
PdbSymUid(const PdbCompilandId & cid)68 PdbSymUid::PdbSymUid(const PdbCompilandId &cid) {
69   CompilandIdRepr repr;
70   ::memset(&repr, 0, sizeof(repr));
71   repr.modi = cid.modi;
72   repr.tag = static_cast<uint64_t>(PdbSymUidKind::Compiland);
73   m_repr = repr_cast<uint64_t>(repr);
74 }
75 
PdbSymUid(const PdbCompilandSymId & csid)76 PdbSymUid::PdbSymUid(const PdbCompilandSymId &csid) {
77   CompilandSymIdRepr repr;
78   ::memset(&repr, 0, sizeof(repr));
79   repr.modi = csid.modi;
80   repr.offset = csid.offset;
81   repr.tag = static_cast<uint64_t>(PdbSymUidKind::CompilandSym);
82   m_repr = repr_cast<uint64_t>(repr);
83 }
84 
PdbSymUid(const PdbGlobalSymId & gsid)85 PdbSymUid::PdbSymUid(const PdbGlobalSymId &gsid) {
86   GlobalSymIdRepr repr;
87   ::memset(&repr, 0, sizeof(repr));
88   repr.pub = gsid.is_public;
89   repr.offset = gsid.offset;
90   repr.tag = static_cast<uint64_t>(PdbSymUidKind::GlobalSym);
91   m_repr = repr_cast<uint64_t>(repr);
92 }
93 
PdbSymUid(const PdbTypeSymId & tsid)94 PdbSymUid::PdbSymUid(const PdbTypeSymId &tsid) {
95   TypeSymIdRepr repr;
96   ::memset(&repr, 0, sizeof(repr));
97   repr.index = tsid.index.getIndex();
98   repr.ipi = tsid.is_ipi;
99   repr.tag = static_cast<uint64_t>(PdbSymUidKind::Type);
100   m_repr = repr_cast<uint64_t>(repr);
101 }
102 
PdbSymUid(const PdbFieldListMemberId & flmid)103 PdbSymUid::PdbSymUid(const PdbFieldListMemberId &flmid) {
104   FieldListMemberIdRepr repr;
105   ::memset(&repr, 0, sizeof(repr));
106   repr.index = flmid.index.getIndex();
107   repr.offset = flmid.offset;
108   repr.tag = static_cast<uint64_t>(PdbSymUidKind::FieldListMember);
109   m_repr = repr_cast<uint64_t>(repr);
110 }
111 
kind() const112 PdbSymUidKind PdbSymUid::kind() const {
113   GenericIdRepr generic = repr_cast<GenericIdRepr>(m_repr);
114   return static_cast<PdbSymUidKind>(generic.tag);
115 }
116 
asCompiland() const117 PdbCompilandId PdbSymUid::asCompiland() const {
118   assert(kind() == PdbSymUidKind::Compiland);
119   auto repr = repr_cast<CompilandIdRepr>(m_repr);
120   PdbCompilandId result;
121   result.modi = repr.modi;
122   return result;
123 }
124 
asCompilandSym() const125 PdbCompilandSymId PdbSymUid::asCompilandSym() const {
126   assert(kind() == PdbSymUidKind::CompilandSym);
127   auto repr = repr_cast<CompilandSymIdRepr>(m_repr);
128   PdbCompilandSymId result;
129   result.modi = repr.modi;
130   result.offset = repr.offset;
131   return result;
132 }
133 
asGlobalSym() const134 PdbGlobalSymId PdbSymUid::asGlobalSym() const {
135   assert(kind() == PdbSymUidKind::GlobalSym ||
136          kind() == PdbSymUidKind::PublicSym);
137   auto repr = repr_cast<GlobalSymIdRepr>(m_repr);
138   PdbGlobalSymId result;
139   result.is_public = repr.pub;
140   result.offset = repr.offset;
141   return result;
142 }
143 
asTypeSym() const144 PdbTypeSymId PdbSymUid::asTypeSym() const {
145   assert(kind() == PdbSymUidKind::Type);
146   auto repr = repr_cast<TypeSymIdRepr>(m_repr);
147   PdbTypeSymId result;
148   result.index.setIndex(repr.index);
149   result.is_ipi = repr.ipi;
150   return result;
151 }
152 
asFieldListMember() const153 PdbFieldListMemberId PdbSymUid::asFieldListMember() const {
154   assert(kind() == PdbSymUidKind::FieldListMember);
155   auto repr = repr_cast<FieldListMemberIdRepr>(m_repr);
156   PdbFieldListMemberId result;
157   result.index.setIndex(repr.index);
158   result.offset = repr.offset;
159   return result;
160 }
161