santiontanon / mdlz80optimizer

MDL (a Z80 assembler optimizer)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Wrong nesting of labels

theNestruo opened this issue · comments

Using 0.8 (mdl-0.8-jar-with-dependencies.jar), self compiled from sources, on the examples of msxlib:

The first example (that has very few includes) does work:

>mdlz80 -dialect tniasm -I . games\examples\00minimal\minimal.asm

The other two examples (that have more includes) do not work:

>mdlz80 -dialect tniasm -I . games\examples\01basic\basic.asm      
WARNING: Style suggestion in lib/msx/io/print.asm#110: Unofficial op syntax: add #0030 converted to add a, #0030
(...)
WARNING: Style suggestion in lib/msx/io/timing.asm#49: Unofficial op syntax: add a converted to add a, a
ERROR: Redefining symbol LDIRVM_UNPACKED_CLRTBL_BANK.COL
ERROR: First defined in lib/msx/etc/fade.asm, 44 as $: LDIRVM_UNPACKED_CLRTBL_BANK.COL:
ERROR: Redefined in lib/msx/etc/fade.asm, 137 as $: LDIRVM_UNPACKED_CLRTBL_BANK.COL:   
ERROR: Problem expanding macros after loading all the source code!

>mdlz80 -dialect tniasm -I . games\examples\02snake\snake.asm      
WARNING: Style suggestion in lib/msx/io/print.asm#110: Unofficial op syntax: add #0030 converted to add a, #0030
(...)
WARNING: Style suggestion in lib/msx/io/timing.asm#49: Unofficial op syntax: add a converted to add a, a
ERROR: Redefining symbol LDIRVM_UNPACKED_CLRTBL_BANK.COL
ERROR: First defined in lib/msx/etc/fade.asm, 44 as $: LDIRVM_UNPACKED_CLRTBL_BANK.COL:
ERROR: Redefined in lib/msx/etc/fade.asm, 137 as $: LDIRVM_UNPACKED_CLRTBL_BANK.COL:
ERROR: Problem expanding macros after loading all the source code!

On a private project (not open source yet), the error is similar:

>mdlz80 -dialect tniasm -I . games\stevedore\stevedore.asm
WARNING: Style suggestion in lib/msx/io/print.asm#110: Unofficial op syntax: add #0030 converted to add a, #0030
(...)
WARNING: Style suggestion in lib/msx/etc/fade.asm#33: Unofficial op syntax: add c converted to add a, c
ERROR: Redefining symbol volatile_sprites.COL2
ERROR: First defined in lib/msx/etc/fade.asm, 24 as $: volatile_sprites.COL2:
ERROR: Redefined in lib/msx/etc/fade.asm, 117 as $: volatile_sprites.COL2:
ERROR: Problem expanding macros after loading all the source code!

In both cases, the error occurs while processing lib/msx/etc/fade.asm, but I guess that's a coincidence because it is the first included file with conditional assembly.
The label that fails matches the conditional assembly of their respective projects (.COL2 fails in the project that has CFG_FADE_TYPE_DOUBLE defined, and .COL fails in the project that has it undefined).
In both cases, it seems that the nested label is being nested to the wrong parent: lib/msx/io/vram.asm#LDIRVM_UNPACKED_CLRTBL_BANK and lib/msx/io/sprites.asm#volatile_sprites, that are not even in the same file as the nested label neither are the last parent label of their respective files.

Just confirming I was able to reproduce the issue! Will investigate now.

Alright, solved! I also added a new unit test for this thing in particular, to prevent breaking it again in the future.

The problem was that local label name resolution assumed the parser read lines sequentially. But when there are macros involved (e.g., like IFDEF), that's not the case. So, I coded it in a different way, that does not assume this sequential order.

Thanks for catching this btw! Since the same code was reused in tniasm, sjasm and asmsx, those dialects had the same issue. So, I took the chance to fix it for all of them too.

I'll close the issue, but please reopen if you try and it still does not work for you. I'll also update the 0.8 release with this fix just in case :)

The issues is not completely fixed.
msxlib examples are correcly parsed, but mdl fails to parse my private repository:

ERROR: Redefining symbol PLAYER_DY_TABLE.TOP_OFFSET
ERROR: First defined in games\stevedore\stevedore.asm, 320 as $ - PLAYER_DY_TABLE: PLAYER_DY_TABLE.TOP_OFFSET: equ $ - PLAYER_DY_TABLE
ERROR: Redefined in games\stevedore\stevedore.asm, 376 as $ - PLAYER_DY_TABLE: PLAYER_DY_TABLE.TOP_OFFSET: equ $

The offending lines (I hope these are enough to reproduce the problem):

; (...)
; Delta-Y (dY) table for jumping and falling
PLAYER_DY_TABLE:
	db	-4, -4			; (2,-8)
	db	-2, -2, -2		; (5,-14)
	db	-1, -1, -1, -1, -1, -1	; (11,-20)
	.TOP_OFFSET:	equ $ - PLAYER_DY_TABLE
	db	 0,  0,  0,  0,  0,  0	; (17,-20)
	.FALL_OFFSET:	equ $ - PLAYER_DY_TABLE
	db	1, 1, 1, 1, 1, 1	; (23,-14) / (6,6)
	db	2, 2, 2			; (26,-8) / (9,12)
	db	4
	.SIZE:		equ $ - PLAYER_DY_TABLE

; (...)

; Enemies delta-Y (dY) table for jumping and falling
	ENEMY_DY_TABLE:			equ PLAYER_DY_TABLE
	.TOP_OFFSET:			equ PLAYER_DY_TABLE.TOP_OFFSET
	.FALL_OFFSET:			equ PLAYER_DY_TABLE.FALL_OFFSET
	.SIZE:				equ PLAYER_DY_TABLE.SIZE
; (...)

I just realized that the game template of msxlib shows the same error; so you have an example to reproduce it:

>mdlz80 -dialect tniasm -I . games\template\template.asm

Oh! damn, haha. I thought I had this case covered haha. But ok! Let me make a note to look into it!

I'll try with template.asm first, and when I find the issue, I'll create a unit test to cover it in the future.

I just tried parsing games/template/template.asm, and it includes a missing file "lib/msx/vram_x.asm", maybe it's missing form the repo?

But just looking at the code above, I see the problem. The problem is the line:

ENEMY_DY_TABLE: equ PLAYER_DY_TABLE

MDL is not considering ENEMY_DY_TABLE as a label to resolve local labels to, since it has an "equ" and it is being assigned to something different than '$'. Thus when resolving ".TOP_OFFSET:" MDL keeps looking backwards until it finds an actual label (according to MDL's definition), and the one it finds is PLAYER_DY_TABLE.

I can definitively change this behavior for the tniasm dialect (it's a one line change, just remove the condition that "labels" must have the value "$"). But I just want to make sure I do it right :) So, imagine this situation:

LABEL:
CONSTANT: equ 1
.LOCAL:

In this example, is ".LOCAL" resolved as "CONSTANT.LOCAL" by tniasm or as "LABEL.LOCAL"? MDL would resolve it as "LABEL.LOCAL". (I will download tniasm tomorrow to try it myself, and make sure I get the right behavior :) )

I might also have to try it with the other dialects, as maybe it is just my misunderstanding that only labels with value $ are used for resolving local labels. So maybe have this wrong also for all other dialects! :)

The template should be fixed now, sorry about that (forgot to commit).

tniasm dummy.asm, with dummy.asm contents being...

LABEL:
CONSTANT: equ 1
.LOCAL:

...produces an empty output tniasm.out and the following tniasm.sym file:

LABEL: equ 00h ; last def. pass 2
CONSTANT.LOCAL: equ 00h ; last def. pass 2
CONSTANT: equ 01h ; last def. pass 2

Very interesting! Thanks theNestruo! Then this was my bad. I misinterpreted the way local labels work. I'll fix this tonight, and will also check in other assemblers to see if this is the case also in sjasm and asMSX (which is likely!)

I just tried with other assemblers, it is so interesting to see how they are all different, haha:

  • tniasm and sjasm do it as you describe. and ".LOCAL" gets resolved to "CONSTANT.LOCAL"
  • asMSX does not allow the colon in the equ, and if I remove it, it resolves ".LOCAL" as "LABEL.CONSTANT", as it does not consider CONSTANT a label

So, I'm updating the code to work as you describe above for tniasm and sjasm, and leave it as is for asMSX :)

I can confirm that with this change games\template\template.asm parses without errors!

Some problems still remain in asMSX though, which I will fix tomorrow. But today I set up a better testing pipeline, through which I can automatically run MDL in (currently) many different projects each time I make a change to make sure I don't break anything accidentally (and if I do, that'll help me create additional unit tests).