mirror of
https://github.com/irmen/prog8.git
synced 2025-02-19 11:31:07 +00:00
use memcopy to assign arrays
This commit is contained in:
parent
d787795759
commit
4f8d4a9585
@ -268,32 +268,31 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
|
|||||||
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)
|
val targetType = assignment.target.inferType(program)
|
||||||
var assignments = emptyList<Assignment>()
|
|
||||||
|
|
||||||
if(targetType.istype(DataType.STRUCT) && (valueType.istype(DataType.STRUCT) || valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes )) {
|
if(targetType.istype(DataType.STRUCT) && (valueType.istype(DataType.STRUCT) || valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes )) {
|
||||||
assignments = if (assignment.value is ArrayLiteralValue) {
|
val assignments = if (assignment.value is ArrayLiteralValue) {
|
||||||
flattenStructAssignmentFromStructLiteral(assignment) // 'structvar = [ ..... ] '
|
throw FatalAstException("array literal should have been translated to a variable at "+assignment.position.toString())
|
||||||
} else {
|
} else {
|
||||||
flattenStructAssignmentFromIdentifier(assignment) // 'structvar1 = structvar2'
|
flattenStructAssignmentFromIdentifier(assignment)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(assignments.isNotEmpty()) {
|
||||||
|
val modifications = mutableListOf<IAstModification>()
|
||||||
|
val scope = assignment.definingScope()
|
||||||
|
assignments.reversed().mapTo(modifications) { IAstModification.InsertAfter(assignment, it, scope) }
|
||||||
|
modifications.add(IAstModification.Remove(assignment, scope))
|
||||||
|
return modifications
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(targetType.typeOrElse(DataType.STRUCT) in ArrayDatatypes && valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes ) {
|
if(targetType.typeOrElse(DataType.STRUCT) in ArrayDatatypes && valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes ) {
|
||||||
assignments = if (assignment.value is ArrayLiteralValue) {
|
if (assignment.value is ArrayLiteralValue) {
|
||||||
flattenArrayAssignmentFromArrayLiteral(assignment) // 'arrayvar = [ ..... ] '
|
throw FatalAstException("array literal should have been translated to a variable at "+assignment.position.toString())
|
||||||
} else {
|
} else {
|
||||||
flattenArrayAssignmentFromIdentifier(assignment) // 'arrayvar1 = arrayvar2'
|
return copyArrayValue(assignment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(assignments.isNotEmpty()) {
|
|
||||||
val modifications = mutableListOf<IAstModification>()
|
|
||||||
val scope = assignment.definingScope()
|
|
||||||
assignments.reversed().mapTo(modifications) { IAstModification.InsertAfter(assignment, it, scope) }
|
|
||||||
modifications.add(IAstModification.Remove(assignment, scope))
|
|
||||||
return modifications
|
|
||||||
}
|
|
||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,66 +345,37 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun flattenArrayAssignmentFromArrayLiteral(assign: Assignment): List<Assignment> {
|
private fun copyArrayValue(assign: Assignment): List<IAstModification> {
|
||||||
val identifier = assign.target.identifier!!
|
val identifier = assign.target.identifier!!
|
||||||
val targetVar = identifier.targetVarDecl(program)!!
|
val targetVar = identifier.targetVarDecl(program)!!
|
||||||
val alv = assign.value as? ArrayLiteralValue
|
|
||||||
return flattenArrayAssign(targetVar, alv, identifier, assign.position)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun flattenArrayAssignmentFromIdentifier(assign: Assignment): List<Assignment> {
|
if(targetVar.arraysize==null)
|
||||||
val identifier = assign.target.identifier!!
|
errors.err("array has no defined size", assign.position)
|
||||||
val targetVar = identifier.targetVarDecl(program)!!
|
|
||||||
val sourceIdent = assign.value as IdentifierReference
|
val sourceIdent = assign.value as IdentifierReference
|
||||||
val sourceVar = sourceIdent.targetVarDecl(program)!!
|
val sourceVar = sourceIdent.targetVarDecl(program)!!
|
||||||
if(!sourceVar.isArray) {
|
if(!sourceVar.isArray) {
|
||||||
errors.err("value must be an array", sourceIdent.position)
|
errors.err("value must be an array", sourceIdent.position)
|
||||||
|
} else {
|
||||||
|
if (sourceVar.arraysize!!.constIndex() != targetVar.arraysize!!.constIndex())
|
||||||
|
errors.err("element count mismatch", assign.position)
|
||||||
|
if (sourceVar.datatype != targetVar.datatype)
|
||||||
|
errors.err("element type mismatch", assign.position)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!errors.isEmpty())
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
|
||||||
val alv = sourceVar.value as? ArrayLiteralValue
|
|
||||||
return flattenArrayAssign(targetVar, alv, identifier, assign.position)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun flattenArrayAssign(targetVar: VarDecl, alv: ArrayLiteralValue?, identifier: IdentifierReference, position: Position): List<Assignment> {
|
val memcopy = FunctionCallStatement(IdentifierReference(listOf("sys", "memcopy"), assign.position),
|
||||||
if(targetVar.arraysize==null) {
|
mutableListOf(
|
||||||
errors.err("array has no defined size", identifier.position)
|
AddressOf(sourceIdent, assign.position),
|
||||||
return emptyList()
|
AddressOf(identifier, assign.position),
|
||||||
}
|
NumericLiteralValue.optimalInteger(targetVar.arraysize!!.constIndex()!!, assign.position)
|
||||||
|
),
|
||||||
if(alv==null || alv.value.size != targetVar.arraysize!!.constIndex()) {
|
true,
|
||||||
errors.err("element count mismatch", position)
|
assign.position
|
||||||
return emptyList()
|
)
|
||||||
}
|
return listOf(IAstModification.ReplaceNode(assign, memcopy, assign.parent))
|
||||||
|
|
||||||
// TODO use memcopy instead of individual assignments after certain amount of elements
|
|
||||||
// TODO what does assigning a struct var use?
|
|
||||||
return alv.value.mapIndexed { index, value ->
|
|
||||||
val idx = ArrayIndexedExpression(identifier, ArrayIndex(NumericLiteralValue(DataType.UBYTE, index, position), position), position)
|
|
||||||
Assignment(AssignTarget(null, idx, null, position), value, value.position)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun flattenStructAssignmentFromStructLiteral(structAssignment: Assignment): List<Assignment> {
|
|
||||||
val identifier = structAssignment.target.identifier!!
|
|
||||||
val identifierName = identifier.nameInSource.single()
|
|
||||||
val targetVar = identifier.targetVarDecl(program)!!
|
|
||||||
val struct = targetVar.struct!!
|
|
||||||
|
|
||||||
val slv = structAssignment.value as? ArrayLiteralValue
|
|
||||||
if(slv==null || slv.value.size != struct.numberOfElements) {
|
|
||||||
errors.err("element count mismatch", structAssignment.position)
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
return struct.statements.zip(slv.value).map { (targetDecl, sourceValue) ->
|
|
||||||
targetDecl as VarDecl
|
|
||||||
val mangled = mangledStructMemberName(identifierName, targetDecl.name)
|
|
||||||
val idref = IdentifierReference(listOf(mangled), structAssignment.position)
|
|
||||||
val assign = Assignment(AssignTarget(idref, null, null, structAssignment.position),
|
|
||||||
sourceValue, sourceValue.position)
|
|
||||||
assign.linkParents(structAssignment)
|
|
||||||
assign
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun flattenStructAssignmentFromIdentifier(structAssignment: Assignment): List<Assignment> {
|
private fun flattenStructAssignmentFromIdentifier(structAssignment: Assignment): List<Assignment> {
|
||||||
|
@ -757,11 +757,12 @@ all(x)
|
|||||||
1 ('true') if all of the values in the array value x are 'true' (not zero), else 0 ('false')
|
1 ('true') if all of the values in the array value x are 'true' (not zero), else 0 ('false')
|
||||||
|
|
||||||
len(x)
|
len(x)
|
||||||
Number of values in the array value x, or the number of characters in a string (excluding the size or 0-byte).
|
Number of values in the array value x, or the number of characters in a string (excluding the 0-byte).
|
||||||
Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte. See sizeof().
|
Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte. See sizeof().
|
||||||
Note: lengths of strings and arrays are determined at compile-time! If your program modifies the actual
|
Note: lengths of strings and arrays are determined at compile-time! If your program modifies the actual
|
||||||
length of the string during execution, the value of len(string) may no longer be correct!
|
length of the string during execution, the value of len(s) may no longer be correct!
|
||||||
(use strlen function if you want to dynamically determine the length)
|
(use the ``string.length`` routine if you want to dynamically determine the length by counting to the
|
||||||
|
first 0-byte)
|
||||||
|
|
||||||
max(x)
|
max(x)
|
||||||
Maximum of the values in the array value x
|
Maximum of the values in the array value x
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- optimize assigning array and struct variables (multi-element assings -> memcopy)
|
- optimize assigning array and struct variables (multi-element assigns -> memcopy)
|
||||||
|
|
||||||
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
|
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
|
||||||
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))
|
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))
|
||||||
- optimize several inner loops in gfx2
|
- optimize several inner loops in gfx2
|
||||||
|
131
examples/test.p8
131
examples/test.p8
@ -4,103 +4,62 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte ubb = $f4
|
ubyte[] arr1 = [1,2,3]
|
||||||
byte bb = -123
|
ubyte[] arr2 = [9,9,9]
|
||||||
uword uww = $f4a1
|
|
||||||
word ww = -12345
|
|
||||||
|
|
||||||
conv.str_ub0($0f)
|
arr1[2]=42
|
||||||
txt.print(conv.string_out)
|
txt.print_ub(arr2[0])
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_ub(arr2[1])
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_ub(arr2[2])
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.print_ub0($0f)
|
arr2=[99,88,77]
|
||||||
|
txt.print_ub(arr2[0])
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_ub(arr2[1])
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_ub(arr2[2])
|
||||||
|
txt.nl()
|
||||||
|
arr2=arr1
|
||||||
|
txt.print_ub(arr2[0])
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_ub(arr2[1])
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_ub(arr2[2])
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
conv.str_ub(ubb)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_ub(ubb)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
conv.str_ub(8)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_ub(8)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_b(bb)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_b(bb)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
conv.str_b(-8)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_b(-8)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_ubhex(ubb)
|
struct MyType {
|
||||||
txt.print(conv.string_out)
|
uword v1
|
||||||
txt.nl()
|
uword w1
|
||||||
txt.print_ubhex(ubb,false)
|
uword w2
|
||||||
txt.nl()
|
}
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_ubbin(ubb)
|
MyType m1 = [1, 888, 999]
|
||||||
txt.print(conv.string_out)
|
MyType m2 = [22, 222, 222]
|
||||||
txt.nl()
|
|
||||||
txt.print_ubbin(ubb,false)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_uwbin(uww)
|
txt.print_uw(m2.v1)
|
||||||
txt.print(conv.string_out)
|
txt.chrout(',')
|
||||||
|
txt.print_uw(m2.w1)
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_uw(m2.w2)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.print_uwbin(uww, false)
|
m2 = [111,222,333]
|
||||||
|
txt.print_uw(m2.v1)
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_uw(m2.w1)
|
||||||
|
txt.chrout(',')
|
||||||
|
txt.print_uw(m2.w2)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.nl()
|
m2 = m1
|
||||||
|
txt.print_uw(m2.v1)
|
||||||
conv.str_uwhex(uww)
|
txt.chrout(',')
|
||||||
txt.print(conv.string_out)
|
txt.print_uw(m2.w1)
|
||||||
txt.nl()
|
txt.chrout(',')
|
||||||
txt.print_uwhex(uww, false)
|
txt.print_uw(m2.w2)
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_uw0(987)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uw0(987)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_uw(uww)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uw(uww)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
conv.str_uw(7)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uw(7)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_w(ww)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_w(ww)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
conv.str_w(99)
|
|
||||||
txt.print(conv.string_out)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_w(99)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user