mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
added experimental -noreinit option
This commit is contained in:
parent
9e90dbdde6
commit
a23281afab
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -41,6 +41,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
||||
filepath = filePath,
|
||||
optimize = false,
|
||||
optimizeFloatExpressions = false,
|
||||
dontReinitGlobals = false,
|
||||
writeAssembly = true,
|
||||
slowCodegenWarnings = false,
|
||||
quietAssembler = true,
|
||||
|
@ -48,6 +48,7 @@ internal fun compileFile(
|
||||
filepath,
|
||||
optimize,
|
||||
optimizeFloatExpressions = optFloatExpr,
|
||||
dontReinitGlobals = false,
|
||||
writeAssembly = writeAssembly,
|
||||
slowCodegenWarnings = false,
|
||||
quietAssembler = true,
|
||||
|
@ -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?,
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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.
|
||||
|
@ -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
104
examples/c128/fpval.p8
Normal 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()
|
||||
}
|
||||
}
|
139
examples/test.p8
139
examples/test.p8
@ -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
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ class RequestParser : Take {
|
||||
Path.of(a),
|
||||
optimize = true,
|
||||
optimizeFloatExpressions = false,
|
||||
dontReinitGlobals = false,
|
||||
writeAssembly = true,
|
||||
slowCodegenWarnings = true,
|
||||
compilationTarget = "c64",
|
||||
|
Loading…
x
Reference in New Issue
Block a user