mirror of
https://github.com/irmen/prog8.git
synced 2024-10-19 07:23:56 +00:00
vardecl with initializer expression are now optimized again (unless floats)
This commit is contained in:
parent
74b5124a42
commit
8eb69d6eda
@ -33,7 +33,7 @@ graphics {
|
|||||||
}
|
}
|
||||||
word @zp d = 0
|
word @zp d = 0
|
||||||
ubyte positive_ix = true
|
ubyte positive_ix = true
|
||||||
word @zp dx = x2-x1
|
word @zp dx = x2-x1 as word
|
||||||
word @zp dy = y2-y1
|
word @zp dy = y2-y1
|
||||||
if dx < 0 {
|
if dx < 0 {
|
||||||
dx = -dx
|
dx = -dx
|
||||||
|
@ -11,7 +11,7 @@ internal class StatementReorderer(val program: Program, val errors: ErrorReporte
|
|||||||
// - 'main' block must be the very first statement UNLESS it has an address set.
|
// - 'main' block must be the very first statement UNLESS it has an address set.
|
||||||
// - library blocks are put last.
|
// - library blocks are put last.
|
||||||
// - blocks are ordered by address, where blocks without address are placed last.
|
// - blocks are ordered by address, where blocks without address are placed last.
|
||||||
// - in every scope, most directives and vardecls are moved to the top.
|
// - in every block and module, most directives and vardecls are moved to the top. (not in subroutines!)
|
||||||
// - the 'start' subroutine is moved to the top.
|
// - the 'start' subroutine is moved to the top.
|
||||||
// - (syntax desugaring) a vardecl with a non-const initializer value is split into a regular vardecl and an assignment statement.
|
// - (syntax desugaring) a vardecl with a non-const initializer value is split into a regular vardecl and an assignment statement.
|
||||||
// - (syntax desugaring) struct value assignment is expanded into several struct member assignments.
|
// - (syntax desugaring) struct value assignment is expanded into several struct member assignments.
|
||||||
@ -121,6 +121,28 @@ internal class StatementReorderer(val program: Program, val errors: ErrorReporte
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> {
|
||||||
|
val declValue = decl.value
|
||||||
|
if(declValue!=null && decl.type== VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
||||||
|
val declConstValue = declValue.constValue(program)
|
||||||
|
if(declConstValue==null) {
|
||||||
|
// move the vardecl (without value) to the scope and replace this with a regular assignment
|
||||||
|
// Unless we're dealing with a floating point variable because that will actually make things less efficient at the moment (because floats are mostly calcualated via the stack)
|
||||||
|
if(decl.datatype!=DataType.FLOAT) {
|
||||||
|
decl.value = null
|
||||||
|
decl.allowInitializeWithZero = false
|
||||||
|
val target = AssignTarget(IdentifierReference(listOf(decl.name), decl.position), null, null, decl.position)
|
||||||
|
val assign = Assignment(target, declValue, decl.position)
|
||||||
|
return listOf(
|
||||||
|
IAstModification.ReplaceNode(decl, assign, parent),
|
||||||
|
IAstModification.InsertFirst(decl, decl.definingScope() as Node)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
override fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
override fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||||
val valueType = assignment.value.inferType(program)
|
val valueType = assignment.value.inferType(program)
|
||||||
val targetType = assignment.target.inferType(program, assignment)
|
val targetType = assignment.target.inferType(program, assignment)
|
||||||
|
@ -5,6 +5,7 @@ import prog8.ast.base.*
|
|||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.processing.AstWalker
|
import prog8.ast.processing.AstWalker
|
||||||
import prog8.ast.processing.IAstVisitor
|
import prog8.ast.processing.IAstVisitor
|
||||||
|
import prog8.compiler.CompilerException
|
||||||
import prog8.compiler.target.CompilationTarget
|
import prog8.compiler.target.CompilationTarget
|
||||||
|
|
||||||
|
|
||||||
@ -171,6 +172,7 @@ open class VarDecl(val type: VarDeclType,
|
|||||||
private set
|
private set
|
||||||
var structHasBeenFlattened = false // set later
|
var structHasBeenFlattened = false // set later
|
||||||
private set
|
private set
|
||||||
|
var allowInitializeWithZero = true
|
||||||
|
|
||||||
// prefix for literal values that are turned into a variable on the heap
|
// prefix for literal values that are turned into a variable on the heap
|
||||||
|
|
||||||
@ -242,7 +244,12 @@ open class VarDecl(val type: VarDeclType,
|
|||||||
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, struct=$structName, value=$value, pos=$position)"
|
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, struct=$structName, value=$value, pos=$position)"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun zeroElementValue() = defaultZero(declaredDatatype, position)
|
fun zeroElementValue(): NumericLiteralValue {
|
||||||
|
if(allowInitializeWithZero)
|
||||||
|
return defaultZero(declaredDatatype, position)
|
||||||
|
else
|
||||||
|
throw CompilerException("attempt to get zero value for vardecl that shouldn't get it")
|
||||||
|
}
|
||||||
|
|
||||||
fun flattenStructMembers(): MutableList<Statement> {
|
fun flattenStructMembers(): MutableList<Statement> {
|
||||||
val result = struct!!.statements.withIndex().map {
|
val result = struct!!.statements.withIndex().map {
|
||||||
|
@ -19,11 +19,14 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
if (decl.value == null && !decl.autogeneratedDontRemove && decl.type == VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
if (decl.value == null && !decl.autogeneratedDontRemove && decl.type == VarDeclType.VAR && decl.datatype in NumericDatatypes) {
|
||||||
// a numeric vardecl without an initial value is initialized with zero,
|
// a numeric vardecl without an initial value is initialized with zero,
|
||||||
// unless there's already an assignment below, that initializes the value
|
// unless there's already an assignment below, that initializes the value
|
||||||
val nextAssign = decl.definingScope().nextSibling(decl) as? Assignment
|
if(decl.allowInitializeWithZero)
|
||||||
if(nextAssign!=null && nextAssign.target.isSameAs(IdentifierReference(listOf(decl.name), Position.DUMMY)))
|
{
|
||||||
decl.value = null
|
val nextAssign = decl.definingScope().nextSibling(decl) as? Assignment
|
||||||
else
|
if (nextAssign != null && nextAssign.target.isSameAs(IdentifierReference(listOf(decl.name), Position.DUMMY)))
|
||||||
decl.value = decl.zeroElementValue()
|
decl.value = null
|
||||||
|
else
|
||||||
|
decl.value = decl.zeroElementValue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
@ -7,23 +7,20 @@ main {
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
ubyte[] array = [1,2,3,4]
|
uword zc
|
||||||
|
|
||||||
const ubyte ic = 2
|
zc = 99
|
||||||
ubyte ib = 2
|
scolor2=scolor
|
||||||
|
|
||||||
|
; TODO WHy does this compile with stack eval:
|
||||||
|
ubyte scolor = (zc>>13) as ubyte + 4
|
||||||
|
|
||||||
|
; TODO this is more optimized:
|
||||||
|
ubyte scolor2
|
||||||
|
scolor2 = (zc>>13) as ubyte + 4
|
||||||
|
|
||||||
|
scolor2=scolor
|
||||||
|
|
||||||
ib = array[ic+1]
|
|
||||||
ib = array[ib]
|
|
||||||
ib = array[ib+1]
|
|
||||||
ib = array[ib+2]
|
|
||||||
ib = array[ib-1]
|
|
||||||
ib = array[ib-2]
|
|
||||||
ib = array[ib*2]
|
|
||||||
ib = array[2*ib]
|
|
||||||
ib = array[ib*3]
|
|
||||||
ib = array[3*ib]
|
|
||||||
ib = array[ib*4]
|
|
||||||
ib = array[4*ib]
|
|
||||||
testX()
|
testX()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user