mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
included libs are now carried over to asm properly
This commit is contained in:
parent
529c525081
commit
1e0ce40d1d
@ -1,26 +1,42 @@
|
||||
%import c64utils
|
||||
|
||||
~ main $c800 {
|
||||
~ block2 $4000 {
|
||||
return
|
||||
}
|
||||
|
||||
~ block3 $3000 {
|
||||
return
|
||||
}
|
||||
|
||||
~ blockNoAddr1 {
|
||||
return
|
||||
}
|
||||
|
||||
~ blockNoAddr2 {
|
||||
return
|
||||
}
|
||||
|
||||
~ block4 $6000 {
|
||||
return
|
||||
}
|
||||
|
||||
~ blockNoAddr3 {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
|
||||
const ubyte screen_color = 9
|
||||
const ubyte border_color = 2
|
||||
const ubyte cursor_color = 7
|
||||
memory ubyte screen = $d021
|
||||
memory ubyte border = $d020
|
||||
memory ubyte cursor = 646
|
||||
|
||||
screen = screen_color
|
||||
border = border_color
|
||||
cursor = cursor_color
|
||||
c64.BGCOL0 = screen_color
|
||||
c64.EXTCOL = border_color
|
||||
c64.COLOR = cursor_color
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~ block2 $c000 {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,8 @@ import prog8.compiler.HeapValues
|
||||
|
||||
class StatementReorderer(private val namespace: INameScope, private val heap: HeapValues): IAstProcessor {
|
||||
// Reorders the statements in a way the compiler needs.
|
||||
// - 'main' block must be the very first statement.
|
||||
// - 'main' block must be the very first statement UNLESS it has an address set.
|
||||
// - blocks are ordered by address, where blocks without address are put at the end.
|
||||
// - in every scope:
|
||||
// -- the directives '%output', '%launcher', '%zeropage', '%zpreserved', '%address' and '%option' will come first.
|
||||
// -- all vardecls then follow.
|
||||
@ -18,9 +19,15 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
|
||||
|
||||
override fun process(module: Module) {
|
||||
super.process(module)
|
||||
|
||||
val (blocks, other) = module.statements.partition { it is Block }
|
||||
module.statements = other.plus(blocks.sortedBy { (it as Block).address ?: Int.MAX_VALUE }).toMutableList()
|
||||
|
||||
val mainBlock = module.statements.single { it is Block && it.name=="main" }
|
||||
module.statements.remove(mainBlock)
|
||||
module.statements.add(0, mainBlock)
|
||||
if((mainBlock as Block).address==null) {
|
||||
module.statements.remove(mainBlock)
|
||||
module.statements.add(0, mainBlock)
|
||||
}
|
||||
val varDecls = module.statements.filter { it is VarDecl }
|
||||
module.statements.removeAll(varDecls)
|
||||
module.statements.addAll(0, varDecls)
|
||||
|
@ -187,7 +187,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
|
||||
private fun processVariables(scope: INameScope) {
|
||||
for(variable in scope.statements.asSequence().filter {it is VarDecl && it.type==VarDeclType.VAR}.map { it as VarDecl })
|
||||
for(variable in scope.statements.asSequence().filter {it is VarDecl }.map { it as VarDecl })
|
||||
prog.variable(variable.scopedname, variable)
|
||||
for(subscope in scope.subScopes())
|
||||
processVariables(subscope.value)
|
||||
@ -199,8 +199,13 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
prog.line(subroutine.position)
|
||||
// note: the caller has already written the arguments into the subroutine's parameter variables.
|
||||
translate(subroutine.statements)
|
||||
} else if(subroutine.isNotEmpty())
|
||||
throw CompilerException("kernel subroutines (with memory address) can't have a body: $subroutine")
|
||||
} else {
|
||||
// asmsub
|
||||
if(subroutine.isNotEmpty())
|
||||
throw CompilerException("kernel subroutines (with memory address) can't have a body: $subroutine")
|
||||
|
||||
prog.symbolDef(subroutine.scopedname, subroutine.asmAddress)
|
||||
}
|
||||
return super.process(subroutine)
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
var address: Int?,
|
||||
val instructions: MutableList<Instruction> = mutableListOf(),
|
||||
val variables: MutableMap<String, Value> = mutableMapOf(),
|
||||
val integerConstants: MutableMap<String, Int> = mutableMapOf(),
|
||||
val labels: MutableMap<String, Instruction> = mutableMapOf())
|
||||
{
|
||||
val numVariables: Int
|
||||
@ -245,25 +246,31 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
}
|
||||
|
||||
fun variable(scopedname: String, decl: VarDecl) {
|
||||
if(decl.type!=VarDeclType.VAR)
|
||||
return // const and memory variables don't require storage
|
||||
val value = when(decl.datatype) {
|
||||
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> Value(decl.datatype, (decl.value as LiteralValue).asNumericValue!!)
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
|
||||
val litval = (decl.value as LiteralValue)
|
||||
if(litval.heapId==null)
|
||||
throw CompilerException("string should already be in the heap")
|
||||
Value(decl.datatype, litval.heapId)
|
||||
when(decl.type) {
|
||||
VarDeclType.VAR -> {
|
||||
val value = when(decl.datatype) {
|
||||
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> Value(decl.datatype, (decl.value as LiteralValue).asNumericValue!!)
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
|
||||
val litval = (decl.value as LiteralValue)
|
||||
if(litval.heapId==null)
|
||||
throw CompilerException("string should already be in the heap")
|
||||
Value(decl.datatype, litval.heapId)
|
||||
}
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F -> {
|
||||
val litval = (decl.value as LiteralValue)
|
||||
if(litval.heapId==null)
|
||||
throw CompilerException("array/matrix should already be in the heap")
|
||||
Value(decl.datatype, litval.heapId)
|
||||
}
|
||||
}
|
||||
currentBlock.variables[scopedname] = value
|
||||
}
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F -> {
|
||||
val litval = (decl.value as LiteralValue)
|
||||
if(litval.heapId==null)
|
||||
throw CompilerException("array/matrix should already be in the heap")
|
||||
Value(decl.datatype, litval.heapId)
|
||||
VarDeclType.CONST -> {} // constants are all folded away
|
||||
VarDeclType.MEMORY -> {
|
||||
currentBlock.integerConstants[scopedname] = (decl.value as LiteralValue).asIntegerValue!!
|
||||
}
|
||||
}
|
||||
currentBlock.variables[scopedname] = value
|
||||
}
|
||||
|
||||
fun instr(opcode: Opcode, arg: Value? = null, callLabel: String? = null) {
|
||||
@ -280,6 +287,10 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
currentBlock.instructions.add(Instruction(Opcode.LINE, callLabel = "${position.line} ${position.file}"))
|
||||
}
|
||||
|
||||
fun symbolDef(name: String, value: Int) {
|
||||
currentBlock.integerConstants[name] = value
|
||||
}
|
||||
|
||||
fun newBlock(scopedname: String, shortname: String, address: Int?) {
|
||||
currentBlock = ProgramBlock(scopedname, shortname, address)
|
||||
blocks.add(currentBlock)
|
||||
|
@ -28,12 +28,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
if(it.callLabel!=null) symname(it.callLabel, block) else null,
|
||||
if(it.callLabel2!=null) symname(it.callLabel2, block) else null)
|
||||
}.toMutableList()
|
||||
val newConstants = block.integerConstants.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
|
||||
newblocks.add(IntermediateProgram.ProgramBlock(
|
||||
block.scopedname,
|
||||
block.shortname,
|
||||
block.address,
|
||||
newinstructions,
|
||||
newvars,
|
||||
newConstants,
|
||||
newlabels))
|
||||
}
|
||||
program.blocks.clear()
|
||||
@ -58,7 +60,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
output = File("${program.name}.asm").printWriter()
|
||||
output.use {
|
||||
header()
|
||||
for(block in program.blocks) // todo sort by address (if specified) (blocks w/o address go LAST)
|
||||
for(block in program.blocks)
|
||||
block2asm(block)
|
||||
}
|
||||
|
||||
@ -140,6 +142,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
out("* = ${block.address?.toHex()}")
|
||||
}
|
||||
out("${block.shortname}\t.proc\n")
|
||||
out("\n; constants/memdefs/kernel subroutines")
|
||||
memdefs2asm(block)
|
||||
out("\n; variables")
|
||||
vardecls2asm(block)
|
||||
out("")
|
||||
@ -154,6 +158,12 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
out("\n\t.pend\n")
|
||||
}
|
||||
|
||||
private fun memdefs2asm(block: IntermediateProgram.ProgramBlock) {
|
||||
for(m in block.integerConstants) {
|
||||
out("\t${m.key} = ${m.value.toHex()}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun vardecls2asm(block: IntermediateProgram.ProgramBlock) {
|
||||
val sortedVars = block.variables.toList().sortedBy { it.second.type }
|
||||
for (v in sortedVars) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user