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'")
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)
}
@ -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"))
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)
zeropagevars2asm(block.statements, block)
memdefs2asm(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")
// 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) }
subroutine.forEach { translateSubroutine(it as Subroutine) }
// generate subroutine to initialize block-level variables
val initializers = blockVariableInitializers.getValue(block)
if(initializers.isNotEmpty()) {
out("prog8_init_vars\t.proc\n")
initializers.forEach { assign -> translate(assign) }
out(" rts\n .pend")
if(!options.dontReinitGlobals) {
// generate subroutine to initialize block-level (global) variables
val initializers = blockVariableInitializers.getValue(block)
if (initializers.isNotEmpty()) {
out("prog8_init_vars\t.proc\n")
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")
@ -291,12 +312,34 @@ class AsmGen(private val program: Program,
private fun vardecl2asm(decl: VarDecl) {
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) {
DataType.UBYTE -> out("$name\t.byte 0")
DataType.BYTE -> out("$name\t.char 0")
DataType.UWORD -> out("$name\t.word 0")
DataType.WORD -> out("$name\t.sint 0")
DataType.FLOAT -> out("$name\t.byte 0,0,0,0,0 ; float")
DataType.UBYTE -> out("$name\t.byte ${staticValue.toHex()}")
DataType.BYTE -> out("$name\t.char $staticValue")
DataType.UWORD -> out("$name\t.word ${staticValue.toHex()}")
DataType.WORD -> out("$name\t.sint $staticValue")
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 -> {
val str = decl.value as StringLiteralValue
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") {
out("; program startup initialization")
out(" cld")
blockVariableInitializers.forEach {
if(it.value.isNotEmpty())
out(" jsr ${it.key.name}.prog8_init_vars")
if(!options.dontReinitGlobals) {
blockVariableInitializers.forEach {
if (it.value.isNotEmpty())
out(" jsr ${it.key.name}.prog8_init_vars")
}
}
out("""
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 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 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 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")
@ -87,6 +88,7 @@ private fun compileMain(args: Array<String>): Boolean {
filepath,
dontOptimize != true,
optimizeFloatExpressions == true,
dontReinitGlobals == true,
dontWriteAssembly != true,
slowCodegenWarnings == true,
quietAssembler == true,
@ -136,6 +138,7 @@ private fun compileMain(args: Array<String>): Boolean {
filepath,
dontOptimize != true,
optimizeFloatExpressions == true,
dontReinitGlobals == true,
dontWriteAssembly != true,
slowCodegenWarnings == true,
quietAssembler == true,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -124,6 +124,13 @@ One or more .p8 module files
Don't perform any code optimizations.
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``
Also optimize float expressions if optimizations are enabled.
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
- 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
- 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)
- optimize several inner loops in gfx2 even further?
- 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 floats
%zeropage basicsafe
%option no_sysinit
main {
ubyte bb = 1
uword ww = 1
float ff = 1.111
str derp = "zzzz"
sub start() {
test_val()
repeat {
}
func()
txt.print(derp)
}
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"
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()
fbb++
fww++
fff += 1.1
bb++
ww++
ff += 1.1
block2.bb++
block2.ww++
block2.ff += 1.1
}
}
block2 {
ubyte bb = 1
uword ww = 1
float ff = 1.111
}

View File

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