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