added experimental -noreinit option

This commit is contained in:
Irmen de Jong 2022-01-01 16:35:36 +01:00
parent 9e90dbdde6
commit a23281afab
13 changed files with 228 additions and 110 deletions

View File

@ -67,7 +67,6 @@ class AsmGen(private val program: Program,
throw AssemblyError("first block should be 'main'") throw AssemblyError("first block should be 'main'")
for(b in program.allBlocks) { for(b in program.allBlocks) {
b.statements.removeAll(blockVariableInitializers.getValue(b)) // no longer output the initialization assignments as regular statements in the block!
block2asm(b) block2asm(b)
} }
@ -216,10 +215,30 @@ class AsmGen(private val program: Program,
out("${block.name}\t" + (if("force_output" in block.options()) ".block\n" else ".proc\n")) out("${block.name}\t" + (if("force_output" in block.options()) ".block\n" else ".proc\n"))
if(options.dontReinitGlobals) {
block.statements.filterIsInstance<VarDecl>().forEach {
it.zeropage = ZeropageWish.NOT_IN_ZEROPAGE
val init = it.nextSibling() as? Assignment
if(init?.target?.identifier?.targetVarDecl(program) === it) {
// put the init value back into the vardecl
it.value = init.value
}
}
}
// no longer output the initialization assignments as regular statements in the block!
block.statements.removeAll(blockVariableInitializers.getValue(block))
outputSourceLine(block) outputSourceLine(block)
zeropagevars2asm(block.statements, block) zeropagevars2asm(block.statements, block)
memdefs2asm(block.statements, block) memdefs2asm(block.statements, block)
vardecls2asm(block.statements, block) vardecls2asm(block.statements, block)
block.statements.filterIsInstance<VarDecl>().forEach {
if(it.type==VarDeclType.VAR && it.datatype in NumericDatatypes)
it.value=null
}
out("\n; subroutines in this block") out("\n; subroutines in this block")
// first translate regular statements, and then put the subroutines at the end. // first translate regular statements, and then put the subroutines at the end.
@ -227,12 +246,14 @@ class AsmGen(private val program: Program,
stmts.forEach { translate(it) } stmts.forEach { translate(it) }
subroutine.forEach { translateSubroutine(it as Subroutine) } subroutine.forEach { translateSubroutine(it as Subroutine) }
// generate subroutine to initialize block-level variables if(!options.dontReinitGlobals) {
val initializers = blockVariableInitializers.getValue(block) // generate subroutine to initialize block-level (global) variables
if(initializers.isNotEmpty()) { val initializers = blockVariableInitializers.getValue(block)
out("prog8_init_vars\t.proc\n") if (initializers.isNotEmpty()) {
initializers.forEach { assign -> translate(assign) } out("prog8_init_vars\t.proc\n")
out(" rts\n .pend") initializers.forEach { assign -> translate(assign) }
out(" rts\n .pend")
}
} }
out(if("force_output" in block.options()) "\n\t.bend\n" else "\n\t.pend\n") out(if("force_output" in block.options()) "\n\t.bend\n" else "\n\t.pend\n")
@ -291,12 +312,34 @@ class AsmGen(private val program: Program,
private fun vardecl2asm(decl: VarDecl) { private fun vardecl2asm(decl: VarDecl) {
val name = decl.name val name = decl.name
val value = decl.value
val staticValue: Number =
if(value!=null) {
if(value is NumericLiteralValue) {
if(value.type==DataType.FLOAT)
value.number
else
value.number.toInt()
} else {
if(decl.datatype in NumericDatatypes)
throw AssemblyError("can only deal with constant numeric values for global vars $value at ${decl.position}")
else 0
}
} else 0
when (decl.datatype) { when (decl.datatype) {
DataType.UBYTE -> out("$name\t.byte 0") DataType.UBYTE -> out("$name\t.byte ${staticValue.toHex()}")
DataType.BYTE -> out("$name\t.char 0") DataType.BYTE -> out("$name\t.char $staticValue")
DataType.UWORD -> out("$name\t.word 0") DataType.UWORD -> out("$name\t.word ${staticValue.toHex()}")
DataType.WORD -> out("$name\t.sint 0") DataType.WORD -> out("$name\t.sint $staticValue")
DataType.FLOAT -> out("$name\t.byte 0,0,0,0,0 ; float") DataType.FLOAT -> {
if(staticValue==0) {
out("$name\t.byte 0,0,0,0,0 ; float")
} else {
val floatFill = compTarget.machine.getFloat(staticValue).makeFloatFillAsm()
out("$name\t.byte $floatFill ; float $staticValue")
}
}
DataType.STR -> { DataType.STR -> {
val str = decl.value as StringLiteralValue val str = decl.value as StringLiteralValue
outputStringvar(decl, compTarget.encodeString(str.value, str.altEncoding).plus(0.toUByte())) outputStringvar(decl, compTarget.encodeString(str.value, str.altEncoding).plus(0.toUByte()))
@ -1001,9 +1044,11 @@ class AsmGen(private val program: Program,
if(sub.name=="start" && sub.definingBlock.name=="main") { if(sub.name=="start" && sub.definingBlock.name=="main") {
out("; program startup initialization") out("; program startup initialization")
out(" cld") out(" cld")
blockVariableInitializers.forEach { if(!options.dontReinitGlobals) {
if(it.value.isNotEmpty()) blockVariableInitializers.forEach {
out(" jsr ${it.key.name}.prog8_init_vars") if (it.value.isNotEmpty())
out(" jsr ${it.key.name}.prog8_init_vars")
}
} }
out(""" out("""
tsx tsx

View File

@ -37,6 +37,7 @@ private fun compileMain(args: Array<String>): Boolean {
val outputDir by cli.option(ArgType.String, fullName = "out", description = "directory for output files instead of current directory").default(".") val outputDir by cli.option(ArgType.String, fullName = "out", description = "directory for output files instead of current directory").default(".")
val dontWriteAssembly by cli.option(ArgType.Boolean, fullName = "noasm", description="don't create assembly code") val dontWriteAssembly by cli.option(ArgType.Boolean, fullName = "noasm", description="don't create assembly code")
val dontOptimize by cli.option(ArgType.Boolean, fullName = "noopt", description = "don't perform any optimizations") val dontOptimize by cli.option(ArgType.Boolean, fullName = "noopt", description = "don't perform any optimizations")
val dontReinitGlobals by cli.option(ArgType.Boolean, fullName = "noreinit", description = "don't create code to reinitialize globals on multiple runs of the program (experimental!)")
val optimizeFloatExpressions by cli.option(ArgType.Boolean, fullName = "optfloatx", description = "optimize float expressions (warning: can increase program size)") val optimizeFloatExpressions by cli.option(ArgType.Boolean, fullName = "optfloatx", description = "optimize float expressions (warning: can increase program size)")
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watches for file changes), greatly increases compilation speed") val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watches for file changes), greatly increases compilation speed")
val slowCodegenWarnings by cli.option(ArgType.Boolean, fullName = "slowwarn", description="show debug warnings about slow/problematic assembly code generation") val slowCodegenWarnings by cli.option(ArgType.Boolean, fullName = "slowwarn", description="show debug warnings about slow/problematic assembly code generation")
@ -87,6 +88,7 @@ private fun compileMain(args: Array<String>): Boolean {
filepath, filepath,
dontOptimize != true, dontOptimize != true,
optimizeFloatExpressions == true, optimizeFloatExpressions == true,
dontReinitGlobals == true,
dontWriteAssembly != true, dontWriteAssembly != true,
slowCodegenWarnings == true, slowCodegenWarnings == true,
quietAssembler == true, quietAssembler == true,
@ -136,6 +138,7 @@ private fun compileMain(args: Array<String>): Boolean {
filepath, filepath,
dontOptimize != true, dontOptimize != true,
optimizeFloatExpressions == true, optimizeFloatExpressions == true,
dontReinitGlobals == true,
dontWriteAssembly != true, dontWriteAssembly != true,
slowCodegenWarnings == true, slowCodegenWarnings == true,
quietAssembler == true, quietAssembler == true,

View File

@ -32,6 +32,7 @@ class CompilationResult(val success: Boolean,
class CompilerArguments(val filepath: Path, class CompilerArguments(val filepath: Path,
val optimize: Boolean, val optimize: Boolean,
val optimizeFloatExpressions: Boolean, val optimizeFloatExpressions: Boolean,
val dontReinitGlobals: Boolean,
val writeAssembly: Boolean, val writeAssembly: Boolean,
val slowCodegenWarnings: Boolean, val slowCodegenWarnings: Boolean,
val quietAssembler: Boolean, val quietAssembler: Boolean,
@ -65,6 +66,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult {
slowCodegenWarnings = args.slowCodegenWarnings slowCodegenWarnings = args.slowCodegenWarnings
optimize = args.optimize optimize = args.optimize
optimizeFloatExpressions = optimizeFloatExpr optimizeFloatExpressions = optimizeFloatExpr
dontReinitGlobals = args.dontReinitGlobals
asmQuiet = args.quietAssembler asmQuiet = args.quietAssembler
asmListfile = args.asmListfile asmListfile = args.asmListfile
} }

View File

@ -27,6 +27,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
filepath, filepath,
optimize, optimize,
optimizeFloatExpressions = true, optimizeFloatExpressions = true,
dontReinitGlobals = false,
writeAssembly = true, writeAssembly = true,
slowCodegenWarnings = false, slowCodegenWarnings = false,
quietAssembler = true, quietAssembler = true,

View File

@ -41,6 +41,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
filepath = filePath, filepath = filePath,
optimize = false, optimize = false,
optimizeFloatExpressions = false, optimizeFloatExpressions = false,
dontReinitGlobals = false,
writeAssembly = true, writeAssembly = true,
slowCodegenWarnings = false, slowCodegenWarnings = false,
quietAssembler = true, quietAssembler = true,

View File

@ -48,6 +48,7 @@ internal fun compileFile(
filepath, filepath,
optimize, optimize,
optimizeFloatExpressions = optFloatExpr, optimizeFloatExpressions = optFloatExpr,
dontReinitGlobals = false,
writeAssembly = writeAssembly, writeAssembly = writeAssembly,
slowCodegenWarnings = false, slowCodegenWarnings = false,
quietAssembler = true, quietAssembler = true,

View File

@ -173,7 +173,7 @@ enum class ZeropageWish {
class VarDecl(val type: VarDeclType, class VarDecl(val type: VarDeclType,
private val declaredDatatype: DataType, private val declaredDatatype: DataType,
val zeropage: ZeropageWish, var zeropage: ZeropageWish,
var arraysize: ArrayIndex?, var arraysize: ArrayIndex?,
override val name: String, override val name: String,
var value: Expression?, var value: Expression?,

View File

@ -29,6 +29,7 @@ class CompilationOptions(val output: OutputType,
var slowCodegenWarnings: Boolean = false, var slowCodegenWarnings: Boolean = false,
var optimize: Boolean = false, var optimize: Boolean = false,
var optimizeFloatExpressions: Boolean = false, var optimizeFloatExpressions: Boolean = false,
var dontReinitGlobals: Boolean = false,
var asmQuiet: Boolean = false, var asmQuiet: Boolean = false,
var asmListfile: Boolean = false var asmListfile: Boolean = false
) )

View File

@ -124,6 +124,13 @@ One or more .p8 module files
Don't perform any code optimizations. Don't perform any code optimizations.
Useful for debugging or faster compilation cycles. Useful for debugging or faster compilation cycles.
``-noreinit``
Don't create code to reinitialize the global (block level) variables on every run of the program.
Also means that all such variables are no longer placed in the zero page.
Sometimes the program will be a lot shorter when using this, but sometimes the opposite happens.
When using this option, it is no longer be possible to run the program correctly more than once!
*Experimental feature*: still has some problems!
``-optfloatx`` ``-optfloatx``
Also optimize float expressions if optimizations are enabled. Also optimize float expressions if optimizations are enabled.
Warning: can increase program size significantly if a lot of floating point expressions are used. Warning: can increase program size significantly if a lot of floating point expressions are used.

View File

@ -31,7 +31,6 @@ Future
- use more of Result<> and Either<> to handle errors/ nulls better - use more of Result<> and Either<> to handle errors/ nulls better
- rethink the whole "isAugmentable" business. Because the way this is determined, should always also be exactly mirrorred in the AugmentableAssignmentAsmGen or you'll get a crash at code gen time. - rethink the whole "isAugmentable" business. Because the way this is determined, should always also be exactly mirrorred in the AugmentableAssignmentAsmGen or you'll get a crash at code gen time.
- can we get rid of pieces of asmgen.AssignmentAsmGen by just reusing the AugmentableAssignment ? generated code should not suffer - can we get rid of pieces of asmgen.AssignmentAsmGen by just reusing the AugmentableAssignment ? generated code should not suffer
- add a switch to not create the globals-initialization logic, but instead create a smaller program (that can only run once though)
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking) - c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
- optimize several inner loops in gfx2 even further? - optimize several inner loops in gfx2 even further?
- add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)? - add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)?

104
examples/c128/fpval.p8 Normal file
View File

@ -0,0 +1,104 @@
%import textio
%import floats
main {
sub start() {
test_val()
repeat {
}
}
sub test_val() {
; TODO c128 how do I set this in "bank 1" ? VAL() needs that...
str @shared value = "-1.23456"
uword @shared result
%asm {{
stx P8ZP_SCRATCH_B1
lda #<value
sta $24
lda #>value
sta $25
lda #8
jsr floats.VAL
jsr floats.FOUT
sta result
sty result+1
ldx P8ZP_SCRATCH_B1
}}
txt.print_uwhex(result, true)
txt.nl()
txt.print(result)
txt.nl()
txt.print($0100)
txt.nl()
}
sub test_freadsa() {
uword @shared result
%asm {{
stx P8ZP_SCRATCH_B1
;lda #-123
;jsr floats.FREADSA
lda #<55444
ldy #>55444
jsr floats.GIVUAYFAY
jsr floats.FOUT
sta result
sty result+1
ldx P8ZP_SCRATCH_B1
}}
txt.print_uwhex(result, true)
txt.nl()
txt.print(result)
txt.nl()
txt.print($0100)
txt.nl()
}
sub test_getadr() {
uword @shared value
%asm {{
stx P8ZP_SCRATCH_B1
lda #<23456
ldy #>23456
jsr floats.GIVAYFAY
jsr floats.GETADRAY
sta value
sty value+1
ldx P8ZP_SCRATCH_B1
}}
txt.print_uw(value)
txt.nl()
}
sub test_ayint() {
%asm {{
stx P8ZP_SCRATCH_B1
lda #<-23456
ldy #>-23456
jsr floats.GIVAYFAY
jsr floats.AYINT
ldx P8ZP_SCRATCH_B1
}}
word value = mkword(@($66), @($67)) as word
txt.print_w(value)
txt.nl()
}
sub test_printf() {
floats.print_f(0)
txt.nl()
floats.print_f(1)
txt.nl()
floats.print_f(-1)
txt.nl()
floats.print_f(floats.PI)
txt.nl()
floats.print_f(floats.TWOPI)
txt.nl()
}
}

View File

@ -1,104 +1,57 @@
%import textio %import textio
%import floats %import floats
%zeropage basicsafe
%option no_sysinit
main { main {
ubyte bb = 1
uword ww = 1
float ff = 1.111
str derp = "zzzz"
sub start() { sub start() {
func()
test_val() txt.print(derp)
repeat {
}
} }
sub test_val() { sub func() {
ubyte fbb = 1
uword fww = 1
float fff = 1.111
; TODO c128 how do I set this in "bank 1" ? VAL() needs that... txt.print_ub(fbb)
txt.spc()
txt.print_uw(fww)
txt.spc()
floats.print_f(fff)
txt.nl()
txt.print_ub(bb)
txt.spc()
txt.print_uw(ww)
txt.spc()
floats.print_f(ff)
txt.nl()
txt.print_ub(block2.bb)
txt.spc()
txt.print_uw(block2.ww)
txt.spc()
floats.print_f(block2.ff)
txt.nl()
str @shared value = "-1.23456" fbb++
uword @shared result fww++
%asm {{ fff += 1.1
stx P8ZP_SCRATCH_B1 bb++
lda #<value ww++
sta $24 ff += 1.1
lda #>value block2.bb++
sta $25 block2.ww++
lda #8 block2.ff += 1.1
jsr floats.VAL
jsr floats.FOUT
sta result
sty result+1
ldx P8ZP_SCRATCH_B1
}}
txt.print_uwhex(result, true)
txt.nl()
txt.print(result)
txt.nl()
txt.print($0100)
txt.nl()
}
sub test_freadsa() {
uword @shared result
%asm {{
stx P8ZP_SCRATCH_B1
;lda #-123
;jsr floats.FREADSA
lda #<55444
ldy #>55444
jsr floats.GIVUAYFAY
jsr floats.FOUT
sta result
sty result+1
ldx P8ZP_SCRATCH_B1
}}
txt.print_uwhex(result, true)
txt.nl()
txt.print(result)
txt.nl()
txt.print($0100)
txt.nl()
}
sub test_getadr() {
uword @shared value
%asm {{
stx P8ZP_SCRATCH_B1
lda #<23456
ldy #>23456
jsr floats.GIVAYFAY
jsr floats.GETADRAY
sta value
sty value+1
ldx P8ZP_SCRATCH_B1
}}
txt.print_uw(value)
txt.nl()
}
sub test_ayint() {
%asm {{
stx P8ZP_SCRATCH_B1
lda #<-23456
ldy #>-23456
jsr floats.GIVAYFAY
jsr floats.AYINT
ldx P8ZP_SCRATCH_B1
}}
word value = mkword(@($66), @($67)) as word
txt.print_w(value)
txt.nl()
}
sub test_printf() {
floats.print_f(0)
txt.nl()
floats.print_f(1)
txt.nl()
floats.print_f(-1)
txt.nl()
floats.print_f(floats.PI)
txt.nl()
floats.print_f(floats.TWOPI)
txt.nl()
} }
} }
block2 {
ubyte bb = 1
uword ww = 1
float ff = 1.111
}

View File

@ -34,6 +34,7 @@ class RequestParser : Take {
Path.of(a), Path.of(a),
optimize = true, optimize = true,
optimizeFloatExpressions = false, optimizeFloatExpressions = false,
dontReinitGlobals = false,
writeAssembly = true, writeAssembly = true,
slowCodegenWarnings = true, slowCodegenWarnings = true,
compilationTarget = "c64", compilationTarget = "c64",