diff --git a/SourceGen/AppForms/GotoBox.cs b/SourceGen/AppForms/GotoBox.cs
index f4c5245..78645cb 100644
--- a/SourceGen/AppForms/GotoBox.cs
+++ b/SourceGen/AppForms/GotoBox.cs
@@ -84,7 +84,7 @@ namespace SourceGen.AppForms {
// Try it as a label. If they give the label a hex name (e.g. "A001") they
// can prefix it with '$' to disambiguate the address.
- int labelOffset = mProject.FindLabelByName(input);
+ int labelOffset = mProject.FindLabelOffsetByName(input);
if (labelOffset >= 0) {
TargetOffset = labelOffset;
} else if (Address.ParseAddress(input, 1<<24, out int addr)) {
diff --git a/SourceGen/AppForms/ProjectView.cs b/SourceGen/AppForms/ProjectView.cs
index 770cdf3..229a20e 100644
--- a/SourceGen/AppForms/ProjectView.cs
+++ b/SourceGen/AppForms/ProjectView.cs
@@ -2069,23 +2069,28 @@ namespace SourceGen.AppForms {
// statements and header comment earlier.
if (line.FileOffset >= 0) {
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
+ FormatDescriptor dfd = attr.DataDescriptor;
+
// Does this have an operand with an in-file target offset?
+ // (Resolve it as a numeric reference.)
if (attr.OperandOffset >= 0) {
// Yup, find the line for that offset and jump to it.
GoToOffset(attr.OperandOffset, false, true);
- //int targetIndex =
- // mDisplayList.FindLineIndexByOffset(attr.OperandOffset);
- //GoToOffset(mDisplayList[targetIndex].FileOffset);
+ } else if (dfd != null && dfd.HasSymbol) {
+ // Operand has a symbol, do a symbol lookup.
+ int labelOffset = mProject.FindLabelOffsetByName(
+ dfd.SymbolRef.Label);
+ if (labelOffset >= 0) {
+ GoToOffset(labelOffset, false, true);
+ }
} else if (attr.IsDataStart || attr.IsInlineDataStart) {
// If it's an Address or Symbol, we can try to resolve
- // the value.
+ // the value. (Symbols should have been resolved by the
+ // previous clause, but Address entries would not have been.)
int operandOffset = DataAnalysis.GetDataOperandOffset(
mProject, line.FileOffset);
if (operandOffset >= 0) {
GoToOffset(operandOffset, false, true);
- //int targetIndex =
- // mDisplayList.FindLineIndexByOffset(operandOffset);
- //GoToOffset(mDisplayList[targetIndex].FileOffset);
}
}
}
@@ -3753,7 +3758,7 @@ namespace SourceGen.AppForms {
Symbol sym = mSymbolSubset.GetSubsetItem(row);
if (sym.SymbolSource == Symbol.Source.Auto || sym.SymbolSource == Symbol.Source.User) {
- int offset = mProject.FindLabelByName(sym.Label);
+ int offset = mProject.FindLabelOffsetByName(sym.Label);
if (offset >= 0) {
GoToOffset(offset, false, true);
codeListView.Focus();
diff --git a/SourceGen/AsmGen/GenCommon.cs b/SourceGen/AsmGen/GenCommon.cs
index 16ef05a..0e5ae7c 100644
--- a/SourceGen/AsmGen/GenCommon.cs
+++ b/SourceGen/AsmGen/GenCommon.cs
@@ -322,28 +322,11 @@ namespace SourceGen.AsmGen {
if (dfd == null || !dfd.HasSymbol) {
return false;
}
- if (!proj.SymbolTable.TryGetValue(dfd.SymbolRef.Label, out Symbol sym)) {
+ int labelOffset = proj.FindLabelOffsetByName(dfd.SymbolRef.Label);
+ if (labelOffset <= offset) {
+ // Doesn't exist, or is backward reference.
return false;
}
- if (!sym.IsInternalLabel) {
- return false;
- }
-
- // It's an internal label reference. We don't currently have a data structure
- // that lets us go from label name to file offset. This situation is sufficiently
- // rare that an O(n) approach is acceptable. We may need to fix this someday.
- //
- // We only want to know if it is defined after the current instruction. This is
- // probably being used for a direct-page reference, which is probably at the start
- // of the file, so we run from the start to the current instruction.
- for (int i = 0; i < offset; i++) {
- Anattrib attr = proj.GetAnattrib(i);
- if (attr.Symbol != null && attr.Symbol == sym) {
- // Found it earlier in file.
- return false;
- }
- }
- // Must appear later in file.
return true;
}
diff --git a/SourceGen/DataAnalysis.cs b/SourceGen/DataAnalysis.cs
index 71f43d7..e69eee3 100644
--- a/SourceGen/DataAnalysis.cs
+++ b/SourceGen/DataAnalysis.cs
@@ -196,7 +196,8 @@ namespace SourceGen {
}
///
- /// Extracts the operand offset from a data item.
+ /// Extracts the operand offset from a data item. Only useful for numeric/Address
+ /// and numeric/Symbol.
///
/// Project reference.
/// Offset of data item.
diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs
index 7fbf66f..b30df98 100644
--- a/SourceGen/DisasmProject.cs
+++ b/SourceGen/DisasmProject.cs
@@ -1584,7 +1584,7 @@ namespace SourceGen {
///
/// Label to find.
/// File offset associated with label, or -1 if not found.
- public int FindLabelByName(string name) {
+ public int FindLabelOffsetByName(string name) {
// We're interested in user labels and auto-generated labels. Do a lookup in
// SymbolTable to find the symbol, then if it's user or auto, we do a second
// search to find the file offset it's associated with. The second search
@@ -1593,10 +1593,11 @@ namespace SourceGen {
//
// This will not find "hidden" labels, i.e. labels that are in the middle of an
// instruction or multi-byte data area, because those are removed from SymbolTable.
+
if (!SymbolTable.TryGetValue(name, out Symbol sym)) {
return -1;
}
- if (sym.SymbolSource != Symbol.Source.Auto && sym.SymbolSource != Symbol.Source.User) {
+ if (!sym.IsInternalLabel) {
return -1;
}
for (int i = 0; i < mAnattribs.Length; i++) {
diff --git a/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S b/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S
index a9279b5..a791b09 100644
--- a/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S
+++ b/SourceGen/SGTestData/Expected/2014-label-dp_cc65.S
@@ -286,7 +286,7 @@ L122A: sbc (L0080),y
sbc f:L0089,x
.org $0080
L0080: bit z:L0082
-L0082: bit z:L0082
+L0082: bit L0082
bit L0082
L0086: bit a:L0086
L0089: lda f:L0089
diff --git a/SourceGen/Symbol.cs b/SourceGen/Symbol.cs
index 3ec391d..d5b785e 100644
--- a/SourceGen/Symbol.cs
+++ b/SourceGen/Symbol.cs
@@ -26,12 +26,12 @@ namespace SourceGen {
///
public enum Source {
// These are in order of highest to lowest precedence. This matters when
- // looking up a symbol by value.
+ // looking up a symbol by value, since multiple symbols can have the same value.
Unknown = 0,
User, // user-defined label
Project, // from project configuration file
Platform, // from platform definition file
- Auto // auto-generated
+ Auto // auto-generated label
}
///
@@ -48,15 +48,13 @@ namespace SourceGen {
Constant // constant value
}
- ///
/// Returns true if the symbol's type is an internal label (auto or user). Returns
/// false for external addresses and constants.
///
public bool IsInternalLabel {
get {
- return SymbolType == Type.LocalOrGlobalAddr ||
- SymbolType == Type.GlobalAddr ||
- SymbolType == Type.GlobalAddrExport;
+ // Could also check Type instead. Either works for now.
+ return SymbolSource == Source.User || SymbolSource == Source.Auto;
}
}