diff --git a/SourceGen/DefSymbol.cs b/SourceGen/DefSymbol.cs index 4e2124e..faa42be 100644 --- a/SourceGen/DefSymbol.cs +++ b/SourceGen/DefSymbol.cs @@ -334,6 +334,23 @@ namespace SourceGen { return (maxStart <= minEnd); } + /// + /// Determines whether symbol one is "wider" than symbol two. It's wider if it + /// has a width, and the other symbol either doesn't have a width or has a width + /// but is narrower. + /// + public static bool IsWider(DefSymbol a, DefSymbol b) { + if (!a.HasWidth && !b.HasWidth) { + return false; + } else if (a.HasWidth && !b.HasWidth) { + return true; + } else if (!a.HasWidth && b.HasWidth) { + return false; + } else { + return a.DataDescriptor.Length > b.DataDescriptor.Length; + } + } + public static bool operator ==(DefSymbol a, DefSymbol b) { if (ReferenceEquals(a, b)) { diff --git a/SourceGen/DisasmProject.cs b/SourceGen/DisasmProject.cs index 8c67a09..b4e4c82 100644 --- a/SourceGen/DisasmProject.cs +++ b/SourceGen/DisasmProject.cs @@ -1693,27 +1693,15 @@ namespace SourceGen { return -1; } else if (a.Value > b.Value) { return 1; - } else if (IsWider(a, b)) { + } else if (DefSymbol.IsWider(a, b)) { return -1; - } else if (IsWider(b, a)) { + } else if (DefSymbol.IsWider(b, a)) { return 1; } return Asm65.Label.LABEL_COMPARER.Compare(a.Label, b.Label); }); } - private bool IsWider(DefSymbol a, DefSymbol b) { - if (!a.HasWidth && !b.HasWidth) { - return false; - } else if (a.HasWidth && !b.HasWidth) { - return true; - } else if (!a.HasWidth && !b.HasWidth) { - return true; - } else { - return a.DataDescriptor.Length > b.DataDescriptor.Length; - } - } - #endregion Analysis diff --git a/SourceGen/SGTestData/2021-external-symbols b/SourceGen/SGTestData/2021-external-symbols index b1d9202..cdd85ed 100644 Binary files a/SourceGen/SGTestData/2021-external-symbols and b/SourceGen/SGTestData/2021-external-symbols differ diff --git a/SourceGen/SGTestData/2021-external-symbols-1.sym65 b/SourceGen/SGTestData/2021-external-symbols-1.sym65 index cdaaa98..8e76ba1 100644 --- a/SourceGen/SGTestData/2021-external-symbols-1.sym65 +++ b/SourceGen/SGTestData/2021-external-symbols-1.sym65 @@ -26,8 +26,8 @@ ChkProj1 @ $2200 4 ChkProj2 @ $2204 4 ; Overlapping regions, defined within a single platform file. We -; should always use the most-recently-defined symbol. When all -; else is equal, alphabetical. +; should prefer matches by proximity and width. When all else is +; equal, choose alphabetically. Over1 @ $3000 16 ;$3000-300f, inclusive Over2 @ $3002 8 ;$3002-3009 Over3 @ $3006 7 ;$3006-300c @@ -54,6 +54,20 @@ BankWrap @ $fff0 $20 ; Width specifiers on constants should be ignored. FatConst = $4000 8 +; Overlapping multi-byte items with exact and inexact matches. +OverA_0 @ $6000 8 ;should win, alphabetically +OverB_0 @ $6000 8 +OverB_1 @ $6100 8 ;(file order reversed) +OverA_1 @ $6100 8 ;should win, alphabetically +OverA_2 @ $6200 8 +OverB_2 @ $6200 ;should win because narrower +OverA_3 @ $6300 8 ;(ref OverA_3+4) +OverB_3 @ $6300 7 ;should win because narrower +OverA_4 @ $6401 8 ;(ref OverA_4+2) +OverB_4 @ $6402 8 ;should win because closer +OverC_4 @ $6403 8 + + ; I/O direction test ReadOnly < $5000 2 ;R WriteOnly > $5001 2 ;W diff --git a/SourceGen/SGTestData/2021-external-symbols.dis65 b/SourceGen/SGTestData/2021-external-symbols.dis65 index f5965fa..b740ba0 100644 --- a/SourceGen/SGTestData/2021-external-symbols.dis65 +++ b/SourceGen/SGTestData/2021-external-symbols.dis65 @@ -1,6 +1,6 @@ ### 6502bench SourceGen dis65 v1.0 ### { -"_ContentVersion":2,"FileDataLength":329,"FileDataCrc32":-573118187,"ProjectProps":{ +"_ContentVersion":2,"FileDataLength":353,"FileDataCrc32":2100812075,"ProjectProps":{ "CpuName":"6502","IncludeUndocumentedInstr":false,"EntryFlags":32702671,"AutoLabelStyle":"Simple","AnalysisParams":{ "AnalyzeUncategorizedData":true,"DefaultTextScanMode":"LowHighAscii","MinCharsForString":4,"SeekNearbyTargets":true,"SmartPlpHandling":true}, "PlatformSymbolFileIdentifiers":["PROJ:2021-external-symbols-1.sym65","PROJ:2021-external-symbols-2.sym65","PROJ:2021-external-symbols-3.sym65"],"ExtensionScriptFileIdentifiers":[],"ProjectSyms":{ diff --git a/SourceGen/SGTestData/Expected/2021-external-symbols_64tass.S b/SourceGen/SGTestData/Expected/2021-external-symbols_64tass.S index 7a8d89f..b0633f1 100644 --- a/SourceGen/SGTestData/Expected/2021-external-symbols_64tass.S +++ b/SourceGen/SGTestData/Expected/2021-external-symbols_64tass.S @@ -22,6 +22,13 @@ SepOver2 = $3102 ;$3102-3105, inclusive ReadOnly = $5000 ;R WriteOnly = $5001 ;W WriteOnly2 = $5002 +OverA_0 = $6000 ;should win, alphabetically +OverA_1 = $6100 ;should win, alphabetically +OverB_2 = $6200 ;should win because narrower +OverB_3 = $6300 ;should win because narrower +OverA_4 = $6401 ;(ref OverA_4+2) +OverB_4 = $6402 ;should win because closer +OverC_4 = $6403 MultiRead = $c004 ;$c004/5/6, read-only MultiWrite = $c005 ;$c005/6/7, write-only AlsoMultiZero = $c010 ;wins (alphabetically) @@ -35,9 +42,9 @@ BankWrap = $fff0 L1000 lda CodeWrap+255 ldx L1000 ldy L1000+1 - lda _L1148 - lda CodeWrap+$249 - lda CodeWrap+$250 + lda _L1160 + lda CodeWrap+$261 + lda CodeWrap+$268 nop lda $1ffe lda SameName1-1 @@ -155,5 +162,13 @@ LocalVar .var $41 bit MoreMultiZero+32 bit MoreMultiZero+240 nop -_L1148 rts + lda OverA_0 + lda OverA_1 + lda OverB_2 + lda OverB_3+4 + lda OverA_4-1 + lda OverA_4 + lda OverB_4 + lda OverC_4 +_L1160 rts diff --git a/SourceGen/SGTestData/Expected/2021-external-symbols_Merlin32.S b/SourceGen/SGTestData/Expected/2021-external-symbols_Merlin32.S index 88f4252..e5b578d 100644 --- a/SourceGen/SGTestData/Expected/2021-external-symbols_Merlin32.S +++ b/SourceGen/SGTestData/Expected/2021-external-symbols_Merlin32.S @@ -21,6 +21,13 @@ SepOver2 equ $3102 ;$3102-3105, inclusive ReadOnly equ $5000 ;R WriteOnly equ $5001 ;W WriteOnly2 equ $5002 +OverA_0 equ $6000 ;should win, alphabetically +OverA_1 equ $6100 ;should win, alphabetically +OverB_2 equ $6200 ;should win because narrower +OverB_3 equ $6300 ;should win because narrower +OverA_4 equ $6401 ;(ref OverA_4+2) +OverB_4 equ $6402 ;should win because closer +OverC_4 equ $6403 MultiRead equ $c004 ;$c004/5/6, read-only MultiWrite equ $c005 ;$c005/6/7, write-only AlsoMultiZero equ $c010 ;wins (alphabetically) @@ -34,9 +41,9 @@ BankWrap equ $fff0 L1000 lda CodeWrap+255 ldx L1000 ldy L1000+1 - lda :L1148 - lda CodeWrap+$249 - lda CodeWrap+$250 + lda :L1160 + lda CodeWrap+$261 + lda CodeWrap+$268 nop lda $1ffe lda SameName1-1 @@ -154,5 +161,13 @@ L1000 lda CodeWrap+255 bit MoreMultiZero+32 bit MoreMultiZero+240 nop -:L1148 rts + lda OverA_0 + lda OverA_1 + lda OverB_2 + lda OverB_3+4 + lda OverA_4-1 + lda OverA_4 + lda OverB_4 + lda OverC_4 +:L1160 rts diff --git a/SourceGen/SGTestData/Expected/2021-external-symbols_acme.S b/SourceGen/SGTestData/Expected/2021-external-symbols_acme.S index 2439019..15fd1c6 100644 --- a/SourceGen/SGTestData/Expected/2021-external-symbols_acme.S +++ b/SourceGen/SGTestData/Expected/2021-external-symbols_acme.S @@ -22,6 +22,13 @@ SepOver2 = $3102 ;$3102-3105, inclusive ReadOnly = $5000 ;R WriteOnly = $5001 ;W WriteOnly2 = $5002 +OverA_0 = $6000 ;should win, alphabetically +OverA_1 = $6100 ;should win, alphabetically +OverB_2 = $6200 ;should win because narrower +OverB_3 = $6300 ;should win because narrower +OverA_4 = $6401 ;(ref OverA_4+2) +OverB_4 = $6402 ;should win because closer +OverC_4 = $6403 MultiRead = $c004 ;$c004/5/6, read-only MultiWrite = $c005 ;$c005/6/7, write-only AlsoMultiZero = $c010 ;wins (alphabetically) @@ -35,9 +42,9 @@ BankWrap = $fff0 L1000 lda CodeWrap+255 ldx L1000 ldy L1000+1 - lda @L1148 - lda CodeWrap+$249 - lda CodeWrap+$250 + lda @L1160 + lda CodeWrap+$261 + lda CodeWrap+$268 nop lda $1ffe lda SameName1-1 @@ -156,5 +163,13 @@ L1000 lda CodeWrap+255 bit MoreMultiZero+32 bit MoreMultiZero+240 nop -@L1148 rts + lda OverA_0 + lda OverA_1 + lda OverB_2 + lda OverB_3+4 + lda OverA_4-1 + lda OverA_4 + lda OverB_4 + lda OverC_4 +@L1160 rts diff --git a/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.S b/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.S index b3f3a22..1068270 100644 --- a/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.S +++ b/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.S @@ -22,6 +22,13 @@ SepOver2 = $3102 ;$3102-3105, inclusive ReadOnly = $5000 ;R WriteOnly = $5001 ;W WriteOnly2 = $5002 +OverA_0 = $6000 ;should win, alphabetically +OverA_1 = $6100 ;should win, alphabetically +OverB_2 = $6200 ;should win because narrower +OverB_3 = $6300 ;should win because narrower +OverA_4 = $6401 ;(ref OverA_4+2) +OverB_4 = $6402 ;should win because closer +OverC_4 = $6403 MultiRead = $c004 ;$c004/5/6, read-only MultiWrite = $c005 ;$c005/6/7, write-only AlsoMultiZero = $c010 ;wins (alphabetically) @@ -36,9 +43,9 @@ BankWrap = $fff0 L1000: lda CodeWrap+255 ldx L1000 ldy L1000+1 - lda L1148 - lda CodeWrap+$249 - lda CodeWrap+$250 + lda L1160 + lda CodeWrap+$261 + lda CodeWrap+$268 nop lda $1ffe lda SameName1-1 @@ -156,5 +163,13 @@ LocalVar .set $41 bit MoreMultiZero+32 bit MoreMultiZero+240 nop -L1148: rts + lda OverA_0 + lda OverA_1 + lda OverB_2 + lda OverB_3+4 + lda OverA_4-1 + lda OverA_4 + lda OverB_4 + lda OverC_4 +L1160: rts diff --git a/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.cfg b/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.cfg index 13d527a..45f3af5 100644 --- a/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.cfg +++ b/SourceGen/SGTestData/Expected/2021-external-symbols_cc65.cfg @@ -1,7 +1,7 @@ # 6502bench SourceGen generated linker script for 2021-external-symbols MEMORY { MAIN: file=%O, start=%S, size=65536; -# MEM000: file=%O, start=$1000, size=329; +# MEM000: file=%O, start=$1000, size=353; } SEGMENTS { CODE: load=MAIN, type=rw; diff --git a/SourceGen/SGTestData/Source/2021-external-symbols.S b/SourceGen/SGTestData/Source/2021-external-symbols.S index 5e45e3d..4810d8e 100644 --- a/SourceGen/SGTestData/Source/2021-external-symbols.S +++ b/SourceGen/SGTestData/Source/2021-external-symbols.S @@ -166,4 +166,14 @@ Dir equ $5000 nop +; test some more overlapping symbols + lda $6000 ;OverA_0 + lda $6100 ;OverA_1 + lda $6200 ;OverB_2 + lda $6304 ;OverB_3 + 4 + lda $6400 ;OverA_4 - 1 + lda $6401 ;OverA_4 + lda $6402 ;OverB_4 + lda $6403 ;OverC_4 + END rts diff --git a/SourceGen/SymbolTable.cs b/SourceGen/SymbolTable.cs index 9948c01..8209002 100644 --- a/SourceGen/SymbolTable.cs +++ b/SourceGen/SymbolTable.cs @@ -41,7 +41,11 @@ The basic rules for determining the symbol associated with a given address are: BAR=$2005/10, $2004 would be FOO and $2005 would be BAR. (Note this can only happen for two symbols inside the same platform file or in the project symbol definitions; otherwise one of the previous rules would have determined it.) - 5. If everything else is equal, e.g. we have FOO=$2000 and BAR=$2000 in the same file, + 5. If two symbols have the same value, and one is wider than the other, we use the + narrower definition. The previous definition allows you to declare a symbol that spans + a buffer and then define individual values within it; this rule makes it work right + for the first byte. + 6. If everything else is equal, e.g. we have FOO=$2000 and BAR=$2000 in the same file, the winner is determined alphabetically. (We don't track symbol definition line numbers, and there's no definite order in project properties, so there's not much else to do.) @@ -433,6 +437,17 @@ namespace SourceGen { return sym2; } + // Check widths. Prefer the narrower definition. + if (sym1 is DefSymbol && sym2 is DefSymbol) { + DefSymbol dsym1 = (DefSymbol)sym1; + DefSymbol dsym2 = (DefSymbol)sym2; + if (DefSymbol.IsWider(dsym1, dsym2)) { + return dsym2; + } else if (DefSymbol.IsWider(dsym2, dsym1)) { + return dsym1; + } + } + // In the absence of anything better, we select them alphabetically. (If they have // the same name, value, and source, there's not much to distinguish them anyway.) if (Asm65.Label.LABEL_COMPARER.Compare(sym1.Label, sym2.Label) < 0) {