1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
|
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
// This include file determines how VARSET_TP is implemented.
//
#ifndef _VARSET_INCLUDED_
#define _VARSET_INCLUDED_ 1
// A VARSET_TP is a set of (small) integers representing local variables.
// We implement varsets using the BitSet abstraction, which supports
// several different implementations.
//
// The set of tracked variables may change during a compilation, and variables may be
// re-sorted, so the tracked variable index of a variable is decidedly *not* stable. The
// bitset abstraction supports labeling of bitsets with "epochs", and supports a
// debugging mode in which live bitsets must have the current epoch. To use this feature,
// divide a compilation up into epochs, during which tracked variable indices are
// stable.
// Some implementations of BitSet may use a level of indirection. Therefore, we
// must be careful about about assignment and initialization. We often want to
// reason about VARSET_TP as immutable values, and just copying the contents would
// introduce sharing in the indirect case, which is usually not what's desired. On
// the other hand, there are many cases in which the RHS value has just been
// created functionally, and the intialization/assignment is obviously its last
// use. In these cases, allocating a new indirect representation for the lhs (if
// it does not already have one) would be unnecessary and wasteful. Thus, for both
// initialization and assignment, we have normal versions, which do make copies to
// prevent sharing and definitely preserve value semantics, and "NOCOPY" versions,
// which do not. Obviously, the latter should be used with care.
#include "bitset.h"
#include "compilerbitsettraits.h"
const unsigned UInt64Bits = sizeof(UINT64) * 8;
// This #define chooses the BitSet representation used for VARSET.
// The choices are defined in "bitset.h"; they currently include
// BSUInt64, BSShortLong, and BSUInt64Class.
#define VARSET_REP BSShortLong
#if VARSET_REP == BSUInt64
#include "bitsetasuint64.h"
typedef BitSetOps</*BitSetType*/UINT64,
/*Brand*/VARSET_REP,
/*Env*/Compiler*,
/*BitSetTraits*/TrackedVarBitSetTraits>
VarSetOpsRaw;
typedef UINT64 VARSET_TP;
const unsigned lclMAX_TRACKED = UInt64Bits;
#define VARSET_REP_IS_CLASS 0
#elif VARSET_REP == BSShortLong
#include "bitsetasshortlong.h"
typedef BitSetOps</*BitSetType*/BitSetShortLongRep,
/*Brand*/VARSET_REP,
/*Env*/Compiler*,
/*BitSetTraits*/TrackedVarBitSetTraits>
VarSetOpsRaw;
typedef BitSetShortLongRep VARSET_TP;
// For the unbounded-width varset implementation, test it a little by allowing the max tracked vars to be than UINT64 can hold.
const unsigned lclMAX_TRACKED = 128;
#define VARSET_REP_IS_CLASS 0
#elif VARSET_REP == BSUInt64Class
#include "bitsetasuint64inclass.h"
typedef BitSetOps</*BitSetType*/BitSetUint64<Compiler*, TrackedVarBitSetTraits>,
/*Brand*/VARSET_REP,
/*Env*/Compiler*,
/*BitSetTraits*/TrackedVarBitSetTraits>
VarSetOpsRaw;
typedef BitSetUint64<Compiler*, TrackedVarBitSetTraits> VARSET_TP;
const unsigned lclMAX_TRACKED = UInt64Bits;
#define VARSET_REP_IS_CLASS 1
#else
#error "Unrecognized BitSet implemention for VarSet."
#endif
// These types should be used as the types for VARSET_TP arguments and return values, respectively.
typedef VarSetOpsRaw::ValArgType VARSET_VALARG_TP;
typedef VarSetOpsRaw::RetValType VARSET_VALRET_TP;
#define VARSET_COUNTOPS 0
#if VARSET_COUNTOPS
typedef BitSetOpsWithCounter<VARSET_TP, VARSET_REP, Compiler*, TrackedVarBitSetTraits, VARSET_VALARG_TP, VARSET_VALRET_TP, VarSetOpsRaw::Iter> VarSetOps;
#else
typedef VarSetOpsRaw VarSetOps;
#endif
#define ALLVARSET_REP BSUInt64
#if ALLVARSET_REP == BSUInt64
#include "bitsetasuint64.h"
typedef BitSetOps</*BitSetType*/UINT64,
/*Brand*/ALLVARSET_REP,
/*Env*/Compiler*,
/*BitSetTraits*/AllVarBitSetTraits>
AllVarSetOps;
typedef UINT64 ALLVARSET_TP;
const unsigned lclMAX_ALLSET_TRACKED = UInt64Bits;
#define ALLVARSET_REP_IS_CLASS 0
#elif ALLVARSET_REP == BSShortLong
#include "bitsetasshortlong.h"
typedef BitSetOps</*BitSetType*/BitSetShortLongRep,
/*Brand*/ALLVARSET_REP,
/*Env*/Compiler*,
/*BitSetTraits*/AllVarBitSetTraits>
AllVarSetOps;
typedef BitSetShortLongRep ALLVARSET_TP;
// For the unbounded-width varset implementation, test them a little by allowing the max tracked vars to be than UINT64 can hold.
const unsigned lclMAX_ALLSET_TRACKED = 128;
#define ALLVARSET_REP_IS_CLASS 0
#elif ALLVARSET_REP == BSUInt64Class
#include "bitsetasuint64inclass.h"
typedef BitSetOps</*BitSetType*/BitSetUint64<Compiler*, AllVarBitSetTraits>,
/*Brand*/ALLVARSET_REP,
/*Env*/Compiler*,
/*BitSetTraits*/AllVarBitSetTraits>
AllVarSetOps;
typedef BitSetUint64<Compiler*, AllVarBitSetTraits> ALLVARSET_TP;
const unsigned lclMAX_ALLSET_TRACKED = UInt64Bits;
#define ALLVARSET_REP_IS_CLASS 1
#else
#error "Unrecognized BitSet implemention for AllVarSet."
#endif
// These types should be used as the types for VARSET_TP arguments and return values, respectively.
typedef AllVarSetOps::ValArgType ALLVARSET_VALARG_TP;
typedef AllVarSetOps::RetValType ALLVARSET_VALRET_TP;
// Initialize "varName" to "initVal." Copies contents, not references; if "varName" is uninitialized, allocates a var set
// for it (using "comp" for any necessary allocation), and copies the contents of "initVal" into it.
#define VARSET_INIT(comp, varName, initVal) varName(VarSetOps::MakeCopy(comp, initVal))
#define ALLVARSET_INIT(comp, varName, initVal) varName(AllVarSetOps::MakeCopy(comp, initVal))
// Initializes "varName" to "initVal", without copying: if "initVal" is an indirect representation, copies its
// pointer into "varName".
#if defined(DEBUG) && VARSET_REP_IS_CLASS
#define VARSET_INIT_NOCOPY(varName, initVal) varName(initVal, 0)
#else
#define VARSET_INIT_NOCOPY(varName, initVal) varName(initVal)
#endif
#if defined(DEBUG) && ALLVARSET_REP_IS_CLASS
#define ALLVARSET_INIT_NOCOPY(varName, initVal) varName(initVal, 0)
#else
#define ALLVARSET_INIT_NOCOPY(varName, initVal) varName(initVal)
#endif
// The iterator pattern.
// Use this to initialize an iterator "iterName" to iterate over a VARSET_TP "vs".
// "varIndex" will be an unsigned variable to which we assign the elements of "vs".
#define VARSET_ITER_INIT(comp, iterName, vs, varIndex) \
unsigned varIndex = 0; \
VarSetOps::Iter iterName(comp, vs)
#endif // _VARSET_INCLUDED_
|