Skip to content

Commit d5f85c7

Browse files
Type memory maps with placeholders (#61933)
Use TYP_UNDEF (as TYP_MEM) for "first field"-like maps and TYP_UNKNOWN (as TYP_HEAP) for the heaps themselves. This will enable the type validation logic to be more precise. For now, just assert that the heap is always updated with the properly typed VNs.
1 parent 9fae29d commit d5f85c7

File tree

3 files changed

+70
-49
lines changed

3 files changed

+70
-49
lines changed

src/coreclr/jit/compiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5492,6 +5492,8 @@ class Compiler
54925492
// For a store to an address-exposed local at curTree, record the new curMemoryVN and update curTree's MemorySsaMap.
54935493
void recordAddressExposedLocalStore(GenTree* curTree, ValueNum memoryVN DEBUGARG(const char* msg));
54945494

5495+
void fgSetCurrentMemoryVN(MemoryKind memoryKind, ValueNum newMemoryVN);
5496+
54955497
// Tree caused an update in the current memory VN. If "tree" has an associated heap SSA #, record that
54965498
// value in that SSA #.
54975499
void fgValueNumberRecordMemorySsa(MemoryKind memoryKind, GenTree* tree);

src/coreclr/jit/valuenum.cpp

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,7 +2217,7 @@ ValueNum ValueNumStore::VNForMapStore(ValueNum map, ValueNum index, ValueNum val
22172217
if (m_pComp->verbose)
22182218
{
22192219
printf(" VNForMapStore(" FMT_VN ", " FMT_VN ", " FMT_VN "):%s in " FMT_BB " returns ", map, index, value,
2220-
varTypeName(TypeOfVN(result)), bb->bbNum);
2220+
VNMapTypeName(TypeOfVN(result)), bb->bbNum);
22212221
m_pComp->vnPrint(result, 1);
22222222
printf("\n");
22232223
}
@@ -2255,7 +2255,7 @@ ValueNum ValueNumStore::VNForMapSelect(ValueNumKind vnk, var_types type, ValueNu
22552255
#ifdef DEBUG
22562256
if (m_pComp->verbose)
22572257
{
2258-
printf(" VNForMapSelect(" FMT_VN ", " FMT_VN "):%s returns ", map, index, varTypeName(type));
2258+
printf(" VNForMapSelect(" FMT_VN ", " FMT_VN "):%s returns ", map, index, VNMapTypeName(type));
22592259
m_pComp->vnPrint(result, 1);
22602260
printf("\n");
22612261
}
@@ -4265,8 +4265,8 @@ ValueNum Compiler::fgValueNumberArrIndexAssign(CORINFO_CLASS_HANDLE elemTypeEq,
42654265
bool invalidateArray = false;
42664266
ValueNum elemTypeEqVN = vnStore->VNForHandle(ssize_t(elemTypeEq), GTF_ICON_CLASS_HDL);
42674267
var_types arrElemType = DecodeElemType(elemTypeEq);
4268-
ValueNum hAtArrType = vnStore->VNForMapSelect(VNK_Liberal, TYP_REF, fgCurMemoryVN[GcHeap], elemTypeEqVN);
4269-
ValueNum hAtArrTypeAtArr = vnStore->VNForMapSelect(VNK_Liberal, TYP_REF, hAtArrType, arrVN);
4268+
ValueNum hAtArrType = vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], elemTypeEqVN);
4269+
ValueNum hAtArrTypeAtArr = vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, hAtArrType, arrVN);
42704270
ValueNum hAtArrTypeAtArrAtInx = vnStore->VNForMapSelect(VNK_Liberal, arrElemType, hAtArrTypeAtArr, inxVN);
42714271

42724272
ValueNum newValAtInx = ValueNumStore::NoVN;
@@ -4279,7 +4279,7 @@ ValueNum Compiler::fgValueNumberArrIndexAssign(CORINFO_CLASS_HANDLE elemTypeEq,
42794279
JITDUMP(" *** NotAField sequence encountered in fgValueNumberArrIndexAssign\n");
42804280

42814281
// Store a new unique value for newValAtArrType
4282-
newValAtArrType = vnStore->VNForExpr(compCurBB, TYP_REF);
4282+
newValAtArrType = vnStore->VNForExpr(compCurBB, TYP_MEM);
42834283
invalidateArray = true;
42844284
}
42854285
else
@@ -4301,7 +4301,7 @@ ValueNum Compiler::fgValueNumberArrIndexAssign(CORINFO_CLASS_HANDLE elemTypeEq,
43014301
JITDUMP(" *** Mismatched types in fgValueNumberArrIndexAssign\n");
43024302

43034303
// Store a new unique value for newValAtArrType
4304-
newValAtArrType = vnStore->VNForExpr(compCurBB, TYP_REF);
4304+
newValAtArrType = vnStore->VNForExpr(compCurBB, TYP_MEM);
43054305
invalidateArray = true;
43064306
}
43074307
}
@@ -4328,7 +4328,7 @@ ValueNum Compiler::fgValueNumberArrIndexAssign(CORINFO_CLASS_HANDLE elemTypeEq,
43284328
printf(" hAtArrTypeAtArr " FMT_VN " is MapSelect(hAtArrType(" FMT_VN "), arr=" FMT_VN ")\n", hAtArrTypeAtArr,
43294329
hAtArrType, arrVN);
43304330
printf(" hAtArrTypeAtArrAtInx " FMT_VN " is MapSelect(hAtArrTypeAtArr(" FMT_VN "), inx=" FMT_VN "):%s\n",
4331-
hAtArrTypeAtArrAtInx, hAtArrTypeAtArr, inxVN, varTypeName(arrElemType));
4331+
hAtArrTypeAtArrAtInx, hAtArrTypeAtArr, inxVN, ValueNumStore::VNMapTypeName(arrElemType));
43324332

43334333
if (!invalidateArray)
43344334
{
@@ -4401,8 +4401,8 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree,
44014401
else
44024402
{
44034403
ValueNum elemTypeEqVN = vnStore->VNForHandle(ssize_t(elemTypeEq), GTF_ICON_CLASS_HDL);
4404-
ValueNum hAtArrType = vnStore->VNForMapSelect(VNK_Liberal, TYP_REF, fgCurMemoryVN[GcHeap], elemTypeEqVN);
4405-
ValueNum hAtArrTypeAtArr = vnStore->VNForMapSelect(VNK_Liberal, TYP_REF, hAtArrType, arrVN);
4404+
ValueNum hAtArrType = vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], elemTypeEqVN);
4405+
ValueNum hAtArrTypeAtArr = vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, hAtArrType, arrVN);
44064406
ValueNum wholeElem = vnStore->VNForMapSelect(VNK_Liberal, elemTyp, hAtArrTypeAtArr, inxVN);
44074407

44084408
#ifdef DEBUG
@@ -6291,8 +6291,7 @@ const char* ValueNumStore::VNFuncNameArr[] = {
62916291
#undef ValueNumFuncDef
62926292
};
62936293

6294-
// static
6295-
const char* ValueNumStore::VNFuncName(VNFunc vnf)
6294+
/* static */ const char* ValueNumStore::VNFuncName(VNFunc vnf)
62966295
{
62976296
if (vnf < VNF_Boundary)
62986297
{
@@ -6304,6 +6303,19 @@ const char* ValueNumStore::VNFuncName(VNFunc vnf)
63046303
}
63056304
}
63066305

6306+
/* static */ const char* ValueNumStore::VNMapTypeName(var_types type)
6307+
{
6308+
switch (type)
6309+
{
6310+
case TYP_HEAP:
6311+
return "heap";
6312+
case TYP_MEM:
6313+
return "mem";
6314+
default:
6315+
return varTypeName(type);
6316+
}
6317+
}
6318+
63076319
static const char* s_reservedNameArr[] = {
63086320
"$VN.Recursive", // -2 RecursiveVN
63096321
"$VN.No", // -1 NoVN
@@ -6757,7 +6769,7 @@ void Compiler::fgValueNumber()
67576769
}
67586770
}
67596771
// Give memory an initial value number (about which we know nothing).
6760-
ValueNum memoryInitVal = vnStore->VNForFunc(TYP_REF, VNF_InitVal, vnStore->VNForIntCon(-1)); // Use -1 for memory.
6772+
ValueNum memoryInitVal = vnStore->VNForFunc(TYP_HEAP, VNF_InitVal, vnStore->VNForIntCon(-1)); // Use -1 for memory.
67616773
GetMemoryPerSsaData(SsaConfig::FIRST_SSA_NUM)->m_vnPair.SetBoth(memoryInitVal);
67626774
#ifdef DEBUG
67636775
if (verbose)
@@ -6894,8 +6906,8 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk)
68946906
// Is there a phi for this block?
68956907
if (blk->bbMemorySsaPhiFunc[memoryKind] == nullptr)
68966908
{
6897-
fgCurMemoryVN[memoryKind] = GetMemoryPerSsaData(blk->bbMemorySsaNumIn[memoryKind])->m_vnPair.GetLiberal();
6898-
assert(fgCurMemoryVN[memoryKind] != ValueNumStore::NoVN);
6909+
ValueNum newMemoryVN = GetMemoryPerSsaData(blk->bbMemorySsaNumIn[memoryKind])->m_vnPair.GetLiberal();
6910+
fgSetCurrentMemoryVN(memoryKind, newMemoryVN);
68996911
}
69006912
else
69016913
{
@@ -6943,7 +6955,7 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk)
69436955
unsigned phiArgSSANum = phiArgs->GetSsaNum();
69446956
ValueNum phiArgSSANumVN = vnStore->VNForIntCon(phiArgSSANum);
69456957
JITDUMP(" Building phi application: $%x = SSA# %d.\n", phiArgSSANumVN, phiArgSSANum);
6946-
phiAppVN = vnStore->VNForFunc(TYP_REF, VNF_Phi, phiArgSSANumVN, phiAppVN);
6958+
phiAppVN = vnStore->VNForFunc(TYP_HEAP, VNF_Phi, phiArgSSANumVN, phiAppVN);
69476959
JITDUMP(" Building phi application: $%x = phi($%x, $%x).\n", phiAppVN, phiArgSSANumVN,
69486960
oldPhiAppVN);
69496961
phiArgs = phiArgs->m_nextArg;
@@ -6954,16 +6966,16 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk)
69546966
}
69556967
else
69566968
{
6957-
newMemoryVN = vnStore->VNForFunc(TYP_REF, VNF_PhiMemoryDef,
6969+
newMemoryVN = vnStore->VNForFunc(TYP_HEAP, VNF_PhiMemoryDef,
69586970
vnStore->VNForHandle(ssize_t(blk), GTF_EMPTY), phiAppVN);
69596971
}
69606972
}
69616973
GetMemoryPerSsaData(blk->bbMemorySsaNumIn[memoryKind])->m_vnPair.SetLiberal(newMemoryVN);
6962-
fgCurMemoryVN[memoryKind] = newMemoryVN;
6974+
fgSetCurrentMemoryVN(memoryKind, newMemoryVN);
69636975
if ((memoryKind == GcHeap) && byrefStatesMatchGcHeapStates)
69646976
{
69656977
// Keep the CurMemoryVNs in sync
6966-
fgCurMemoryVN[ByrefExposed] = newMemoryVN;
6978+
fgSetCurrentMemoryVN(ByrefExposed, newMemoryVN);
69676979
}
69686980
}
69696981
#ifdef DEBUG
@@ -7061,7 +7073,7 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind,
70617073
// If this loop has memory havoc effects, just use a new, unique VN.
70627074
if (optLoopTable[loopNum].lpLoopHasMemoryHavoc[memoryKind])
70637075
{
7064-
ValueNum res = vnStore->VNForExpr(entryBlock, TYP_REF);
7076+
ValueNum res = vnStore->VNForExpr(entryBlock, TYP_HEAP);
70657077
#ifdef DEBUG
70667078
if (verbose)
70677079
{
@@ -7101,7 +7113,7 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind,
71017113
}
71027114
if (multipleNonLoopPreds)
71037115
{
7104-
ValueNum res = vnStore->VNForExpr(entryBlock, TYP_REF);
7116+
ValueNum res = vnStore->VNForExpr(entryBlock, TYP_HEAP);
71057117
#ifdef DEBUG
71067118
if (verbose)
71077119
{
@@ -7146,9 +7158,9 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind,
71467158
}
71477159
#endif // DEBUG
71487160

7149-
// Instance field maps get the placeholder TYP_REF - they do not represent "singular"
7161+
// Instance field maps get a placeholder type - they do not represent "singular"
71507162
// values. Static field maps, on the other hand, do, and so must be given proper types.
7151-
var_types fldMapType = eeIsFieldStatic(fldHnd) ? eeGetFieldType(fldHnd) : TYP_REF;
7163+
var_types fldMapType = eeIsFieldStatic(fldHnd) ? eeGetFieldType(fldHnd) : TYP_MEM;
71527164

71537165
newMemoryVN = vnStore->VNForMapStore(newMemoryVN, fldHndVN, vnStore->VNForExpr(entryBlock, fldMapType));
71547166
}
@@ -7181,7 +7193,7 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind,
71817193
#endif // DEBUG
71827194

71837195
ValueNum elemTypeVN = vnStore->VNForHandle(ssize_t(elemClsHnd), GTF_ICON_CLASS_HDL);
7184-
ValueNum uniqueVN = vnStore->VNForExpr(entryBlock, TYP_REF);
7196+
ValueNum uniqueVN = vnStore->VNForExpr(entryBlock, TYP_MEM);
71857197
newMemoryVN = vnStore->VNForMapStore(newMemoryVN, elemTypeVN, uniqueVN);
71867198
}
71877199
}
@@ -7209,35 +7221,35 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind,
72097221
void Compiler::fgMutateGcHeap(GenTree* tree DEBUGARG(const char* msg))
72107222
{
72117223
// Update the current memory VN, and if we're tracking the heap SSA # caused by this node, record it.
7212-
recordGcHeapStore(tree, vnStore->VNForExpr(compCurBB, TYP_REF) DEBUGARG(msg));
7224+
recordGcHeapStore(tree, vnStore->VNForExpr(compCurBB, TYP_HEAP) DEBUGARG(msg));
72137225
}
72147226

72157227
void Compiler::fgMutateAddressExposedLocal(GenTree* tree DEBUGARG(const char* msg))
72167228
{
72177229
// Update the current ByrefExposed VN, and if we're tracking the heap SSA # caused by this node, record it.
7218-
recordAddressExposedLocalStore(tree, vnStore->VNForExpr(compCurBB) DEBUGARG(msg));
7230+
recordAddressExposedLocalStore(tree, vnStore->VNForExpr(compCurBB, TYP_HEAP) DEBUGARG(msg));
72197231
}
72207232

72217233
void Compiler::recordGcHeapStore(GenTree* curTree, ValueNum gcHeapVN DEBUGARG(const char* msg))
72227234
{
72237235
// bbMemoryDef must include GcHeap for any block that mutates the GC Heap
72247236
// and GC Heap mutations are also ByrefExposed mutations
72257237
assert((compCurBB->bbMemoryDef & memoryKindSet(GcHeap, ByrefExposed)) == memoryKindSet(GcHeap, ByrefExposed));
7226-
fgCurMemoryVN[GcHeap] = gcHeapVN;
7238+
fgSetCurrentMemoryVN(GcHeap, gcHeapVN);
72277239

72287240
if (byrefStatesMatchGcHeapStates)
72297241
{
72307242
// Since GcHeap and ByrefExposed share SSA nodes, they need to share
72317243
// value numbers too.
7232-
fgCurMemoryVN[ByrefExposed] = gcHeapVN;
7244+
fgSetCurrentMemoryVN(ByrefExposed, gcHeapVN);
72337245
}
72347246
else
72357247
{
72367248
// GcHeap and ByrefExposed have different defnums and VNs. We conservatively
72377249
// assume that this GcHeap store may alias any byref load/store, so don't
72387250
// bother trying to record the map/select stuff, and instead just an opaque VN
72397251
// for ByrefExposed
7240-
fgCurMemoryVN[ByrefExposed] = vnStore->VNForExpr(compCurBB);
7252+
fgSetCurrentMemoryVN(ByrefExposed, vnStore->VNForExpr(compCurBB, TYP_HEAP));
72417253
}
72427254

72437255
#ifdef DEBUG
@@ -7262,7 +7274,7 @@ void Compiler::recordAddressExposedLocalStore(GenTree* curTree, ValueNum memoryV
72627274

72637275
// bbMemoryDef must include ByrefExposed for any block that mutates an address-exposed local
72647276
assert((compCurBB->bbMemoryDef & memoryKindSet(ByrefExposed)) != 0);
7265-
fgCurMemoryVN[ByrefExposed] = memoryVN;
7277+
fgSetCurrentMemoryVN(ByrefExposed, memoryVN);
72667278

72677279
#ifdef DEBUG
72687280
if (verbose)
@@ -7276,6 +7288,13 @@ void Compiler::recordAddressExposedLocalStore(GenTree* curTree, ValueNum memoryV
72767288
fgValueNumberRecordMemorySsa(ByrefExposed, curTree);
72777289
}
72787290

7291+
void Compiler::fgSetCurrentMemoryVN(MemoryKind memoryKind, ValueNum newMemoryVN)
7292+
{
7293+
assert(vnStore->VNIsValid(newMemoryVN));
7294+
assert(vnStore->TypeOfVN(newMemoryVN) == TYP_HEAP);
7295+
fgCurMemoryVN[memoryKind] = newMemoryVN;
7296+
}
7297+
72797298
void Compiler::fgValueNumberRecordMemorySsa(MemoryKind memoryKind, GenTree* tree)
72807299
{
72817300
unsigned ssaNum;
@@ -7516,7 +7535,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
75167535
// through address-taken locals in regions of code with no calls or byref
75177536
// writes.
75187537
// For now, just use a new opaque VN.
7519-
ValueNum heapVN = vnStore->VNForExpr(compCurBB);
7538+
ValueNum heapVN = vnStore->VNForExpr(compCurBB, TYP_HEAP);
75207539
recordAddressExposedLocalStore(tree, heapVN DEBUGARG("local assign"));
75217540
}
75227541
#ifdef DEBUG
@@ -7599,7 +7618,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
75997618
// As with GT_LCL_VAR, we could probably use MapStore here and MapSelect at corresponding
76007619
// loads, but to do so would have to identify the subset of address-exposed locals
76017620
// whose fields can be disambiguated.
7602-
ValueNum heapVN = vnStore->VNForExpr(compCurBB);
7621+
ValueNum heapVN = vnStore->VNForExpr(compCurBB, TYP_HEAP);
76037622
recordAddressExposedLocalStore(tree, heapVN DEBUGARG("local field assign"));
76047623
}
76057624
}
@@ -7725,7 +7744,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
77257744
// through address-taken locals in regions of code with no calls or byref
77267745
// writes.
77277746
// For now, just use a new opaque VN.
7728-
ValueNum heapVN = vnStore->VNForExpr(compCurBB);
7747+
ValueNum heapVN = vnStore->VNForExpr(compCurBB, TYP_HEAP);
77297748
recordAddressExposedLocalStore(tree, heapVN DEBUGARG("PtrToLoc indir"));
77307749
}
77317750
}
@@ -7841,8 +7860,8 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
78417860

78427861
// Construct the "field map" VN. It represents memory state of the first field
78437862
// of all objects on the heap. This is our primary map.
7844-
ValueNum fldMapVN = vnStore->VNForMapSelect(VNK_Liberal, firstFieldType,
7845-
fgCurMemoryVN[GcHeap], firstFieldSelectorVN);
7863+
ValueNum fldMapVN = vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap],
7864+
firstFieldSelectorVN);
78467865

78477866
ValueNum firstFieldValueSelectorVN = ValueNumStore::NoVN;
78487867
if (obj != nullptr)
@@ -7911,7 +7930,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
79117930
// through address-taken locals in regions of code with no calls or byref
79127931
// writes.
79137932
// For now, just use a new opaque VN.
7914-
ValueNum memoryVN = vnStore->VNForExpr(compCurBB);
7933+
ValueNum memoryVN = vnStore->VNForExpr(compCurBB, TYP_HEAP);
79157934
recordAddressExposedLocalStore(tree, memoryVN DEBUGARG("PtrToLoc indir"));
79167935
}
79177936
else if (!isLocal)
@@ -9026,8 +9045,8 @@ void Compiler::fgValueNumberTree(GenTree* tree)
90269045
ValueNum firstFieldSelectorVN =
90279046
vnStore->VNForFieldSelector(fldSeq2->GetFieldHandle(), &firstFieldType, &structSize);
90289047

9029-
ValueNum fldMapVN = vnStore->VNForMapSelect(VNK_Liberal, firstFieldType, fgCurMemoryVN[GcHeap],
9030-
firstFieldSelectorVN);
9048+
ValueNum fldMapVN =
9049+
vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], firstFieldSelectorVN);
90319050

90329051
ValueNum firstFieldValueSelectorVN;
90339052
if (obj != nullptr)

src/coreclr/jit/valuenum.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,9 @@
5757
// taken from another map at a given index. As such, it must have a type that corresponds
5858
// to the "index/selector", in practical terms - the field's type.
5959
//
60-
// Note that the above constraints on the types for maps are not followed currently to the
61-
// letter by the implementation - "opaque" maps can and do have TYP_REF assigned to them
62-
// in various situations such as when initializing the "primary" VNs for loop entries.
63-
//
64-
// Note as well that the meaning of "the type" for a map is overloaded, because maps are used
65-
// both to represent memory "of all fields B of all objects that have this field in the heap"
66-
// and "the field B of this particular object on the heap". Only the latter maps can be used
67-
// as VNs for actual nodes, while the former are used for "the first field" maps and "array
68-
// equivalence type" maps, and, of course, for the heap VNs, which always have the placeholder
69-
// types of TYP_REF or TYP_UNKNOWN. In principle, placeholder types could be given to all the
70-
// maps of the former type.
60+
// Note that we give "placeholder" types (TYP_UNDEF and TYP_UNKNOWN as TYP_MEM and TYP_HEAP)
61+
// to maps that do not represent values found in IR. This is just to avoid confusion and
62+
// facilitate more precise validating checks.
7163
//
7264
// Let's review the following snippet to demonstrate how the MapSelect/MapStore machinery works
7365
// together to deliver the results that it does. Say we have this snippet of (C#) code:
@@ -196,6 +188,12 @@ struct VNFuncApp
196188
// This define is used with string concatenation to put this in printf format strings
197189
#define FMT_VN "$%x"
198190

191+
// We will use this placeholder type for memory maps that do not represent IR values ("field maps", etc).
192+
static const var_types TYP_MEM = TYP_UNDEF;
193+
194+
// We will use this placeholder type for memory maps representing "the heap" (GcHeap/ByrefExposed).
195+
static const var_types TYP_HEAP = TYP_UNKNOWN;
196+
199197
class ValueNumStore
200198
{
201199

@@ -1037,9 +1035,11 @@ class ValueNumStore
10371035
// Used in the implementation of the above.
10381036
static const char* VNFuncNameArr[];
10391037

1038+
// Returns a type name used for "maps", i. e. displays TYP_UNDEF and TYP_UNKNOWN as TYP_MEM and TYP_HEAP.
1039+
static const char* VNMapTypeName(var_types type);
1040+
10401041
// Returns the string name of "vn" when it is a reserved value number, nullptr otherwise
10411042
static const char* reservedName(ValueNum vn);
1042-
10431043
#endif // DEBUG
10441044

10451045
// Returns true if "vn" is a reserved value number

0 commit comments

Comments
 (0)