boolean vs byte cast fixing, and pointervar error

This commit is contained in:
Irmen de Jong 2023-02-02 00:01:36 +01:00
parent a5ca08f33d
commit 201b77d5b6
6 changed files with 77 additions and 15 deletions

View File

@ -113,10 +113,10 @@ class AsmGen(
out(" lda $sourceName")
return sourceName
}
is PtVariable -> {
is PtVariable, is PtMemMapped -> {
val sourceName = asmVariableName(pointervar)
if (isTargetCpu(CpuType.CPU65c02)) {
return if (allocator.isZpVar(target.scopedName.split('.'))) { // TODO dotted string
return if (allocator.isZpVar((target as PtNamedNode).scopedName.split('.'))) { // TODO dotted string
// pointervar is already in the zero page, no need to copy
out(" lda ($sourceName)")
sourceName
@ -130,7 +130,7 @@ class AsmGen(
"P8ZP_SCRATCH_W1"
}
} else {
return if (allocator.isZpVar(target.scopedName.split('.'))) { // TODO dotted string
return if (allocator.isZpVar((target as PtNamedNode).scopedName.split('.'))) { // TODO dotted string
// pointervar is already in the zero page, no need to copy
out(" ldy #0 | lda ($sourceName),y")
sourceName
@ -146,7 +146,7 @@ class AsmGen(
}
}
}
else -> throw AssemblyError("invalid pointervar")
else -> throw AssemblyError("invalid pointervar $target")
}
}
@ -995,7 +995,7 @@ $repeatLabel lda $counterVar
out(" lda ${asmSymbolName(pointervar)},y")
return true
}
is PtVariable, null -> {
is IPtVariable, null -> {
if(write) {
if(pointervar!=null && isZpVar(pointervar)) {
val saveA = evalBytevalueWillClobberA(ptrAndIndex.second)
@ -1045,7 +1045,7 @@ $repeatLabel lda $counterVar
}
return true
}
else -> throw AssemblyError("invalid pointervar")
else -> throw AssemblyError("invalid pointervar $pointervar")
}
}
}

View File

@ -162,3 +162,27 @@ internal fun IPtSubroutine.returnsWhatWhere(): List<Pair<DataType, RegisterOrSta
}
}
}
internal fun PtExpression.clone(): PtExpression {
fun withClonedChildrenFrom(orig: PtExpression, clone: PtExpression): PtExpression {
orig.children.forEach { clone.add((it as PtExpression).clone()) }
return clone
}
when(this) {
is PtAddressOf -> return withClonedChildrenFrom(this, PtAddressOf(position))
is PtArray -> return withClonedChildrenFrom(this, PtArray(type, position))
is PtArrayIndexer -> return withClonedChildrenFrom(this, PtArrayIndexer(type, position))
is PtBinaryExpression -> return withClonedChildrenFrom(this, PtBinaryExpression(operator, type, position))
is PtBuiltinFunctionCall -> return withClonedChildrenFrom(this, PtBuiltinFunctionCall(name, void, hasNoSideEffects, type, position))
is PtContainmentCheck -> return withClonedChildrenFrom(this, PtContainmentCheck(position))
is PtFunctionCall -> return withClonedChildrenFrom(this, PtFunctionCall(name, void, type, position))
is PtIdentifier -> return withClonedChildrenFrom(this, PtIdentifier(name, type, position))
is PtMachineRegister -> return withClonedChildrenFrom(this, PtMachineRegister(register, type, position))
is PtMemoryByte -> return withClonedChildrenFrom(this, PtMemoryByte(position))
is PtNumber -> return withClonedChildrenFrom(this, PtNumber(type, number, position))
is PtPrefix -> return withClonedChildrenFrom(this, PtPrefix(operator, type, position))
is PtRange -> return withClonedChildrenFrom(this, PtRange(type, position))
is PtString -> return withClonedChildrenFrom(this, PtString(value, encoding, position))
is PtTypeCast -> return withClonedChildrenFrom(this, PtTypeCast(type, position))
}
}

View File

@ -363,11 +363,12 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignTrue.add(assignment)
val assignFalse = PtNodeGroup()
val ifelse = PtIfElse(assign.position)
val exprClone = arrayOf(expr).clone()[0]
require(exprClone !== expr) // TODO remove check if it works
ifelse.add(expr)
val exprClone = PtBinaryExpression(expr.operator, expr.type, expr.position)
expr.children.forEach { exprClone.children.add(it) } // doesn't seem to need a deep clone
ifelse.add(exprClone)
ifelse.add(assignTrue)
ifelse.add(assignFalse)
ifelse.parent = expr.parent
asmgen.translate(ifelse)
return true
}

View File

@ -136,12 +136,8 @@ internal fun Program.checkIdentifiers(errors: IErrorReporter, options: Compilati
internal fun Program.variousCleanups(errors: IErrorReporter, options: CompilationOptions) {
val process = VariousCleanups(this, errors, options)
process.visit(this)
if(errors.noErrors()) {
if(process.applyModifications()>0) {
process.visit(this)
if(errors.noErrors())
process.applyModifications()
}
while(errors.noErrors() && process.applyModifications()>0) { // TODO limit the number of cycles here?
process.visit(this)
}
}

View File

@ -62,6 +62,11 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
}
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
if(assignment.target isSameAs assignment.value) {
// remove assignment to self
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
}
// remove duplicated assignments, but not if it's a memory mapped IO register
val isIO = try {
assignment.target.isIOAddress(options.compTarget.machine)

View File

@ -120,6 +120,42 @@ main {
right3.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
}
test("simple logical with bool no typecast") {
val text="""
main {
bool bb
sub start() {
bb = bb and 123
}
}"""
val result = compileText(C64Target(), true, text, writeAssembly = true)!!
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 2
val assignValue = (stmts[0] as Assignment).value as BinaryExpression
assignValue.left shouldBe instanceOf<IdentifierReference>()
assignValue.operator shouldBe "&"
(assignValue.right as NumericLiteral).number shouldBe 1.0
}
test("simple logical with byte instead of bool ok with typecasting") {
val text="""
main {
ubyte ubb
sub start() {
ubb = ubb and 123
}
}"""
val result = compileText(C64Target(), true, text, writeAssembly = true)!!
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 2
val assignValue = (stmts[0] as Assignment).value as BinaryExpression
assignValue.left shouldBe instanceOf<BinaryExpression>() // as a result of the cast to boolean
assignValue.operator shouldBe "&"
(assignValue.right as NumericLiteral).number shouldBe 1.0
}
test("logical with byte instead of bool") {
val text="""
%import textio