Skip to content

Commit 97420b2

Browse files
committed
preparing to support assignment to indexed pointer targets
1 parent 1467c70 commit 97420b2

File tree

12 files changed

+197
-135
lines changed

12 files changed

+197
-135
lines changed

codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
9191
array != null -> return AsmAssignTarget(TargetStorageKind.ARRAY, asmgen, type, definingSub, target.position, array = array, origAstTarget = this)
9292
memory != null -> return AsmAssignTarget(TargetStorageKind.MEMORY, asmgen, type, definingSub, target.position, memory = memory, origAstTarget = this)
9393
pointerDeref != null -> return AsmAssignTarget(TargetStorageKind.POINTER, asmgen, type, definingSub, target.position, pointer = pointerDeref, origAstTarget = this)
94+
indexedPointerDeref != null -> TODO("assign to indexed pointer ${target.position} - for now, split up the assignment target using a temporary pointer variable")
9495
else -> throw AssemblyError("weird target")
9596
}
9697
}

codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt

Lines changed: 87 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -463,10 +463,6 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
463463

464464
private fun translateRegularAssign(assignment: PtAssignment): IRCodeChunks {
465465
// note: assigning array and string values is done via an explicit memcopy/stringcopy function call.
466-
val targetIdent = assignment.target.identifier
467-
val targetMemory = assignment.target.memory
468-
val targetArray = assignment.target.array
469-
val targetPointerDeref = assignment.target.pointerDeref
470466
val valueDt = irType(assignment.value.type)
471467
val targetDt = irType(assignment.target.type)
472468
val result = mutableListOf<IRCodeChunkBase>()
@@ -507,98 +503,107 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
507503
}
508504
}
509505

510-
if(targetIdent!=null) {
511-
val instruction = if(zero) {
512-
IRInstruction(Opcode.STOREZM, targetDt, labelSymbol = targetIdent.name)
513-
} else {
514-
if (targetDt == IRDataType.FLOAT) {
515-
require(valueFpRegister>=0)
516-
IRInstruction(Opcode.STOREM, targetDt, fpReg1 = valueFpRegister, labelSymbol = targetIdent.name)
517-
}
518-
else {
519-
require(valueRegister>=0)
520-
IRInstruction(Opcode.STOREM, targetDt, reg1 = valueRegister, labelSymbol = targetIdent.name)
521-
}
522-
}
523-
result += IRCodeChunk(null, null).also { it += instruction }
524-
return result
525-
}
526-
else if(targetArray!=null) {
527-
val eltSize = codeGen.program.memsizer.memorySize(targetArray.type, null)
528-
val variable = targetArray.variable
529-
if(variable==null)
530-
translateRegularAssignPointerIndexed(result, targetArray.pointerderef!!, eltSize, targetArray, zero, targetDt, valueRegister, valueFpRegister)
531-
else if(variable.type.isPointer)
532-
assignToIndexedSimplePointer(result, variable, eltSize, targetArray, zero, targetDt, valueRegister, valueFpRegister)
533-
else
534-
translateRegularAssignArrayIndexed(result, variable.name, eltSize, targetArray, zero, targetDt, valueRegister, valueFpRegister)
535-
return result
536-
}
537-
else if(targetMemory!=null) {
538-
require(targetDt == IRDataType.BYTE) { "must be byte type ${targetMemory.position}"}
539-
if(zero) {
540-
if(targetMemory.address is PtNumber) {
541-
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, targetDt, address = (targetMemory.address as PtNumber).number.toInt()) }
542-
result += chunk
543-
} else {
544-
val tr = expressionEval.translateExpression(targetMemory.address)
545-
val addressReg = tr.resultReg
546-
addToResult(result, tr, tr.resultReg, -1)
547-
result += IRCodeChunk(null, null).also {
548-
it += IRInstruction(Opcode.STOREZI, targetDt, reg1=addressReg)
506+
with(assignment.target) {
507+
when {
508+
identifier != null -> {
509+
val instruction = if(zero) {
510+
IRInstruction(Opcode.STOREZM, targetDt, labelSymbol = identifier!!.name)
511+
} else {
512+
if (targetDt == IRDataType.FLOAT) {
513+
require(valueFpRegister>=0)
514+
IRInstruction(Opcode.STOREM, targetDt, fpReg1 = valueFpRegister, labelSymbol = identifier!!.name)
515+
}
516+
else {
517+
require(valueRegister>=0)
518+
IRInstruction(Opcode.STOREM, targetDt, reg1 = valueRegister, labelSymbol = identifier!!.name)
519+
}
549520
}
550-
}
551-
} else {
552-
val constAddress = targetMemory.address as? PtNumber
553-
if(constAddress!=null) {
554-
addInstr(result, IRInstruction(Opcode.STOREM, targetDt, reg1=valueRegister, address=constAddress.number.toInt()), null)
521+
result += IRCodeChunk(null, null).also { it += instruction }
555522
return result
556523
}
557-
val ptrWithOffset = targetMemory.address as? PtBinaryExpression
558-
if(ptrWithOffset!=null) {
559-
if(ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier) {
560-
val constOffset = (ptrWithOffset.right as? PtNumber)?.number?.toInt()
561-
if(constOffset in 0..255) {
562-
val ptrName = (ptrWithOffset.left as PtIdentifier).name
563-
val pointerReg = codeGen.registers.next(IRDataType.WORD)
524+
memory != null -> {
525+
require(targetDt == IRDataType.BYTE) { "must be byte type ${memory!!.position}"}
526+
if(zero) {
527+
if(memory!!.address is PtNumber) {
528+
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, targetDt, address = (memory!!.address as PtNumber).number.toInt()) }
529+
result += chunk
530+
} else {
531+
val tr = expressionEval.translateExpression(memory!!.address)
532+
val addressReg = tr.resultReg
533+
addToResult(result, tr, tr.resultReg, -1)
564534
result += IRCodeChunk(null, null).also {
565-
it += IRInstruction(Opcode.LOADM, IRDataType.WORD, reg1=pointerReg, labelSymbol = ptrName)
566-
it += IRInstruction(Opcode.STOREFIELD, IRDataType.BYTE, reg1=valueRegister, reg2=pointerReg, immediate = constOffset)
535+
it += IRInstruction(Opcode.STOREZI, targetDt, reg1=addressReg)
567536
}
537+
}
538+
} else {
539+
val constAddress = memory!!.address as? PtNumber
540+
if(constAddress!=null) {
541+
addInstr(result, IRInstruction(Opcode.STOREM, targetDt, reg1=valueRegister, address=constAddress.number.toInt()), null)
568542
return result
569543
}
570-
}
571-
val offsetTypecast = ptrWithOffset.right as? PtTypeCast
572-
if(ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier && (ptrWithOffset.right.type.isByte || offsetTypecast?.value?.type?.isByte==true)) {
573-
// STOREIX only works with byte index.
574-
val tr = if(offsetTypecast?.value?.type?.isByte==true)
575-
expressionEval.translateExpression(offsetTypecast.value)
576-
else
577-
expressionEval.translateExpression(ptrWithOffset.right)
544+
val ptrWithOffset = memory!!.address as? PtBinaryExpression
545+
if(ptrWithOffset!=null) {
546+
if(ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier) {
547+
val constOffset = (ptrWithOffset.right as? PtNumber)?.number?.toInt()
548+
if(constOffset in 0..255) {
549+
val ptrName = (ptrWithOffset.left as PtIdentifier).name
550+
val pointerReg = codeGen.registers.next(IRDataType.WORD)
551+
result += IRCodeChunk(null, null).also {
552+
it += IRInstruction(Opcode.LOADM, IRDataType.WORD, reg1=pointerReg, labelSymbol = ptrName)
553+
it += IRInstruction(Opcode.STOREFIELD, IRDataType.BYTE, reg1=valueRegister, reg2=pointerReg, immediate = constOffset)
554+
}
555+
return result
556+
}
557+
}
558+
val offsetTypecast = ptrWithOffset.right as? PtTypeCast
559+
if(ptrWithOffset.operator=="+" && ptrWithOffset.left is PtIdentifier && (ptrWithOffset.right.type.isByte || offsetTypecast?.value?.type?.isByte==true)) {
560+
// STOREIX only works with byte index.
561+
val tr = if(offsetTypecast?.value?.type?.isByte==true)
562+
expressionEval.translateExpression(offsetTypecast.value)
563+
else
564+
expressionEval.translateExpression(ptrWithOffset.right)
565+
addToResult(result, tr, tr.resultReg, -1)
566+
val ptrName = (ptrWithOffset.left as PtIdentifier).name
567+
addInstr(result, IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=valueRegister, reg2=tr.resultReg, labelSymbol = ptrName), null)
568+
return result
569+
}
570+
}
571+
572+
val tr = expressionEval.translateExpression(memory!!.address)
573+
val addressReg = tr.resultReg
578574
addToResult(result, tr, tr.resultReg, -1)
579-
val ptrName = (ptrWithOffset.left as PtIdentifier).name
580-
addInstr(result, IRInstruction(Opcode.STOREIX, IRDataType.BYTE, reg1=valueRegister, reg2=tr.resultReg, labelSymbol = ptrName), null)
575+
addInstr(result, IRInstruction(Opcode.STOREI, targetDt, reg1=valueRegister, reg2=addressReg), null)
581576
return result
582577
}
578+
579+
return result
583580
}
581+
array != null -> {
582+
val eltSize = codeGen.program.memsizer.memorySize(array!!.type, null)
583+
val variable = array!!.variable
584+
if(variable==null)
585+
translateRegularAssignPointerIndexed(result, array!!.pointerderef!!, eltSize, array!!, zero, targetDt, valueRegister, valueFpRegister)
586+
else if(variable.type.isPointer)
587+
assignToIndexedSimplePointer(result, variable, eltSize, array!!, zero, targetDt, valueRegister, valueFpRegister)
588+
else
589+
translateRegularAssignArrayIndexed(result, variable.name, eltSize, array!!, zero, targetDt, valueRegister, valueFpRegister)
590+
return result
591+
}
592+
pointerDeref != null -> {
593+
val (addressReg, offset) = codeGen.evaluatePointerAddressIntoReg(result, pointerDeref!!)
594+
val actualValueReg = if(pointerDeref!!.type.isFloat) valueFpRegister else valueRegister
595+
codeGen.storeValueAtPointersLocation(result, addressReg, offset, pointerDeref!!.type, zero, actualValueReg)
596+
return result
584597

585-
val tr = expressionEval.translateExpression(targetMemory.address)
586-
val addressReg = tr.resultReg
587-
addToResult(result, tr, tr.resultReg, -1)
588-
addInstr(result, IRInstruction(Opcode.STOREI, targetDt, reg1=valueRegister, reg2=addressReg), null)
589-
return result
598+
}
599+
indexedPointerDeref != null -> {
600+
TODO("assign to indexed pointer ${assignment.target.position} - for now, split up the assignment target using a temporary pointer variable")
601+
}
602+
else -> {
603+
throw AssemblyError("weird assigntarget")
604+
}
590605
}
591-
592-
return result
593606
}
594-
else if(targetPointerDeref!=null) {
595-
val (addressReg, offset) = codeGen.evaluatePointerAddressIntoReg(result, targetPointerDeref)
596-
val actualValueReg = if(targetPointerDeref.type.isFloat) valueFpRegister else valueRegister
597-
codeGen.storeValueAtPointersLocation(result, addressReg, offset, targetPointerDeref.type, zero, actualValueReg)
598-
return result
599-
}
600-
else
601-
throw AssemblyError("weird assigntarget")
602607
}
603608

604609
private fun assignToIndexedSimplePointer(

codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
8888
is PtFunctionCall -> translate(expr)
8989
is PtContainmentCheck -> translate(expr)
9090
is PtPointerDeref -> translate(expr)
91+
is PtArrayIndexedPointerDeref -> TODO("translate array indexed pointer deref expression $expr")
9192
is PtRange,
9293
is PtArray,
9394
is PtString -> throw AssemblyError("range/arrayliteral/string should no longer occur as expression")

codeOptimizers/src/prog8/optimizer/ConstantIdentifierReplacer.kt

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,13 @@ class VarConstantValueTypeAdjuster(
2828
if(decl.parent is AnonymousScope)
2929
throw FatalAstException("vardecl may no longer occur in anonymousscope ${decl.position}")
3030

31-
try {
32-
val declConstValue = decl.value?.constValue(program)
33-
if(declConstValue!=null && (decl.type== VarDeclType.VAR || decl.type==VarDeclType.CONST)
34-
&& declConstValue.type != decl.datatype.base) {
35-
if(decl.datatype.isInteger && declConstValue.type == BaseDataType.FLOAT) {
36-
// avoid silent float roundings
37-
errors.err("refused truncating of float to avoid loss of precision", decl.value!!.position)
38-
}
31+
val declConstValue = decl.value?.constValue(program)
32+
if(declConstValue!=null && (decl.type== VarDeclType.VAR || decl.type==VarDeclType.CONST)
33+
&& declConstValue.type != decl.datatype.base) {
34+
if(decl.datatype.isInteger && declConstValue.type == BaseDataType.FLOAT) {
35+
// avoid silent float roundings
36+
errors.err("refused truncating of float to avoid loss of precision", decl.value!!.position)
3937
}
40-
} catch (x: UndefinedSymbolError) {
41-
errors.err(x.message, x.position)
4238
}
4339

4440
// replace variables by constants, if possible
@@ -313,41 +309,36 @@ internal class ConstantIdentifierReplacer(
313309
if(!dt.isKnown || !dt.isNumeric && !dt.isBool)
314310
return noModifications
315311

316-
try {
317-
val cval = identifier.constValue(program) ?: return noModifications
318-
val arrayIdx = identifier.parent as? ArrayIndexedExpression
319-
if(arrayIdx!=null && cval.type.isNumeric) {
320-
// special case when the identifier is used as a pointer var
321-
// var = constpointer[x] --> var = @(constvalue+x) [directmemoryread]
322-
// constpointer[x] = var -> @(constvalue+x) [directmemorywrite] = var
323-
val add = BinaryExpression(NumericLiteral(cval.type, cval.number, identifier.position), "+", arrayIdx.indexer.indexExpr, identifier.position)
324-
return if(arrayIdx.parent is AssignTarget) {
325-
val memwrite = DirectMemoryWrite(add, identifier.position)
326-
val assignTarget = AssignTarget(null, null, memwrite, null, false, position = identifier.position)
327-
listOf(IAstModification.ReplaceNode(arrayIdx.parent, assignTarget, arrayIdx.parent.parent))
328-
} else {
329-
val memread = DirectMemoryRead(add, identifier.position)
330-
listOf(IAstModification.ReplaceNode(arrayIdx, memread, arrayIdx.parent))
331-
}
312+
val cval = identifier.constValue(program) ?: return noModifications
313+
val arrayIdx = identifier.parent as? ArrayIndexedExpression
314+
if(arrayIdx!=null && cval.type.isNumeric) {
315+
// special case when the identifier is used as a pointer var
316+
// var = constpointer[x] --> var = @(constvalue+x) [directmemoryread]
317+
// constpointer[x] = var -> @(constvalue+x) [directmemorywrite] = var
318+
val add = BinaryExpression(NumericLiteral(cval.type, cval.number, identifier.position), "+", arrayIdx.indexer.indexExpr, identifier.position)
319+
return if(arrayIdx.parent is AssignTarget) {
320+
val memwrite = DirectMemoryWrite(add, identifier.position)
321+
val assignTarget = AssignTarget(null, null, memwrite, null, false, position = identifier.position)
322+
listOf(IAstModification.ReplaceNode(arrayIdx.parent, assignTarget, arrayIdx.parent.parent))
323+
} else {
324+
val memread = DirectMemoryRead(add, identifier.position)
325+
listOf(IAstModification.ReplaceNode(arrayIdx, memread, arrayIdx.parent))
332326
}
333-
when {
334-
cval.type.isNumericOrBool -> {
335-
if(parent is AddressOf)
336-
return noModifications // cannot replace the identifier INSIDE the addr-of here, let's do it later.
337-
return listOf(
338-
IAstModification.ReplaceNode(
339-
identifier,
340-
NumericLiteral(cval.type, cval.number, identifier.position),
341-
identifier.parent
342-
)
327+
}
328+
when {
329+
cval.type.isNumericOrBool -> {
330+
if(parent is AddressOf)
331+
return noModifications // cannot replace the identifier INSIDE the addr-of here, let's do it later.
332+
return listOf(
333+
IAstModification.ReplaceNode(
334+
identifier,
335+
NumericLiteral(cval.type, cval.number, identifier.position),
336+
identifier.parent
343337
)
344-
}
345-
cval.type.isPassByRef -> throw InternalCompilerException("pass-by-reference type should not be considered a constant")
346-
else -> return noModifications
338+
)
347339
}
348-
} catch (x: UndefinedSymbolError) {
349-
errors.err(x.message, x.position)
350-
return noModifications
340+
cval.type.isPassByRef -> throw InternalCompilerException("pass-by-reference type should not be considered a constant")
341+
else -> return noModifications
351342
}
352343
}
353344

0 commit comments

Comments
 (0)