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; } }