mirror of
https://github.com/irmen/prog8.git
synced 2025-08-09 03:25:24 +00:00
fix compiler error and codegen fault on signed value bitwise operation
This commit is contained in:
@@ -157,6 +157,12 @@ class UnusedCodeRemover(private val program: Program,
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||||
|
if(assignment.target isSameAs assignment.value)
|
||||||
|
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||||
|
return noModifications
|
||||||
|
}
|
||||||
|
|
||||||
private fun deduplicateAssignments(statements: List<Statement>, scope: IStatementContainer): List<IAstModification> {
|
private fun deduplicateAssignments(statements: List<Statement>, scope: IStatementContainer): List<IAstModification> {
|
||||||
// removes 'duplicate' assignments that assign the same target directly after another, unless it is a function call
|
// removes 'duplicate' assignments that assign the same target directly after another, unless it is a function call
|
||||||
val linesToRemove = mutableListOf<Assignment>()
|
val linesToRemove = mutableListOf<Assignment>()
|
||||||
|
@@ -480,7 +480,9 @@ internal class AstChecker(private val program: Program,
|
|||||||
errors.err("target datatype is unknown", assignment.target.position)
|
errors.err("target datatype is unknown", assignment.target.position)
|
||||||
// otherwise, another error about missing symbol is already reported.
|
// otherwise, another error about missing symbol is already reported.
|
||||||
} else {
|
} else {
|
||||||
errors.err("type of value $valueDt doesn't match target $targetDt", assignment.value.position)
|
// allow bitwise operations on different types as long as the size is the same
|
||||||
|
if (!((assignment.value as? BinaryExpression)?.operator in BitwiseOperators && targetDt.isBytes && valueDt.isBytes || targetDt.isWords && valueDt.isWords))
|
||||||
|
errors.err("type of value $valueDt doesn't match target $targetDt", assignment.value.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1607,8 +1609,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
else if(sourceDatatype== DataType.FLOAT && targetDatatype in IntegerDatatypes)
|
else if(sourceDatatype== DataType.FLOAT && targetDatatype in IntegerDatatypes)
|
||||||
errors.err("cannot assign float to ${targetDatatype.name.lowercase()}; possible loss of precision. Suggestion: round the value or revert to integer arithmetic", position)
|
errors.err("cannot assign float to ${targetDatatype.name.lowercase()}; possible loss of precision. Suggestion: round the value or revert to integer arithmetic", position)
|
||||||
else {
|
else {
|
||||||
if(targetDatatype!=DataType.UWORD && sourceDatatype !in PassByReferenceDatatypes)
|
if(targetDatatype!=DataType.UWORD && sourceDatatype !in PassByReferenceDatatypes) {
|
||||||
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
// allow bitwise operations on different types as long as the size is the same
|
||||||
|
if (!((sourceValue as? BinaryExpression)?.operator in BitwiseOperators && targetDatatype.equalsSize(sourceDatatype)))
|
||||||
|
errors.err("type of value $sourceDatatype doesn't match target $targetDatatype", position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@@ -93,6 +93,11 @@ internal class BeforeAsmAstChanger(val program: Program,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if(binExpr.left isSameAs assignment.target)
|
||||||
|
return noModifications
|
||||||
|
val typeCast = binExpr.left as? TypecastExpression
|
||||||
|
if(typeCast!=null && typeCast.expression isSameAs assignment.target)
|
||||||
|
return noModifications
|
||||||
val sourceDt = binExpr.left.inferType(program).getOrElse { throw AssemblyError("unknown dt") }
|
val sourceDt = binExpr.left.inferType(program).getOrElse { throw AssemblyError("unknown dt") }
|
||||||
val (_, left) = binExpr.left.typecastTo(assignment.target.inferType(program).getOrElse { throw AssemblyError(
|
val (_, left) = binExpr.left.typecastTo(assignment.target.inferType(program).getOrElse { throw AssemblyError(
|
||||||
"unknown dt"
|
"unknown dt"
|
||||||
|
@@ -133,9 +133,16 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
|||||||
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
||||||
}
|
}
|
||||||
if(leftDt istype DataType.WORD && rightDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
if(leftDt istype DataType.WORD && rightDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
||||||
// cast left to unsigned
|
// cast left to unsigned word. Cast right to unsigned word if it is ubyte
|
||||||
val cast = TypecastExpression(expr.left, rightDt.getOr(DataType.UNDEFINED), true, expr.left.position)
|
val mods = mutableListOf<IAstModification>()
|
||||||
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
val cast = TypecastExpression(expr.left, DataType.UWORD, true, expr.left.position)
|
||||||
|
mods += IAstModification.ReplaceNode(expr.left, cast, expr)
|
||||||
|
if(rightDt istype DataType.UBYTE) {
|
||||||
|
mods += IAstModification.ReplaceNode(expr.right,
|
||||||
|
TypecastExpression(expr.right, DataType.UWORD, true, expr.right.position),
|
||||||
|
expr)
|
||||||
|
}
|
||||||
|
return mods
|
||||||
}
|
}
|
||||||
if(rightDt istype DataType.BYTE && leftDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
if(rightDt istype DataType.BYTE && leftDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
||||||
// cast right to unsigned
|
// cast right to unsigned
|
||||||
@@ -143,9 +150,16 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
|
|||||||
return listOf(IAstModification.ReplaceNode(expr.right, cast, expr))
|
return listOf(IAstModification.ReplaceNode(expr.right, cast, expr))
|
||||||
}
|
}
|
||||||
if(rightDt istype DataType.WORD && leftDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
if(rightDt istype DataType.WORD && leftDt.oneOf(DataType.UBYTE, DataType.UWORD)) {
|
||||||
// cast right to unsigned
|
// cast right to unsigned word. Cast left to unsigned word if it is ubyte
|
||||||
val cast = TypecastExpression(expr.right, leftDt.getOr(DataType.UNDEFINED), true, expr.right.position)
|
val mods = mutableListOf<IAstModification>()
|
||||||
return listOf(IAstModification.ReplaceNode(expr.right, cast, expr))
|
val cast = TypecastExpression(expr.right, DataType.UWORD, true, expr.right.position)
|
||||||
|
mods += IAstModification.ReplaceNode(expr.right, cast, expr)
|
||||||
|
if(leftDt istype DataType.UBYTE) {
|
||||||
|
mods += IAstModification.ReplaceNode(expr.left,
|
||||||
|
TypecastExpression(expr.left, DataType.UWORD, true, expr.left.position),
|
||||||
|
expr)
|
||||||
|
}
|
||||||
|
return mods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,18 +4,32 @@
|
|||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
ubyte ub = 123
|
||||||
|
byte bb = -100
|
||||||
|
uword uw = 12345
|
||||||
|
word ww = -12345
|
||||||
|
|
||||||
uword table = memory("table", 100, 0)
|
ub |= 63 ; vm/c64 ok (127)
|
||||||
|
bb |= 63 ; vm/c64 ok (-65)
|
||||||
|
uw |= 63 ; vm/c64 ok (12351)
|
||||||
|
ww |= 63 ; vm/c64 ok (-12289)
|
||||||
|
|
||||||
ubyte pos
|
txt.print_ub(ub)
|
||||||
for pos in 0 to 7 {
|
txt.spc()
|
||||||
pokew(table + 64 + pos*2, ($000a-pos)*200)
|
txt.print_b(bb)
|
||||||
}
|
txt.spc()
|
||||||
|
txt.print_uw(uw)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_w(ww)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
for pos in 0 to 7 {
|
uw |= 16384 ; vm/c64 ok (28735)
|
||||||
txt.print_uw(peekw(table+64+pos*2))
|
ww |= 8192 ; vm/c64 ok (-4097)
|
||||||
txt.nl()
|
|
||||||
}
|
txt.print_uw(uw)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_w(ww)
|
||||||
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user