Skip to content

Commit 488d4e2

Browse files
committed
Fix recursive function call that shouldnot be recursive.
Actually add the section to the smart link queue. Fix various smart linking issues Smart link after the linking script. Keep fully constrained sections with smart linking. Fix modifing the section hash map while you are iterating over it Remove the ffpad from the smart linking tests, it does not add anything while making the test script more complex and failing on Mac Fix some smart linking tests and remove some obviously broken/wrong ones. Add smart linking test to check if chained references are kept Remove -x link flag, as we cannot test everything we want with that Add a test to check if constrained sections are kept Add wram smart linking test, which will fail.
1 parent 4b93720 commit 488d4e2

37 files changed

+130
-85
lines changed

src/link/assign.c

+4
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,10 @@ void assign_AssignSections(void)
400400
/* Process linker script, if any */
401401
processLinkerScript();
402402

403+
/* After the linker script check if we need to do smart linking
404+
and discard any sections */
405+
sect_PerformSmartLink();
406+
403407
nbSectionsToAssign = 0;
404408
sect_ForEach(categorizeSection, NULL);
405409

src/link/main.c

-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,6 @@ int main(int argc, char *argv[])
296296

297297
/* then process them, */
298298
obj_DoSanityChecks();
299-
sect_PerformSmartLink();
300299
assign_AssignSections();
301300
obj_CheckAssertions();
302301
assign_Cleanup();

src/link/object.c

+4
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
382382
i, fileSections, fileNodes);
383383
}
384384
section->patches = patches;
385+
} else {
386+
section->data = NULL;
387+
section->nbPatches = 0;
388+
section->patches = NULL;
385389
}
386390

387391
section->smartLinked = false;

src/link/patch.c

+4
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ void patch_FindRefdSections(struct Patch const *patch, void (*callback)(struct S
567567
break;
568568

569569
case RPN_BANK_SYM:
570+
symbolID = 0;
570571
for (uint8_t shift = 0; shift < 32; shift += 8)
571572
symbolID |= getRPNByte(&expression, &size,
572573
patch->src, patch->lineNo) << shift;
@@ -603,7 +604,10 @@ void patch_FindRefdSections(struct Patch const *patch, void (*callback)(struct S
603604
case RPN_BANK_SELF:
604605
case RPN_HRAM:
605606
case RPN_RST:
607+
break;
606608
case RPN_CONST:
609+
for (uint8_t shift = 0; shift < 32; shift += 8)
610+
getRPNByte(&expression, &size, patch->src, patch->lineNo);
607611
break;
608612

609613
case RPN_SYM:

src/link/section.c

+46-9
Original file line numberDiff line numberDiff line change
@@ -368,22 +368,34 @@ void sect_AddSmartSection(char const *name)
368368
nbSmartLinkNames++;
369369
}
370370

371+
// Actually a stack, not a queue; however, the order in which sections are processed doesn't matter
372+
struct Section **smartLinkQueue;
373+
size_t queueSize = 0;
374+
size_t queueCapacity;
375+
371376
static void smartSectionPurge(void *arg, void *ign)
372377
{
373378
(void)ign;
374379
struct Section *sect = arg;
375380

376381
if (!sect->smartLinked) {
377382
verbosePrint("Dropping \"%s\" due to smart linking\n", sect->name);
378-
sect_RemoveSection(sect->name);
383+
384+
if (queueSize == queueCapacity) {
385+
if (queueCapacity == SIZE_MAX)
386+
error(NULL, 0, "Smart linking queue capacity exceeded!");
387+
else if (queueCapacity > SIZE_MAX / 2)
388+
queueCapacity = SIZE_MAX;
389+
else
390+
queueCapacity *= 2;
391+
smartLinkQueue = realloc(smartLinkQueue, sizeof(*smartLinkQueue) * queueCapacity);
392+
}
393+
394+
smartLinkQueue[queueSize] = sect;
395+
queueSize++;
379396
}
380397
}
381398

382-
// Actually a stack, not a queue; however, the order in which sections are processed doesn't matter
383-
struct Section **smartLinkQueue;
384-
size_t queueSize = 0;
385-
size_t queueCapacity;
386-
387399
static void queueSmartSection(struct Section *sect)
388400
{
389401
if (queueSize == queueCapacity) {
@@ -396,7 +408,12 @@ static void queueSmartSection(struct Section *sect)
396408
smartLinkQueue = realloc(smartLinkQueue, sizeof(*smartLinkQueue) * queueCapacity);
397409
}
398410

399-
sect->smartLinked = true;
411+
if (!sect->smartLinked) {
412+
sect->smartLinked = true;
413+
414+
smartLinkQueue[queueSize] = sect;
415+
queueSize++;
416+
}
400417
}
401418

402419
void sect_LinkSection(struct Section const *sect)
@@ -406,6 +423,19 @@ void sect_LinkSection(struct Section const *sect)
406423
patch_FindRefdSections(&sect->patches[i], queueSmartSection, (struct Symbol const * const *)sect->fileSymbols);
407424
}
408425

426+
static void smartLinkConstrained(void *arg, void *ign)
427+
{
428+
(void)ign;
429+
430+
struct Section *sect = arg;
431+
/* if a section isn't smart linked yet, but is fully constrained
432+
by address and bank, we want to smart link it as well */
433+
if (!sect->smartLinked && sect->isAddressFixed && sect->isBankFixed) {
434+
sect->smartLinked = true;
435+
sect_LinkSection(sect);
436+
}
437+
}
438+
409439
void sect_PerformSmartLink(void)
410440
{
411441
// If smart linking wasn't requested, do nothing
@@ -414,7 +444,7 @@ void sect_PerformSmartLink(void)
414444

415445
// Assume that each section is going to link a new one...
416446
queueCapacity = nbSmartLinkNames;
417-
smartLinkQueue = malloc(queueSize * sizeof(*smartLinkQueue));
447+
smartLinkQueue = malloc(queueCapacity * sizeof(*smartLinkQueue));
418448
if (!smartLinkQueue)
419449
error(NULL, 0, "Smart linking allocation failed: %s", strerror(errno));
420450

@@ -433,6 +463,8 @@ void sect_PerformSmartLink(void)
433463
}
434464
free(smartLinkNames);
435465

466+
hash_ForEach(sections, smartLinkConstrained, NULL);
467+
436468
// Also add sections referenced by assertions
437469
struct Assertion const *assertion = obj_GetFirstAssertion();
438470

@@ -444,7 +476,12 @@ void sect_PerformSmartLink(void)
444476
// As long as the queue isn't empty, get the last one, and process it
445477
while (queueSize)
446478
sect_LinkSection(smartLinkQueue[--queueSize]);
447-
free(smartLinkQueue);
448479

480+
// Find each section that needs to be removed and put it in the smartLinkQueue
449481
hash_ForEach(sections, smartSectionPurge, NULL);
482+
483+
// Remove all entries that need to be purged. (cannot be done during hash_ForEach)
484+
while (queueSize)
485+
sect_RemoveSection(smartLinkQueue[--queueSize]->name);
486+
free(smartLinkQueue);
450487
}

src/link/symbol.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct Symbol *sym_GetSymbol(char const *name)
6767

6868
void sym_RemoveSymbol(char const *name)
6969
{
70-
sym_RemoveSymbol(hash_RemoveElement(symbols, name));
70+
hash_RemoveElement(symbols, name);
7171
}
7272

7373
void sym_CleanupSymbols(void)

test/link/smart/assert.asm

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ SECTION "root", ROM0[0]
33

44
db Label
55

6-
SECTION "A", ROM0[1]
6+
SECTION "A", ROM0
77

88
Label:
99
db 2, Label
1010

1111
assert Unrefd == 3 ; The assertion will reference section "B"
1212

13-
SECTION "B", ROM0[3]
13+
SECTION "B", ROM0
1414

1515
Unrefd:
1616
db Unrefd ; References itself, but unless referenced externally, that doesn't matter

test/link/smart/assert.bin

16 KB
Binary file not shown.

test/link/smart/assert.smart.bin

16 KB
Binary file not shown.

test/link/smart/chain-wram.asm

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
SECTION "root", ROM0[0]
2+
dw WRAMLabel
3+
4+
; This section should be kept thanks to the reference from the WRAM section
5+
SECTION "A", ROM0
6+
Label:
7+
db $01, $02
8+
.end:
9+
10+
SECTION "wram", WRAM0
11+
WRAMLabel:
12+
ds Label.end - Label
13+
14+
SECTION "UnRef", ROM0
15+
UnRef:
16+
db UnRef

test/link/smart/chain-wram.bin

16 KB
Binary file not shown.

test/link/smart/chain-wram.smart.bin

16 KB
Binary file not shown.

test/link/smart/chain.asm

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; If multiple sections are chained together by references
2+
; they all should be kept if they can be traced back to a root
3+
SECTION "root", ROM0[0]
4+
db LabelA
5+
6+
SECTION "A", ROM0
7+
LabelA:
8+
db LabelB
9+
ds 3, $EE
10+
11+
SECTION "B", ROM0
12+
LabelB:
13+
db LabelC
14+
ds 2, $EE
15+
16+
SECTION "C", ROM0
17+
LabelC:
18+
db $ff
19+
ds 1, $EE
20+
21+
SECTION "unref", ROM0
22+
UnRef:
23+
db UnRef

test/link/smart/chain.bin

16 KB
Binary file not shown.

test/link/smart/chain.smart.bin

16 KB
Binary file not shown.

test/link/smart/const.asm

-17
This file was deleted.

test/link/smart/const.bin

-1
This file was deleted.

test/link/smart/const.smart.bin

-1
This file was deleted.

test/link/smart/const_assert.asm

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ SECTION "root", ROM0[0]
33

44
db Label
55

6-
SECTION "A", ROM0[1]
6+
SECTION "A", ROM0
77

88
Label:
99
db 2, Label
1010

11-
SECTION "B", ROM0[3]
11+
SECTION "B", ROM0
1212

1313
Unrefd:
1414
db Unrefd ; References itself, but unless referenced externally, that doesn't matter
1515

16-
assert Unrefd == 3 ; The assertion should reference section "B"... but it'll be resolved by RGBASM
16+
assert Label == 1 ; This assert will be ignored when smart linking, as nothing references section "B"

test/link/smart/const_assert.bin

16 KB
Binary file not shown.
16 KB
Binary file not shown.

test/link/smart/const_sect.asm

-17
This file was deleted.

test/link/smart/const_sect.bin

-1
This file was deleted.

test/link/smart/const_sect.smart.bin

-1
This file was deleted.

test/link/smart/constexpr.asm

-14
This file was deleted.

test/link/smart/constexpr.bin

-1
This file was deleted.

test/link/smart/constexpr.smart.bin

-1
This file was deleted.

test/link/smart/constrained.asm

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; Fully constrained sections need to be kept
2+
SECTION "root", ROM0[0]
3+
4+
5+
; This section is fully constrained and should be kept
6+
SECTION "01", ROM0[1]
7+
db $01
8+
9+
; This section is not fully constrained and should not be kept, bank is unknown.
10+
SECTION "02", ROMX[$4002]
11+
db $02
12+
13+
; This section is fully constrained and should be kept
14+
SECTION "03", ROMX[$4003], BANK[1]
15+
db $03

test/link/smart/constrained.bin

32 KB
Binary file not shown.

test/link/smart/constrained.smart.bin

32 KB
Binary file not shown.

test/link/smart/label-diff.asm

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
SECTION "A", ROM0[1]
2+
SECTION "A", ROM0
33

44
Label:
55
db 2, Label
@@ -9,7 +9,7 @@ SECTION "root", ROM0[0]
99

1010
db Label.end - Label
1111

12-
SECTION "B", ROM0[3]
12+
SECTION "B", ROM0
1313

1414
Unrefd:
1515
db Unrefd

test/link/smart/label-diff.bin

16 KB
Binary file not shown.

test/link/smart/label-diff.smart.bin

16 KB
Binary file not shown.

test/link/smart/simple.asm

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ SECTION "root", ROM0[0]
33

44
db Label
55

6-
SECTION "A", ROM0[1]
6+
SECTION "A", ROM0
77

88
Label:
99
db 2, Label
1010

11-
SECTION "B", ROM0[3]
11+
SECTION "B", ROM0
1212

1313
Unrefd:
1414
db Unrefd ; References itself, but unless referenced externally, that doesn't matter

test/link/smart/simple.bin

16 KB
Binary file not shown.

test/link/smart/simple.smart.bin

16 KB
Binary file not shown.

test/link/test.sh

+8-11
Original file line numberDiff line numberDiff line change
@@ -97,21 +97,18 @@ for i in *.asm; do
9797
fi
9898
done
9999

100-
ffpad() { # Pads $1 to size $3 into $2 with 0xFF bytes
101-
dd if=/dev/zero count=1 ibs=$3 2>/dev/null | tr '\000' '\377' > $2
102-
dd if="$1" of=$2 conv=notrunc 2>/dev/null
103-
}
104100
for i in smart/*.asm; do
105101
startTest
106102
$RGBASM -o $otemp $i
107-
$RGBLINK -p 0xff -o $gbtemp $otemp
108-
SIZE=$(wc -c $gbtemp | cut -d ' ' -f 1)
109-
ffpad "${i%.asm}.bin" $gbtemp2 $SIZE
110-
tryCmp $gbtemp2 $gbtemp
103+
rm $gbtemp
104+
$RGBLINK -o $gbtemp $otemp
105+
tryCmp "${i%.asm}.bin" $gbtemp
111106
rc=$(($? || $rc))
112-
$RGBLINK -p 0xff -vs "root" -o $gbtemp $otemp
113-
ffpad "${i%.asm}.smart.bin" $gbtemp2 $SIZE
114-
tryCmp $gbtemp2 $gbtemp
107+
rm $gbtemp
108+
i="${i%.asm}.smart"
109+
startTest
110+
$RGBLINK -vs "root" -o $gbtemp $otemp
111+
tryCmp "$i.bin" $gbtemp
115112
rc=$(($? || $rc))
116113
done
117114

0 commit comments

Comments
 (0)