1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-25 23:49:17 +00:00

Handle tricky case of abs.interp.'ing a repeat loop.

This commit is contained in:
Cat's Eye Technologies 2014-04-12 13:07:46 +01:00
parent 2607e408d5
commit f9d0c8173d
3 changed files with 81 additions and 26 deletions

View File

@ -87,10 +87,9 @@ blocks. The `with` construct takes an instruction like `sei` and implicitly
Abstract interpretation extends to `if` blocks. The two incoming contexts are
merged, and any storage locations poisoned in either context are considered
poisoned in the result context.
(Same should apply for `repeat` and `with` and, really, many other cases
which there just aren't enough test cases for yet.)
poisoned in the result context. (A similar case applies to `repeat` and
`with`, but these are different too as there is only one block and it is always
executed at least once.)
Declarations can have block scope. Such declarations may only be used within
the block in which they are declared. `reserve`d storage inside a block is not,

View File

@ -132,7 +132,7 @@ Routines can name registers as outputs.
= A: UpdatedWith (Immediate 8)
If a location is poisoned in either branch of an `if`, it is poisoned
after the `if`.
after the `if`. Note there are several tests for this.
| reserve byte score
| routine update_score
@ -224,24 +224,6 @@ after the `if`.
= X: UpdatedWith (Immediate 4)
= NamedLocation Nothing "score": UpdatedWith X
Poisoning a high byte or low byte of a word poisons the whole word.
| reserve word score
| reserve byte temp
| routine update_score
| {
| ldx #4
| stx <score
| }
| routine main {
| jsr update_score
| lda >score
| sta temp
| }
? routine 'main' does not preserve 'NamedLocation Nothing "score"'
Some more tests...
| assign word position $fb
| reserve byte value
|
@ -318,3 +300,73 @@ Some more tests...
| }
| }
? routine 'main' does not preserve 'A'
A storage location poisoned in a `repeat` continues to be poisoned
after the `repeat`.
| reserve byte value
|
| routine blah {
| lda #123
| }
| routine main {
| lda #33
| ldy #255
| repeat bne {
| jsr blah
| dey
| }
| sta value
| }
? routine 'main' does not preserve 'A'
Oh, here's a tricky one. The accumulator isn't poisoned on the first run
through the `repeat`, but it **is** on the second run through. We handle
this simply by abstractly interpreting the `repeat`'s block twice — the
second time in the context of having already interpreted it once.
| reserve byte value
|
| routine blah {
| lda #123
| }
| routine main {
| lda #33
| ldy #255
| repeat bne {
| sta value
| jsr blah
| dey
| }
| }
? routine 'main' does not preserve 'A'
Poisoning a high byte or low byte of a word poisons the whole word.
| reserve word score
| reserve byte temp
| routine update_score
| {
| ldx #4
| stx <score
| }
| routine main {
| jsr update_score
| lda >score
| sta temp
| }
? routine 'main' does not preserve 'NamedLocation Nothing "score"'
| reserve word score
| reserve byte temp
| routine update_score
| {
| ldx #4
| stx >score
| }
| routine main {
| jsr update_score
| lda <score
| sta temp
| }
? routine 'main' does not preserve 'NamedLocation Nothing "score"'

View File

@ -71,9 +71,13 @@ analyzeProgram program@(Program decls routines) =
in
mergeAlternateRoutCtxs nm routCtx1 routCtx2
checkInstr nm (REPEAT _ branch blk) progCtx routCtx =
-- TODO: oooh, this one's gonna be fun too
--checkBlock blk progCtx routCtx
routCtx
-- we analyze the block twice, to simulate it being
-- repeated. (see tests for a test case on this.
let
routCtx' = checkBlock nm blk progCtx routCtx
routCtx'' = checkBlock nm blk progCtx routCtx'
in
routCtx''
-- TODO -- THESE ARE WEAK --
checkInstr nm (WITH _ blk) progCtx routCtx =