mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-24 15:29:23 +00:00
#11 Fix allocation of variables in functions with trampolines
This commit is contained in:
parent
f65651f2c0
commit
ff46129c4e
@ -119,6 +119,10 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
if (forZpOnly && !options.platform.hasZeroPage) {
|
if (forZpOnly && !options.platform.hasZeroPage) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (nf.exists(_.name.endsWith(".trampoline"))) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (log.traceEnabled) log.trace("Allocating variables in " + nf.map(f => "function " + f.name).getOrElse("global scope"))
|
||||||
val b = get[Type]("byte")
|
val b = get[Type]("byte")
|
||||||
val p = get[Type]("pointer")
|
val p = get[Type]("pointer")
|
||||||
val params = nf.fold(List[String]()) { f =>
|
val params = nf.fold(List[String]()) { f =>
|
||||||
@ -146,6 +150,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
} else 3
|
} else 3
|
||||||
val toAdd = things.values.flatMap {
|
val toAdd = things.values.flatMap {
|
||||||
case m: UninitializedMemory if passForAlloc(m.alloc) == pass && nf.isDefined == isLocalVariableName(m.name) && !m.name.endsWith(".addr") && maybeGet[Thing](m.name + ".array").isEmpty =>
|
case m: UninitializedMemory if passForAlloc(m.alloc) == pass && nf.isDefined == isLocalVariableName(m.name) && !m.name.endsWith(".addr") && maybeGet[Thing](m.name + ".array").isEmpty =>
|
||||||
|
if (log.traceEnabled) log.trace("Allocating " + m.name)
|
||||||
val vertex = if (options.flag(CompilationFlag.VariableOverlap)) {
|
val vertex = if (options.flag(CompilationFlag.VariableOverlap)) {
|
||||||
nf.fold[VariableVertex](GlobalVertex) { f =>
|
nf.fold[VariableVertex](GlobalVertex) { f =>
|
||||||
if (m.alloc == VariableAllocationMethod.Static) {
|
if (m.alloc == VariableAllocationMethod.Static) {
|
||||||
|
@ -182,6 +182,12 @@ class StandardCallGraph(program: Program, log: Logger) extends CallGraph(program
|
|||||||
if (multiaccessibleFunctions(a.function) || multiaccessibleFunctions(b.function)) {
|
if (multiaccessibleFunctions(a.function) || multiaccessibleFunctions(b.function)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if (a.function + ".trampoline" == b.function) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (a.function == b.function + ".trampoline") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (callEdges(a.function -> b.function) || callEdges(b.function -> a.function)) {
|
if (callEdges(a.function -> b.function) || callEdges(b.function -> a.function)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
108
src/test/scala/millfork/test/Issue11Test.scala
Normal file
108
src/test/scala/millfork/test/Issue11Test.scala
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package millfork.test
|
||||||
|
|
||||||
|
import millfork.Cpu
|
||||||
|
import millfork.test.emu.{EmuCrossPlatformBenchmarkRun, EmuUnoptimizedCmosRun}
|
||||||
|
import org.scalatest.{FunSuite, Matchers}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karol Stasiak
|
||||||
|
*/
|
||||||
|
class Issue11Test extends FunSuite with Matchers {
|
||||||
|
|
||||||
|
test("Test issue 11") {
|
||||||
|
val src =
|
||||||
|
"""
|
||||||
|
|import c64_basic
|
||||||
|
|import stdio
|
||||||
|
|
|
||||||
|
|struct Box {
|
||||||
|
| byte x,
|
||||||
|
| byte y,
|
||||||
|
| byte width,
|
||||||
|
| byte height
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|struct Phys_Obj {
|
||||||
|
| Box pos,
|
||||||
|
| byte xfrac,
|
||||||
|
| byte yfrac,
|
||||||
|
| sbyte xvel,
|
||||||
|
| sbyte yvel,
|
||||||
|
| byte xaccel,
|
||||||
|
| byte yaccel,
|
||||||
|
| byte xspeed,
|
||||||
|
| bool on_ground,
|
||||||
|
| bool jumping,
|
||||||
|
| bool can_jump
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|Phys_Obj player1
|
||||||
|
|byte output @$c000
|
||||||
|
|
|
||||||
|
|inline pointer get_metatile_column(word metatiles_column) {
|
||||||
|
| //This is the function where the original player pointer
|
||||||
|
| //gets corrupted.
|
||||||
|
| return pointer(metatiles_column)
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|byte get_tile(byte column, byte row) {
|
||||||
|
| byte tile
|
||||||
|
| pointer metatiles_column
|
||||||
|
|
|
||||||
|
| metatiles_column = get_metatile_column($0000)
|
||||||
|
| tile = $00
|
||||||
|
| return tile
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|void check_background_collis(byte screenx, byte screeny, byte spritewidth, byte spriteheight) {
|
||||||
|
| byte new_column1
|
||||||
|
| byte new_column2
|
||||||
|
| byte new_row1
|
||||||
|
| byte new_row2
|
||||||
|
| byte i
|
||||||
|
| byte limit
|
||||||
|
| byte current_tile
|
||||||
|
|
|
||||||
|
| current_tile = get_tile(0,0)
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|void check_player_collis_and_update_player_loc(pointer.Phys_Obj player) {
|
||||||
|
| sbyte temp_vel
|
||||||
|
| byte old_playerx
|
||||||
|
| byte old_playerx_frac
|
||||||
|
| byte old_playery
|
||||||
|
| byte old_playery_frac
|
||||||
|
|
|
||||||
|
| old_playerx = player1.pos.x
|
||||||
|
| old_playery = player1.pos.y
|
||||||
|
| old_playerx_frac = player1.xfrac
|
||||||
|
| old_playery_frac = player1.yfrac
|
||||||
|
|
|
||||||
|
| check_background_collis(player1.pos.x, player1.pos.y, player1.pos.width, player1.pos.height)
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|inline void game_logic(pointer.Phys_Obj player) {
|
||||||
|
| player->pos.x = 15
|
||||||
|
|
|
||||||
|
| //comment out this function call and the player
|
||||||
|
| //pointer should still point to the correct location
|
||||||
|
| check_player_collis_and_update_player_loc(player)
|
||||||
|
| //after the function call, player points to garbage
|
||||||
|
|
|
||||||
|
| //expected val: 15
|
||||||
|
| //if player no longer points to player1: garbage
|
||||||
|
| output = player->pos.x
|
||||||
|
|}
|
||||||
|
|
|
||||||
|
|void main() {
|
||||||
|
| pointer.Phys_Obj player
|
||||||
|
| player = pointer.Phys_Obj(player1.addr)
|
||||||
|
| game_logic(player)
|
||||||
|
|}
|
||||||
|
|""".stripMargin
|
||||||
|
|
||||||
|
EmuCrossPlatformBenchmarkRun(Cpu.Mos)(src) { m =>
|
||||||
|
m.readByte(0xc000) should equal(15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user