mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 23:30:22 +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) {
|
||||
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 p = get[Type]("pointer")
|
||||
val params = nf.fold(List[String]()) { f =>
|
||||
@ -146,6 +150,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
} else 3
|
||||
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 =>
|
||||
if (log.traceEnabled) log.trace("Allocating " + m.name)
|
||||
val vertex = if (options.flag(CompilationFlag.VariableOverlap)) {
|
||||
nf.fold[VariableVertex](GlobalVertex) { f =>
|
||||
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)) {
|
||||
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)) {
|
||||
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