em_reset cleared only one row of em_meth_label: ldx #$FF / dex / bpl exits
after the first store because $FE is negative. Method label ids from the count
pass survived into the emitting pass after fl_init had freed every flow label,
so a later fl_alloc could hand the same id to another label. The loop now
clears all 256 rows, and labels are stored as id + 1 so 0 means unassigned.
hello-test.s never cleared em_on. Since 5489ae6 added emitter BSS, em_on lands
on RAM that VICE's power-on pattern leaves non-zero, so the statement emitter
ran without print vectors and reported E227 at end program. The fixture now
clears em_on before parse_file, as every emitter caller must.
harness.tests.ps1 embedded quotes in arguments for the call operator, which
PowerShell 7.3+ escapes into the path; it now passes plain arguments and runs
under both Windows PowerShell 5.1 and PowerShell 7.
main
| @@ -108,16 +108,34 @@ supply frame entry points keep their previous code shape (D156). | |||||
| `planning/epics-and-stories.md`, `planning/claims/E04-S08.md`. | `planning/epics-and-stories.md`, `planning/claims/E04-S08.md`. | ||||
| - Remaining risks: interface arguments and four-byte interface returns are not | - Remaining risks: interface arguments and four-byte interface returns are not | ||||
| emitted (E06-S07); arguments are limited to `EM_ARG_MAX` (8) staged values; | emitted (E06-S07); arguments are limited to `EM_ARG_MAX` (8) staged values; | ||||
| the prologue's failure path returns without a diagnostic, so a refused frame | |||||
| is currently silent; and the pre-existing `calls` suite failure described | |||||
| below is unrelated but still red. | |||||
| ## Known unrelated failure | |||||
| `calls` fails on a **fresh** build with `EM_ERR_LABEL` (7) and | |||||
| `FL_ERR_STATE` (3), `cg_len = 0x31`, while the same test passes when the build | |||||
| directory's older object files are reused. The identical signature reproduces | |||||
| on pristine `8a2d8ce` (verified by `git stash` + fresh `build/calls-test`), so | |||||
| it predates this story and points at emitter label state that is not | |||||
| deterministically initialized. It is not caused by E04-S08 and needs its own | |||||
| fix (initialize or validate the per-row method-label table before pass 2). | |||||
| and the prologue's failure path returns without a diagnostic, so a refused | |||||
| frame is currently silent. | |||||
| ## Related label fix | |||||
| A fresh-build failure with `EM_ERR_LABEL` (7) and `FL_ERR_STATE` (3) reproduced | |||||
| on pristine `8a2d8ce` and was independent of this story. Its cause was the | |||||
| method-label table's `$FF` sentinel: any row whose byte was not `$FF` was taken | |||||
| as an already-assigned label 0, so a later method redefined it at a different | |||||
| offset. `em_reset` now clears the table to zero, `em_method_label` stores each | |||||
| label as `id + 1`, and a lookup outside 1..`FL_LABELS` allocates again. Fresh | |||||
| `calls` and `args` runs now pass. | |||||
| The clear loop itself was also wrong: `ldx #$FF` / `dex` / `bpl` stops after | |||||
| one row because `$FE` is negative, so ids from the count pass survived into the | |||||
| emitting pass after `fl_init` had freed every flow label. The loop now counts | |||||
| X up from 0 until it wraps, clearing all 256 rows on every `em_reset`. | |||||
| ## Hello fixture regression | |||||
| `hello` failed at HEAD with `E227 CANNOT EMIT THIS CODE YET` at `end program` | |||||
| (verified passing at `221e0c5`, failing at `5489ae6`). `hello-test.s` never set | |||||
| `em_on`, and the new BSS variables moved it onto RAM that VICE's power-on | |||||
| pattern leaves non-zero, so the statement emitter ran without print vectors. | |||||
| The fixture now clears `em_on` before `parse_file`, as the emitter contract | |||||
| requires of every caller. | |||||
| The `parser` suite's verification passes, but its baseline hashes in | |||||
| `tests/regression/baseline.json` predate `221e0c5` and `5489ae6`; pristine | |||||
| HEAD's `parser-test.prg` already differs, so that entry needs a reviewed | |||||
| refresh. | |||||
| @@ -98,10 +98,11 @@ em_reset: | |||||
| sta em_n_routines | sta em_n_routines | ||||
| lda #$FF | lda #$FF | ||||
| sta em_loc_next | sta em_loc_next | ||||
| ldx #$FF | |||||
| lda #$00 ; clear all 256 rows; X wraps $00 -> $00 | |||||
| tax | |||||
| @meth: sta em_meth_label,x | @meth: sta em_meth_label,x | ||||
| dex | |||||
| bpl @meth | |||||
| inx | |||||
| bne @meth | |||||
| lda #$02 | lda #$02 | ||||
| sta em_par_next | sta em_par_next | ||||
| rts | rts | ||||
| @@ -685,17 +686,24 @@ em_method_label: | |||||
| sta em_nid | sta em_nid | ||||
| tax | tax | ||||
| lda em_meth_label,x | lda em_meth_label,x | ||||
| cmp #$FF | |||||
| bne @have | |||||
| lda em_nid | |||||
| beq @alloc | |||||
| cmp #FL_LABELS + 1 | |||||
| bcs @alloc | |||||
| sec | |||||
| sbc #$01 | |||||
| tax | |||||
| clc | |||||
| rts | |||||
| @alloc: lda em_nid | |||||
| jsr fl_alloc | jsr fl_alloc | ||||
| bcs @bad | bcs @bad | ||||
| ldy em_nid | ldy em_nid | ||||
| sta em_meth_label,y | sta em_meth_label,y | ||||
| tax | tax | ||||
| lda em_meth_label,y | |||||
| clc | clc | ||||
| rts | |||||
| @have: tax | |||||
| adc #$01 | |||||
| sta em_meth_label,y | |||||
| clc | clc | ||||
| rts | rts | ||||
| @bad: lda #EM_ERR_LABEL | @bad: lda #EM_ERR_LABEL | ||||
| @@ -27,6 +27,7 @@ | |||||
| .import out_byte, out_bytes, out_finish, out_abort | .import out_byte, out_bytes, out_finish, out_abort | ||||
| .import out_load, out_entry, out_start, out_err | .import out_load, out_entry, out_start, out_err | ||||
| .import gen_stub | .import gen_stub | ||||
| .import em_on | |||||
| ; A conditional branch to a far error path: near branch over an absolute JMP. | ; A conditional branch to a far error path: near branch over an absolute JMP. | ||||
| .macro ON_CARRY target | .macro ON_CARRY target | ||||
| @@ -104,6 +105,7 @@ test_entry: | |||||
| jsr diag_init | jsr diag_init | ||||
| lda #$00 ; ERR files only; keep the screen quiet | lda #$00 ; ERR files only; keep the screen quiet | ||||
| sta diag_screen | sta diag_screen | ||||
| sta em_on ; captured-print proof: no statement emitter | |||||
| jsr parse_file | jsr parse_file | ||||
| jsr diag_finish | jsr diag_finish | ||||
| sta diag_count | sta diag_count | ||||
| @@ -66,9 +66,11 @@ exit 0 | |||||
| '@, [Text.UTF8Encoding]::new($false)) | '@, [Text.UTF8Encoding]::new($false)) | ||||
| function Invoke-Harness([string[]]$Extra) { | function Invoke-Harness([string[]]$Extra) { | ||||
| $arguments = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ('"' + $harness + '"'), | |||||
| "-Manifest", ('"' + $manifest + '"'), "-BuildRoot", ('"' + $buildRoot + '"'), | |||||
| "-Baseline", ('"' + $baseline + '"'), "-Results", ('"' + $results + '"')) + $Extra | |||||
| # The call operator quotes arguments that contain spaces itself. Embedding | |||||
| # quotes here breaks PowerShell 7.3+, which escapes them into the path. | |||||
| $arguments = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $harness, | |||||
| "-Manifest", $manifest, "-BuildRoot", $buildRoot, | |||||
| "-Baseline", $baseline, "-Results", $results) + $Extra | |||||
| $output = & (Get-Command powershell).Source @arguments 2>&1 | Out-String | $output = & (Get-Command powershell).Source @arguments 2>&1 | Out-String | ||||
| return @{ Output = $output; Code = $LASTEXITCODE } | return @{ Output = $output; Code = $LASTEXITCODE } | ||||
| } | } | ||||
Powered by TurnKey Linux.