1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// ZapInnerPtr.h
6//
7
8//
9// ZapNode that points into middle of other ZapNode. It is used to create
10// pointers into datastructures that are not convenient to split into smaller zap nodes.
11//
12// ======================================================================================
13
14#ifndef __ZAPINNERPTR_H__
15#define __ZAPINNERPTR_H__
16
17class ZapInnerPtr : public ZapNode
18{
19 ZapNode * m_pBase;
20
21public:
22 ZapInnerPtr(ZapNode * pBase)
23 : m_pBase(pBase)
24 {
25 }
26
27 ZapNode * GetBase()
28 {
29 return m_pBase;
30 }
31
32 virtual int GetOffset() = 0;
33
34 void Resolve()
35 {
36 if (m_pBase->IsPlaced())
37 {
38 SetRVA(m_pBase->GetRVA() + GetOffset());
39 }
40 }
41
42 virtual ZapNodeType GetType()
43 {
44 return ZapNodeType_InnerPtr;
45 }
46};
47
48class ZapInnerPtrTable
49{
50 // Create more space efficient nodes for a few common constant offsets
51 template <DWORD offset>
52 class InnerPtrConst : public ZapInnerPtr
53 {
54 public:
55 InnerPtrConst(ZapNode * pBase)
56 : ZapInnerPtr(pBase)
57 {
58 }
59
60 virtual int GetOffset()
61 {
62 return offset;
63 }
64 };
65
66 // The generic node for arbitrary offsets
67 class InnerPtrVar : public ZapInnerPtr
68 {
69 int m_offset;
70
71 public:
72 InnerPtrVar(ZapNode * pBase, SSIZE_T offset)
73 : ZapInnerPtr(pBase), m_offset((int)offset)
74 {
75 if (offset != (int)offset)
76 ThrowHR(COR_E_OVERFLOW);
77 }
78
79 virtual int GetOffset()
80 {
81 return m_offset;
82 }
83 };
84
85 struct InnerPtrKey
86 {
87 InnerPtrKey(ZapNode * pBase, SSIZE_T offset)
88 : m_pBase(pBase), m_offset(offset)
89 {
90 }
91
92 ZapNode * m_pBase;
93 SSIZE_T m_offset;
94 };
95
96 class InnerPtrTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapInnerPtr *> >
97 {
98 public:
99 typedef const InnerPtrKey key_t;
100
101 static key_t GetKey(element_t e)
102 {
103 LIMITED_METHOD_CONTRACT;
104 return InnerPtrKey(e->GetBase(), e->GetOffset());
105 }
106 static BOOL Equals(key_t k1, key_t k2)
107 {
108 LIMITED_METHOD_CONTRACT;
109 return (k1.m_pBase == k2.m_pBase) && (k1.m_offset == k2.m_offset);
110 }
111 static count_t Hash(key_t k)
112 {
113 LIMITED_METHOD_CONTRACT;
114 return (count_t)(size_t)k.m_pBase ^ (count_t)k.m_offset;
115 }
116
117 static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; }
118 static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
119 };
120
121 typedef SHash< InnerPtrTraits > InnerPtrTable;
122
123 InnerPtrTable m_entries;
124 ZapWriter * m_pWriter;
125
126public:
127 ZapInnerPtrTable(ZapWriter * pWriter)
128 : m_pWriter(pWriter)
129 {
130 }
131
132 void Preallocate(COUNT_T cbILImage)
133 {
134 PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapInnerPtrTable::m_entries, cbILImage);
135 }
136
137 // Returns ZapNode that points at given offset in base ZapNode
138 ZapNode * Get(ZapNode * pBase, SSIZE_T offset);
139
140 // Assign offsets to the inner-ptr ZapNodes
141 void Resolve();
142};
143
144#endif // __ZAPINNERPTR_H__
145