mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
fix rts in empty asmsub
This commit is contained in:
parent
77de99b383
commit
8ae3bad6f7
@ -279,7 +279,7 @@ class AsmGen6502(internal val program: Program,
|
||||
|
||||
statements.asSequence().filterIsInstance<VarDecl>().forEach {
|
||||
if(it.type==VarDeclType.VAR && it.datatype in NumericDatatypes)
|
||||
it.value=null // TODO why is this done?
|
||||
it.value=null // make sure every var has no init value anymore (could be set due to 'noreinit' option) because initialization is done via explicit assignment
|
||||
}
|
||||
|
||||
out("\n; subroutines in this block")
|
||||
|
@ -96,8 +96,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
// NOTE: *if* there is a return statement, it will be the only one, and the very last statement of the subroutine
|
||||
// (this condition has been enforced by an ast check earlier)
|
||||
asmgen.out(" \t; inlined routine follows: ${sub.name}")
|
||||
val assembly = sub.statements.single() as InlineAssembly
|
||||
asmgen.translate(assembly)
|
||||
sub.statements.forEach { asmgen.translate(it as InlineAssembly) }
|
||||
asmgen.out(" \t; inlined routine end: ${sub.name}")
|
||||
} else {
|
||||
asmgen.out(" jsr $subAsmName")
|
||||
|
@ -20,33 +20,34 @@ class CX16Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
||||
// the addresses 0x02 to 0x21 (inclusive) are taken for sixteen virtual 16-bit api registers.
|
||||
|
||||
when (options.zeropage) {
|
||||
ZeropageType.FULL -> {
|
||||
free.addAll(0x22u..0xffu)
|
||||
synchronized(this) {
|
||||
when (options.zeropage) {
|
||||
ZeropageType.FULL -> {
|
||||
free.addAll(0x22u..0xffu)
|
||||
}
|
||||
ZeropageType.KERNALSAFE -> {
|
||||
free.addAll(0x22u..0x7fu)
|
||||
free.addAll(0xa9u..0xffu)
|
||||
}
|
||||
ZeropageType.BASICSAFE -> {
|
||||
free.addAll(0x22u..0x7fu)
|
||||
}
|
||||
ZeropageType.DONTUSE -> {
|
||||
free.clear() // don't use zeropage at all
|
||||
}
|
||||
else -> throw InternalCompilerException("for this machine target, zero page type 'floatsafe' is not available. ${options.zeropage}")
|
||||
}
|
||||
ZeropageType.KERNALSAFE -> {
|
||||
free.addAll(0x22u..0x7fu)
|
||||
free.addAll(0xa9u..0xffu)
|
||||
|
||||
removeReservedFromFreePool()
|
||||
|
||||
for(reg in 0..15) {
|
||||
allocatedVariables[listOf("cx16", "r${reg}")] = (2+reg*2).toUInt() to (DataType.UWORD to 2) // cx16.r0 .. cx16.r15
|
||||
allocatedVariables[listOf("cx16", "r${reg}s")] = (2+reg*2).toUInt() to (DataType.WORD to 2) // cx16.r0s .. cx16.r15s
|
||||
allocatedVariables[listOf("cx16", "r${reg}L")] = (2+reg*2).toUInt() to (DataType.UBYTE to 1) // cx16.r0L .. cx16.r15L
|
||||
allocatedVariables[listOf("cx16", "r${reg}H")] = (3+reg*2).toUInt() to (DataType.UBYTE to 1) // cx16.r0H .. cx16.r15H
|
||||
allocatedVariables[listOf("cx16", "r${reg}sL")] = (2+reg*2).toUInt() to (DataType.BYTE to 1) // cx16.r0sL .. cx16.r15sL
|
||||
allocatedVariables[listOf("cx16", "r${reg}sH")] = (3+reg*2).toUInt() to (DataType.BYTE to 1) // cx16.r0sH .. cx16.r15sH
|
||||
}
|
||||
ZeropageType.BASICSAFE -> {
|
||||
free.addAll(0x22u..0x7fu)
|
||||
}
|
||||
ZeropageType.DONTUSE -> {
|
||||
free.clear() // don't use zeropage at all
|
||||
}
|
||||
else -> throw InternalCompilerException("for this machine target, zero page type 'floatsafe' is not available. ${options.zeropage}")
|
||||
}
|
||||
|
||||
removeReservedFromFreePool()
|
||||
|
||||
for(reg in 0..15) {
|
||||
allocatedVariables[listOf("cx16", "r${reg}")] = (2+reg*2).toUInt() to (DataType.UWORD to 2) // cx16.r0 .. cx16.r15
|
||||
allocatedVariables[listOf("cx16", "r${reg}s")] = (2+reg*2).toUInt() to (DataType.WORD to 2) // cx16.r0s .. cx16.r15s
|
||||
allocatedVariables[listOf("cx16", "r${reg}L")] = (2+reg*2).toUInt() to (DataType.UBYTE to 1) // cx16.r0L .. cx16.r15L
|
||||
allocatedVariables[listOf("cx16", "r${reg}H")] = (3+reg*2).toUInt() to (DataType.UBYTE to 1) // cx16.r0H .. cx16.r15H
|
||||
allocatedVariables[listOf("cx16", "r${reg}sL")] = (2+reg*2).toUInt() to (DataType.BYTE to 1) // cx16.r0sL .. cx16.r15sL
|
||||
allocatedVariables[listOf("cx16", "r${reg}sH")] = (3+reg*2).toUInt() to (DataType.BYTE to 1) // cx16.r0sH .. cx16.r15sH
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -146,12 +146,13 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
||||
|
||||
// add the implicit return statement at the end (if it's not there yet), but only if it's not a kernal routine.
|
||||
// and if an assembly block doesn't contain a rts/rti, and some other situations.
|
||||
val returnStmt = Return(null, subroutine.position)
|
||||
if (!subroutine.isAsmSubroutine && !subroutine.inline) {
|
||||
if(subroutine.statements.isEmpty() ||
|
||||
(subroutine.amountOfRtsInAsm() == 0
|
||||
&& subroutine.statements.lastOrNull { it !is VarDecl } !is Return
|
||||
&& subroutine.statements.last() !is Subroutine)) {
|
||||
&& subroutine.statements.last() !is Subroutine
|
||||
&& subroutine.statements.last() !is Return)) {
|
||||
val returnStmt = Return(null, subroutine.position)
|
||||
mods += IAstModification.InsertLast(returnStmt, subroutine)
|
||||
}
|
||||
}
|
||||
@ -167,14 +168,17 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
||||
&& prevStmt !is Subroutine
|
||||
&& prevStmt !is Return
|
||||
) {
|
||||
val returnStmt = Return(null, subroutine.position)
|
||||
mods += IAstModification.InsertAfter(outerStatements[subroutineStmtIdx - 1], returnStmt, outerScope)
|
||||
}
|
||||
}
|
||||
|
||||
if (subroutine.inline && subroutine.isAsmSubroutine && subroutine.amountOfRtsInAsm() == 0) {
|
||||
// make sure the NOT INLINED asm subroutine actually has a rts at the end
|
||||
// (non-asm routines get a Return statement as needed, above)
|
||||
mods += IAstModification.InsertLast(InlineAssembly(" rts\n", Position.DUMMY), subroutine)
|
||||
if (!subroutine.inline) {
|
||||
if (subroutine.isAsmSubroutine && subroutine.asmAddress==null && subroutine.amountOfRtsInAsm() == 0) {
|
||||
// make sure the NOT INLINED asm subroutine actually has a rts at the end
|
||||
// (non-asm routines get a Return statement as needed, above)
|
||||
mods += IAstModification.InsertLast(InlineAssembly(" rts\n", Position.DUMMY), subroutine)
|
||||
}
|
||||
}
|
||||
|
||||
return mods
|
||||
|
@ -85,6 +85,7 @@ class TestSubroutines: FunSpec({
|
||||
func("text")
|
||||
func(text)
|
||||
func($2000)
|
||||
emptysub()
|
||||
}
|
||||
|
||||
asmsub asmfunc(str thing @AY) {
|
||||
@ -94,6 +95,9 @@ class TestSubroutines: FunSpec({
|
||||
uword t2 = thing as uword
|
||||
asmfunc(thing)
|
||||
}
|
||||
|
||||
sub emptysub() {
|
||||
}
|
||||
}
|
||||
"""
|
||||
val result = compileText(C64Target, false, text, writeAssembly = true).assertSuccess()
|
||||
@ -101,14 +105,16 @@ class TestSubroutines: FunSpec({
|
||||
val mainBlock = module.statements.single() as Block
|
||||
val asmfunc = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="asmfunc"}
|
||||
val func = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="func"}
|
||||
val emptysub = mainBlock.statements.filterIsInstance<Subroutine>().single { it.name=="emptysub"}
|
||||
asmfunc.isAsmSubroutine shouldBe true
|
||||
asmfunc.statements.single() shouldBe instanceOf<Return>()
|
||||
asmfunc.statements.single() shouldBe instanceOf<InlineAssembly>()
|
||||
(asmfunc.statements.single() as InlineAssembly).assembly.trim() shouldBe "rts"
|
||||
asmfunc.amountOfRtsInAsm() shouldBe 1
|
||||
func.isAsmSubroutine shouldBe false
|
||||
withClue("str param should have been changed to uword") {
|
||||
asmfunc.parameters.single().type shouldBe DataType.UWORD
|
||||
func.parameters.single().type shouldBe DataType.UWORD
|
||||
}
|
||||
asmfunc.statements.last() shouldBe instanceOf<Return>()
|
||||
|
||||
func.statements.size shouldBe 5
|
||||
func.statements[4] shouldBe instanceOf<Return>()
|
||||
@ -129,6 +135,9 @@ class TestSubroutines: FunSpec({
|
||||
call.args.single() shouldBe instanceOf<IdentifierReference>()
|
||||
}
|
||||
(call.args.single() as IdentifierReference).nameInSource.single() shouldBe "thing"
|
||||
|
||||
emptysub.statements.size shouldBe 1
|
||||
emptysub.statements.single() shouldBe instanceOf<Return>()
|
||||
}
|
||||
|
||||
test("ubyte[] array parameters") {
|
||||
|
@ -25,10 +25,12 @@ abstract class Zeropage(protected val options: CompilationOptions) {
|
||||
val free = mutableListOf<UInt>() // subclasses must set this to the appropriate free locations.
|
||||
|
||||
fun removeReservedFromFreePool() {
|
||||
for (reserved in options.zpReserved)
|
||||
reserve(reserved)
|
||||
synchronized(this) {
|
||||
for (reserved in options.zpReserved)
|
||||
reserve(reserved)
|
||||
|
||||
free.removeAll(setOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1u, SCRATCH_W2, SCRATCH_W2 + 1u))
|
||||
free.removeAll(setOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1u, SCRATCH_W2, SCRATCH_W2 + 1u))
|
||||
}
|
||||
}
|
||||
|
||||
fun availableBytes() = if(options.zeropage== ZeropageType.DONTUSE) 0 else free.size
|
||||
|
@ -23,8 +23,8 @@ Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Ast modifications done in AsmGen, that should be done BEFORE calling asmgen (so that it doesn't have to modify the Ast any longer):
|
||||
|
||||
- block2asm: after vardecls2asm it clears the vardecl.value of all variables (why?)
|
||||
- block2asm: removes init-assignments to no longer output the initialization assignments as regular statements (is done separately in block initialization routine)
|
||||
- block2asm: after vardecls2asm it clears the vardecl.value of all variables
|
||||
- Maybe don't rely on vardecls at all any longer but figure out the variable allocations (including ZP allocations) beforehand
|
||||
and pass that via a new datastructure to asmgen? So that asmgen is no longer tasked with doing the allocations.
|
||||
This could perhaps make it easer for the codegen as well to deal with sections, if any, in the future.
|
||||
|
@ -17,7 +17,18 @@ main {
|
||||
txt.nl()
|
||||
txt.print_ub(startval1)
|
||||
txt.nl()
|
||||
derp()
|
||||
derp()
|
||||
foobar()
|
||||
startval1++
|
||||
mainglobal1++
|
||||
}
|
||||
|
||||
asmsub derp() {
|
||||
|
||||
}
|
||||
|
||||
sub foobar() {
|
||||
txt.print("foobar\n")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user