Prefer narrower project/platform symbols

We want to be able to declare a symbol for a struct or buffer that
spans the entire width, and then declare more-specific items within
it that take precedence.  This worked for everything but the very
first byte, because on an exact match we were resolving the conflict
alphabetically.

Now, if one is wider than the other, we use the narrower definition.

Updated 2021-external-symbols with some additional test cases.
This commit is contained in:
Andy McFadden 2020-01-23 10:49:22 -08:00
parent 14ce56ec9a
commit c535201884
12 changed files with 139 additions and 35 deletions

View File

@ -334,6 +334,23 @@ namespace SourceGen {
return (maxStart <= minEnd);
}
/// <summary>
/// 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.
/// </summary>
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)) {

View File

@ -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

View File

@ -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

View File

@ -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":{

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

@ -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

View File

@ -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) {