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:
parent
2607e408d5
commit
f9d0c8173d
@ -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,
|
||||
|
@ -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"'
|
||||
|
@ -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 =
|
||||
|
Loading…
Reference in New Issue
Block a user