mirror of
https://github.com/fadden/6502bench.git
synced 2024-11-29 10:50:28 +00:00
Correctly handle a label update edge case
Test case: 1. create a label FOO (can be referenced or unreferenced) 2. add a platform symbol file that also defines FOO (the platform symbol will be masked by the user label) 3. rename FOO to BAR (platform symbol should appear) 4. hit "undo" (platform symbol should disappear) 5. delete label FOO (platform symbol should appear) 6. hit "undo" (platform symbol should disappear) This will fail to update the display list properly, and/or crash when we try to add FOO to a symbol table that already has a symbol with that label. The problem is the optimization that tries to avoid running the data analysis pass if we're just renaming a user label. We need to check to see if the rename overlaps with project/platform symbols, because we need to update the active def symbol set in that case. To avoid the crash, we just need to use table[key]=value syntax instead of table.Add(key,value).
This commit is contained in:
parent
76efbcfcbe
commit
3702448780
@ -799,7 +799,7 @@ namespace SourceGen {
|
||||
//reanalysisTimer.DumpTimes("DisasmProject timers:", debugLog);
|
||||
|
||||
debugLog.LogI("Analysis complete");
|
||||
Problems.DebugDump();
|
||||
//Problems.DebugDump();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1009,6 +1009,28 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a symbol with a matching label appears in the project symbols
|
||||
/// or any of the platform lists. This operates on the raw lists, not SymbolTable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Useful for determining whether a label masks a project or platform symbol.
|
||||
/// </remarks>
|
||||
private bool IsInProjectOrPlatformList(Symbol sym) {
|
||||
if (sym == null) {
|
||||
return false;
|
||||
}
|
||||
foreach (PlatformSymbols ps in PlatformSyms) {
|
||||
if (ps.ContainsKey(sym.Label)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ProjectProps.ProjectSyms.ContainsKey(sym.Label)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges symbols from UserLabels into SymbolTable. Existing entries with matching
|
||||
/// labels will be replaced.
|
||||
@ -1881,12 +1903,16 @@ namespace SourceGen {
|
||||
// auto-generated label, we'll have a duplicate label unless we
|
||||
// do a full code+data reanalysis. If we're okay with reanalyzing
|
||||
// on user-label renames, we can allow such conflicts.
|
||||
//
|
||||
// We might be changing it to match an existing platform symbol
|
||||
// though. (Ex: create label FOO, add .sym65 with symbol FOO,
|
||||
// edit FOO to BAR, then hit undo.)
|
||||
if (oldValue != null) {
|
||||
SymbolTable.Remove((Symbol)oldValue);
|
||||
}
|
||||
UserLabels[offset] = (Symbol)newValue;
|
||||
//SymbolTable[((Symbol)newValue).Label] = (Symbol)newValue;
|
||||
SymbolTable.Add((Symbol)newValue);
|
||||
SymbolTable[((Symbol)newValue).Label] = (Symbol)newValue;
|
||||
//SymbolTable.Add((Symbol)newValue);
|
||||
Debug.Assert(oldSym != null || uc.ReanalysisRequired ==
|
||||
UndoableChange.ReanalysisScope.DataOnly);
|
||||
}
|
||||
@ -1908,18 +1934,33 @@ namespace SourceGen {
|
||||
RefactorLabel(offset, ((Symbol)oldValue).Label);
|
||||
}
|
||||
|
||||
affectedOffsets.Add(offset);
|
||||
// Compute the affected offsets. We have one special case to
|
||||
// consider: if we renamed a label, and the old or new name is
|
||||
// in project or platform symbols, we need to restore that
|
||||
// symbol to the symbol table. The most reliable way to do that
|
||||
// is to switch us to a data re-analysis.
|
||||
//
|
||||
// The UI doesn't let you directly edit a label to overwrite a
|
||||
// symbol, but see FOO/BAR example above.
|
||||
if (IsInProjectOrPlatformList((Symbol)oldValue) ||
|
||||
IsInProjectOrPlatformList((Symbol)newValue)) {
|
||||
Debug.WriteLine("Label change masked/unmasked " +
|
||||
"project/platform symbol");
|
||||
needReanalysis |= UndoableChange.ReanalysisScope.DataOnly;
|
||||
} else {
|
||||
affectedOffsets.Add(offset);
|
||||
|
||||
// Use the cross-reference table to identify the offsets that
|
||||
// we need to update.
|
||||
if (mXrefs.TryGetValue(offset, out XrefSet xrefs)) {
|
||||
foreach (XrefSet.Xref xr in xrefs) {
|
||||
// This isn't quite right -- in theory we should be adding
|
||||
// all offsets that are part of the instruction, so that
|
||||
// affectedOffsets can hold a contiguous range instead of
|
||||
// a collection of opcode offsets. In practice, for a
|
||||
// label change, it shouldn't matter.
|
||||
affectedOffsets.Add(xr.Offset);
|
||||
// Use the cross-reference table to identify the offsets that
|
||||
// we need to update.
|
||||
if (mXrefs.TryGetValue(offset, out XrefSet xrefs)) {
|
||||
foreach (XrefSet.Xref xr in xrefs) {
|
||||
// This isn't quite right -- in theory we should be
|
||||
// adding all offsets that are part of the instruction,
|
||||
// so that affectedOffsets can hold a contiguous range
|
||||
// instead of a collection of opcode offsets. In
|
||||
// practice, for a label change, it shouldn't matter.
|
||||
affectedOffsets.Add(xr.Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -68,6 +68,10 @@ namespace SourceGen {
|
||||
return mSymbols.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
public bool ContainsKey(string label) {
|
||||
return mSymbols.ContainsKey(label);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads platform symbols.
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user