mirror of
https://github.com/irmen/prog8.git
synced 2024-06-26 07:29:32 +00:00
temp vars are now dynamically added to AST as needed
This commit is contained in:
parent
41b1c80492
commit
08bacdd090
|
@ -4,11 +4,11 @@ import prog8.ast.IStatementContainer
|
|||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.AugmentAssignmentOperators
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.TypecastExpression
|
||||
import prog8.ast.getTempVar
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.AssignmentOrigin
|
||||
|
@ -98,14 +98,7 @@ X = BinExpr X = LeftExpr
|
|||
// we can see if we can unwrap the binary expression by working on a new temporary variable
|
||||
// (that has the type of the expression), and then finally doing the typecast.
|
||||
// Once it's outside the typecast, the regular splitting can commence.
|
||||
val tempVar = when(val tempDt = origExpr.inferType(program).getOr(DataType.UNDEFINED)) {
|
||||
DataType.UBYTE -> listOf("prog8_lib", "retval_interm_ub")
|
||||
DataType.BYTE -> listOf("prog8_lib", "retval_interm_b")
|
||||
DataType.UWORD -> listOf("prog8_lib", "retval_interm_uw")
|
||||
DataType.WORD -> listOf("prog8_lib", "retval_interm_w")
|
||||
DataType.FLOAT -> listOf("floats", "tempvar_swap_float")
|
||||
else -> throw FatalAstException("invalid dt $tempDt")
|
||||
}
|
||||
val tempVar = program.getTempVar(origExpr.inferType(program).getOr(DataType.UNDEFINED))
|
||||
val assignTempVar = Assignment(
|
||||
AssignTarget(IdentifierReference(tempVar, typecast.position), null, null, typecast.position),
|
||||
typecast.expression, AssignmentOrigin.OPTIMIZER, typecast.position
|
||||
|
|
|
@ -4,7 +4,12 @@ import prog8.ast.IBuiltinFunctions
|
|||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.base.Position
|
||||
import prog8.ast.base.VarDeclType
|
||||
import prog8.ast.expressions.InferredTypes
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.ast.statements.VarDeclOrigin
|
||||
import prog8.ast.statements.ZeropageWish
|
||||
import prog8.compilerinterface.CompilationOptions
|
||||
import prog8.compilerinterface.ICompilationTarget
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
|
@ -69,7 +74,7 @@ fun Program.splitBinaryExpressions(options: CompilationOptions, compTarget: ICom
|
|||
return opti.applyModifications()
|
||||
}
|
||||
|
||||
fun getTempVarName(dt: InferredTypes.InferredType): List<String> {
|
||||
fun getTempRegisterName(dt: InferredTypes.InferredType): List<String> {
|
||||
return when {
|
||||
// TODO assume (hope) cx16.r9 isn't used for anything else during the use of this temporary variable...
|
||||
dt istype DataType.UBYTE -> listOf("cx16", "r9L")
|
||||
|
|
|
@ -130,7 +130,7 @@ class StatementOptimizer(private val program: Program,
|
|||
if(functionCallStatement.target.nameInSource !in listOf(listOf("pop"), listOf("popw")) && functionCallStatement.args.size==1) {
|
||||
val arg = functionCallStatement.args[0]
|
||||
if(!arg.isSimple && arg !is TypecastExpression && arg !is IFunctionCall) {
|
||||
val name = getTempVarName(arg.inferType(program))
|
||||
val name = getTempRegisterName(arg.inferType(program))
|
||||
val tempvar = IdentifierReference(name, functionCallStatement.position)
|
||||
val assignTempvar = Assignment(AssignTarget(tempvar.copy(), null, null, functionCallStatement.position), arg, AssignmentOrigin.OPTIMIZER, functionCallStatement.position)
|
||||
return listOf(
|
||||
|
@ -474,14 +474,8 @@ class StatementOptimizer(private val program: Program,
|
|||
val returnDt = subr.returntypes.single()
|
||||
if (returnDt in IntegerDatatypes) {
|
||||
// first assign to intermediary variable, then return that
|
||||
val returnVarName = "retval_interm_" + when(returnDt) {
|
||||
DataType.UBYTE -> "ub"
|
||||
DataType.BYTE -> "b"
|
||||
DataType.UWORD -> "uw"
|
||||
DataType.WORD -> "w"
|
||||
else -> "<undefined>"
|
||||
}
|
||||
val returnValueIntermediary = IdentifierReference(listOf("prog8_lib", returnVarName), returnStmt.position)
|
||||
val returnVarName = program.getTempVar(returnDt)
|
||||
val returnValueIntermediary = IdentifierReference(returnVarName, returnStmt.position)
|
||||
val tgt = AssignTarget(returnValueIntermediary, null, null, returnStmt.position)
|
||||
val assign = Assignment(tgt, value, AssignmentOrigin.OPTIMIZER, returnStmt.position)
|
||||
val returnReplacement = Return(returnValueIntermediary.copy(), returnStmt.position)
|
||||
|
|
|
@ -10,8 +10,6 @@ floats {
|
|||
const float PI = 3.141592653589793
|
||||
const float TWOPI = 6.283185307179586
|
||||
|
||||
float tempvar_swap_float ; used for some swap() operations
|
||||
|
||||
|
||||
; ---- ROM float functions ----
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@ floats {
|
|||
const float PI = 3.141592653589793
|
||||
const float TWOPI = 6.283185307179586
|
||||
|
||||
float tempvar_swap_float ; used for some swap() operations
|
||||
|
||||
|
||||
; ---- ROM float functions ----
|
||||
|
||||
|
|
|
@ -6,24 +6,6 @@ prog8_lib {
|
|||
%asminclude "library:prog8_lib.asm"
|
||||
%asminclude "library:prog8_funcs.asm"
|
||||
|
||||
; to store intermediary expression results for return values:
|
||||
; NOTE: these variables can be used in the StatementReorderer and StatementOptimizer
|
||||
uword @zp retval_interm_uw
|
||||
word @zp retval_interm_w
|
||||
ubyte @zp retval_interm_ub
|
||||
byte @zp retval_interm_b
|
||||
word retval_interm_w2
|
||||
byte retval_interm_b2
|
||||
|
||||
; prog8 "hooks" to be able to access the temporary scratch variables
|
||||
; YOU SHOULD NOT USE THESE IN USER CODE - THESE ARE MEANT FOR INTERNAL COMPILER USE
|
||||
; NOTE: the assembly code generator will match these names and not generate
|
||||
; new variables/memdefs for them, rather, they'll point to the scratch variables directly.
|
||||
&ubyte P8ZP_SCRATCH_REG = $ff
|
||||
&byte P8ZP_SCRATCH_B1 = $ff
|
||||
&uword P8ZP_SCRATCH_W1 = $ff
|
||||
&word P8ZP_SCRATCH_W2 = $ff
|
||||
|
||||
|
||||
asmsub pattern_match(str string @AY, str pattern @R0) clobbers(Y) -> ubyte @A {
|
||||
%asm {{
|
||||
|
|
|
@ -345,7 +345,7 @@ private fun writeAssembly(program: Program,
|
|||
// asm generation directly from the Ast
|
||||
compilerOptions.compTarget.machine.initializeZeropage(compilerOptions)
|
||||
val variables = VariableExtractor().extractVars(program)
|
||||
program.processAstBeforeAsmGeneration(compilerOptions, errors)
|
||||
program.processAstBeforeAsmGeneration(compilerOptions, variables, errors)
|
||||
errors.report()
|
||||
|
||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||
|
|
|
@ -13,6 +13,7 @@ import prog8.ast.walk.IAstModification
|
|||
import prog8.compilerinterface.CompilationOptions
|
||||
import prog8.compilerinterface.IErrorReporter
|
||||
import prog8.compilerinterface.IStringEncoding
|
||||
import prog8.compilerinterface.IVariablesAndConsts
|
||||
|
||||
|
||||
internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: CompilationOptions) {
|
||||
|
@ -23,8 +24,8 @@ internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: Compila
|
|||
checker.visit(this)
|
||||
}
|
||||
|
||||
internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationOptions, errors: IErrorReporter) {
|
||||
val fixer = BeforeAsmAstChanger(this, compilerOptions, errors)
|
||||
internal fun Program.processAstBeforeAsmGeneration(compilerOptions: CompilationOptions, variables: IVariablesAndConsts, errors: IErrorReporter) {
|
||||
val fixer = BeforeAsmAstChanger(this, compilerOptions, variables, errors)
|
||||
fixer.visit(this)
|
||||
while(errors.noErrors() && fixer.applyModifications()>0) {
|
||||
fixer.visit(this)
|
||||
|
|
|
@ -8,10 +8,11 @@ import prog8.ast.walk.AstWalker
|
|||
import prog8.ast.walk.IAstModification
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.compilerinterface.*
|
||||
import prog8.optimizer.getTempVarName
|
||||
import prog8.optimizer.getTempRegisterName
|
||||
|
||||
internal class BeforeAsmAstChanger(val program: Program,
|
||||
private val options: CompilationOptions,
|
||||
private val variables: IVariablesAndConsts,
|
||||
private val errors: IErrorReporter
|
||||
) : AstWalker() {
|
||||
|
||||
|
@ -243,7 +244,7 @@ internal class BeforeAsmAstChanger(val program: Program,
|
|||
}
|
||||
|
||||
if(separateLeftExpr) {
|
||||
val name = getTempVarName(leftDt)
|
||||
val name = getTempRegisterName(leftDt)
|
||||
leftOperandReplacement = IdentifierReference(name, expr.position)
|
||||
leftAssignment = Assignment(
|
||||
AssignTarget(IdentifierReference(name, expr.position), null, null, expr.position),
|
||||
|
@ -252,13 +253,9 @@ internal class BeforeAsmAstChanger(val program: Program,
|
|||
)
|
||||
}
|
||||
if(separateRightExpr) {
|
||||
val name = when {
|
||||
rightDt istype DataType.UBYTE -> listOf("prog8_lib","retval_interm_ub")
|
||||
rightDt istype DataType.UWORD -> listOf("prog8_lib","retval_interm_uw")
|
||||
rightDt istype DataType.BYTE -> listOf("prog8_lib","retval_interm_b2")
|
||||
rightDt istype DataType.WORD -> listOf("prog8_lib","retval_interm_w2")
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
val name = program.getTempVar(rightDt.getOrElse { throw FatalAstException("invalid dt") }, true)
|
||||
val tempvardecl = program.toplevelModule.lookup(name) as VarDecl
|
||||
variables.addIfUnknown(tempvardecl.definingBlock, tempvardecl)
|
||||
rightOperandReplacement = IdentifierReference(name, expr.position)
|
||||
rightAssignment = Assignment(
|
||||
AssignTarget(IdentifierReference(name, expr.position), null, null, expr.position),
|
||||
|
@ -354,7 +351,9 @@ internal class BeforeAsmAstChanger(val program: Program,
|
|||
val modifications = mutableListOf<IAstModification>()
|
||||
val statement = expr.containingStatement
|
||||
val dt = expr.indexer.indexExpr.inferType(program)
|
||||
val tempvar = if(dt.isBytes) listOf("prog8_lib","retval_interm_ub") else listOf("prog8_lib","retval_interm_b")
|
||||
val tempvar = program.getTempVar(dt.getOrElse { throw FatalAstException("invalid dt") })
|
||||
val tempvardecl = program.toplevelModule.lookup(tempvar) as VarDecl
|
||||
variables.addIfUnknown(tempvardecl.definingBlock, tempvardecl)
|
||||
val target = AssignTarget(IdentifierReference(tempvar, expr.indexer.position), null, null, expr.indexer.position)
|
||||
val assign = Assignment(target, expr.indexer.indexExpr, AssignmentOrigin.BEFOREASMGEN, expr.indexer.position)
|
||||
modifications.add(IAstModification.InsertBefore(statement, assign, statement.parent as IStatementContainer))
|
||||
|
|
|
@ -55,8 +55,8 @@ internal class StatementReorderer(val program: Program,
|
|||
// This allows you to restart the program and have the same starting values of the variables
|
||||
// So basically consider 'ubyte xx' as a short form for 'ubyte xx; xx=0'
|
||||
decl.value = null
|
||||
if(decl.name.startsWith("retval_interm_") && decl.definingScope.name=="prog8_lib") {
|
||||
// no need to zero out the special internal returnvalue intermediates.
|
||||
if(decl.name.startsWith("tempvar_") && decl.definingScope.name=="prog8_lib") {
|
||||
// no need to zero out the special internal temporary variables.
|
||||
return noModifications
|
||||
}
|
||||
if(decl.findInitializer(program)!=null)
|
||||
|
|
|
@ -104,18 +104,17 @@ internal class VariablesAndConsts (
|
|||
override val subroutineConsts: Map<Subroutine, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||
override val subroutineMemvars: Map<Subroutine, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||
|
||||
private val bv = astBlockVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticVariable>() }.toMutableMap()
|
||||
private val bc = astBlockConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||
private val bmv = astBlockMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||
private val sv = astSubroutineVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticVariable>() }
|
||||
private val sc = astSubroutineConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||
private val smv = astSubroutineMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||
|
||||
init {
|
||||
val bv = astBlockVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticVariable>() }
|
||||
val bc = astBlockConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||
val bmv = astBlockMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||
val sv = astSubroutineVars.keys.associateWith { mutableSetOf<IVariablesAndConsts.StaticVariable>() }
|
||||
val sc = astSubroutineConsts.keys.associateWith { mutableSetOf<IVariablesAndConsts.ConstantNumberSymbol>() }
|
||||
val smv = astSubroutineMemvars.keys.associateWith { mutableSetOf<IVariablesAndConsts.MemoryMappedVariable>() }
|
||||
astBlockVars.forEach { (block, decls) ->
|
||||
val vars = bv.getValue(block)
|
||||
vars.addAll(decls.map {
|
||||
IVariablesAndConsts.StaticVariable(it.datatype, it.scopedName, it.definingScope, it.value, it.arraysize?.constIndex(), it.zeropage, it.position)
|
||||
})
|
||||
vars.addAll(decls.map { toStatic(it) })
|
||||
}
|
||||
astBlockConsts.forEach { (block, decls) ->
|
||||
bc.getValue(block).addAll(
|
||||
|
@ -146,9 +145,7 @@ internal class VariablesAndConsts (
|
|||
}
|
||||
astSubroutineVars.forEach { (sub, decls) ->
|
||||
val vars = sv.getValue(sub)
|
||||
vars.addAll(decls.map {
|
||||
IVariablesAndConsts.StaticVariable(it.datatype, it.scopedName, it.definingScope, it.value, it.arraysize?.constIndex(), it.zeropage, it.position)
|
||||
})
|
||||
vars.addAll(decls.map { toStatic(it) })
|
||||
}
|
||||
astSubroutineConsts.forEach { (sub, decls) ->
|
||||
sc.getValue(sub).addAll(
|
||||
|
@ -179,4 +176,16 @@ internal class VariablesAndConsts (
|
|||
subroutineConsts = sc
|
||||
subroutineMemvars = smv
|
||||
}
|
||||
|
||||
private fun toStatic(decl: VarDecl) =
|
||||
IVariablesAndConsts.StaticVariable(decl.datatype, decl.scopedName, decl.definingScope, decl.value, decl.arraysize?.constIndex(), decl.zeropage, decl.position)
|
||||
|
||||
override fun addIfUnknown(definingBlock: Block, variable: VarDecl) {
|
||||
var blockvars = bv[definingBlock]
|
||||
if(blockvars==null) {
|
||||
blockvars = mutableSetOf()
|
||||
bv[definingBlock] = blockvars
|
||||
}
|
||||
blockvars.add(toStatic(variable))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ class TestOptimization: FunSpec({
|
|||
expr.inferType(result.program).getOrElse { fail("dt") } shouldBe DataType.UBYTE
|
||||
|
||||
val options = CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.DONTUSE, emptyList(), false, true, C64Target(), outputDir= outputDir)
|
||||
result.program.processAstBeforeAsmGeneration(options, ErrorReporterForTests())
|
||||
result.program.processAstBeforeAsmGeneration(options, DummyVarsAndConsts, ErrorReporterForTests())
|
||||
|
||||
// assignment is now split into:
|
||||
// bb = not bb
|
||||
|
@ -357,11 +357,11 @@ class TestOptimization: FunSpec({
|
|||
st.size shouldBe 8
|
||||
st.last() shouldBe instanceOf<Return>()
|
||||
var assign = st[3] as Assignment
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("prog8_lib","retval_interm_b")
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("prog8_lib","tempvar_b")
|
||||
assign = st[4] as Assignment
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("prog8_lib","retval_interm_b")
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("prog8_lib","tempvar_b")
|
||||
assign = st[5] as Assignment
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("prog8_lib","retval_interm_b")
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("prog8_lib","tempvar_b")
|
||||
assign = st[6] as Assignment
|
||||
assign.target.identifier!!.nameInSource shouldBe listOf("bb")
|
||||
}
|
||||
|
|
|
@ -76,6 +76,11 @@ class TestAsmGenSymbols: StringSpec({
|
|||
override val subroutineVars: Map<Subroutine, Set<IVariablesAndConsts.StaticVariable>>
|
||||
override val subroutineConsts: Map<Subroutine, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||
override val subroutineMemvars: Map<Subroutine, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||
|
||||
override fun addIfUnknown(definingBlock: Block, variable: VarDecl) {
|
||||
throw NotImplementedError("dummy")
|
||||
}
|
||||
|
||||
init {
|
||||
blockVars = mutableMapOf()
|
||||
blockVars[block] = mutableSetOf(IVariablesAndConsts.StaticVariable(varInBlock.datatype, varInBlock.scopedName, varInBlock.definingScope, varInBlock.value, varInBlock.arraysize?.constIndex(), varInBlock.zeropage, varInBlock.position))
|
||||
|
|
|
@ -6,6 +6,7 @@ import prog8.ast.base.Position
|
|||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.expressions.InferredTypes
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.statements.Block
|
||||
import prog8.ast.statements.RegisterOrStatusflag
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.VarDecl
|
||||
|
@ -76,3 +77,23 @@ internal object DummyCompilationTarget : ICompilationTarget {
|
|||
throw NotImplementedError("dummy")
|
||||
}
|
||||
}
|
||||
|
||||
internal object DummyVarsAndConsts : IVariablesAndConsts {
|
||||
override val blockVars: Map<Block, Set<IVariablesAndConsts.StaticVariable>>
|
||||
get() = throw NotImplementedError("dummy")
|
||||
override val blockConsts: Map<Block, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||
get() = throw NotImplementedError("dummy")
|
||||
override val blockMemvars: Map<Block, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||
get() = throw NotImplementedError("dummy")
|
||||
override val subroutineVars: Map<Subroutine, Set<IVariablesAndConsts.StaticVariable>>
|
||||
get() = throw NotImplementedError("dummy")
|
||||
override val subroutineConsts: Map<Subroutine, Set<IVariablesAndConsts.ConstantNumberSymbol>>
|
||||
get() = throw NotImplementedError("dummy")
|
||||
override val subroutineMemvars: Map<Subroutine, Set<IVariablesAndConsts.MemoryMappedVariable>>
|
||||
get() = throw NotImplementedError("dummy")
|
||||
|
||||
override fun addIfUnknown(definingBlock: Block, variable: VarDecl) {
|
||||
throw NotImplementedError("dummy")
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,12 @@
|
|||
package prog8.ast
|
||||
|
||||
import prog8.ast.base.DataType
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.base.Position
|
||||
import prog8.ast.base.VarDeclType
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.ast.statements.VarDeclOrigin
|
||||
import prog8.ast.statements.ZeropageWish
|
||||
import kotlin.math.abs
|
||||
|
||||
fun Number.toHex(): String {
|
||||
|
@ -29,3 +36,37 @@ fun UInt.toHex(): String {
|
|||
else -> throw IllegalArgumentException("number too large for 16 bits $this")
|
||||
}
|
||||
}
|
||||
|
||||
fun Program.getTempVar(dt: DataType, altNames: Boolean=false): List<String> {
|
||||
val tmpvarName = if(altNames) {
|
||||
when (dt) {
|
||||
DataType.UBYTE -> listOf("prog8_lib", "tempvar_ub2")
|
||||
DataType.BYTE -> listOf("prog8_lib", "tempvar_b2")
|
||||
DataType.UWORD -> listOf("prog8_lib", "tempvar_uw2")
|
||||
DataType.WORD -> listOf("prog8_lib", "tempvar_w2")
|
||||
DataType.FLOAT -> listOf("floats", "tempvar_swap_float2")
|
||||
else -> throw FatalAstException("invalid dt")
|
||||
}
|
||||
} else {
|
||||
when (dt) {
|
||||
DataType.UBYTE -> listOf("prog8_lib", "tempvar_ub")
|
||||
DataType.BYTE -> listOf("prog8_lib", "tempvar_b")
|
||||
DataType.UWORD -> listOf("prog8_lib", "tempvar_uw")
|
||||
DataType.WORD -> listOf("prog8_lib", "tempvar_w")
|
||||
DataType.FLOAT -> listOf("floats", "tempvar_swap_float")
|
||||
else -> throw FatalAstException("invalid dt")
|
||||
}
|
||||
}
|
||||
|
||||
val block = this.allBlocks.first { it.name==tmpvarName[0] }
|
||||
if(block.statements.filterIsInstance<VarDecl>().any { it.name == tmpvarName[1] })
|
||||
return tmpvarName
|
||||
|
||||
// add new temp variable to the ast directly (we can do this here because we're not iterating inside those container blocks)
|
||||
val decl = VarDecl(
|
||||
VarDeclType.VAR, VarDeclOrigin.AUTOGENERATED, dt, ZeropageWish.DONTCARE,
|
||||
null, tmpvarName[1], null, false, false, null, Position.DUMMY)
|
||||
block.statements.add(decl)
|
||||
decl.linkParents(block)
|
||||
return tmpvarName
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ class Program(val name: String,
|
|||
}
|
||||
|
||||
val allBlocks: List<Block>
|
||||
get() = modules.flatMap { it.statements.filterIsInstance<Block>() }
|
||||
get() = modules.flatMap { it.statements.asSequence().filterIsInstance<Block>() }
|
||||
|
||||
val entrypoint: Subroutine
|
||||
get() {
|
||||
|
|
|
@ -175,7 +175,8 @@ enum class VarDeclOrigin {
|
|||
USERCODE,
|
||||
SUBROUTINEPARAM,
|
||||
STRINGLITERAL,
|
||||
ARRAYLITERAL
|
||||
ARRAYLITERAL,
|
||||
AUTOGENERATED
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ fun AssignTarget.isIOAddress(machine: IMachineDefinition): Boolean {
|
|||
} else false
|
||||
}
|
||||
ident != null -> {
|
||||
val decl = ident.targetVarDecl(definingModule.program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}")
|
||||
val decl = ident.targetVarDecl(definingModule.program) ?:
|
||||
throw FatalAstException("invalid identifier ${ident.nameInSource}")
|
||||
return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue)
|
||||
machine.isIOAddress((decl.value as NumericLiteralValue).number.toUInt())
|
||||
else
|
||||
|
|
|
@ -27,4 +27,6 @@ interface IVariablesAndConsts {
|
|||
val subroutineVars: Map<Subroutine, Set<StaticVariable>>
|
||||
val subroutineConsts: Map<Subroutine, Set<ConstantNumberSymbol>>
|
||||
val subroutineMemvars: Map<Subroutine, Set<MemoryMappedVariable>>
|
||||
|
||||
fun addIfUnknown(definingBlock: Block, variable: VarDecl)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ TODO
|
|||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- (newvaralloc) UnusedCodeRemover after(decl: VarDecl): fix that vars defined in a library can also safely be removed if unused. Currently this breaks programs such as textelite (due to diskio.save().end_address ?)
|
||||
- check that retval_interm_* are not in the varallocation if they're not used
|
||||
- make it so that subroutine parameters as variables can again be allocated in ZP, if there's still space
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user