make uword xx = 1<<shift into a word shifting

This commit is contained in:
Irmen de Jong 2022-11-16 01:39:34 +01:00
parent 922033c1b2
commit d8e87bd881
4 changed files with 72 additions and 1 deletions

View File

@ -47,6 +47,36 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
val rightCv = expr.right.constValue(program)
if(leftDt.isKnown && rightDt.isKnown) {
if(expr.operator=="<<" && leftDt.isBytes) {
// uword ww = 1 << shift --> make the '1' a word constant
val leftConst = expr.left.constValue(program)
if(leftConst!=null) {
val leftConstAsWord =
if(leftDt.istype(DataType.UBYTE))
NumericLiteral(DataType.UWORD, leftConst.number, leftConst.position)
else
NumericLiteral(DataType.WORD, leftConst.number, leftConst.position)
val modifications = mutableListOf<IAstModification>()
if (parent is Assignment) {
if (parent.target.inferType(program).isWords) {
modifications += IAstModification.ReplaceNode(expr.left, leftConstAsWord, expr)
if(rightDt.isBytes)
modifications += IAstModification.ReplaceNode(expr.right, TypecastExpression(expr.right, leftConstAsWord.type, true, expr.right.position), expr)
}
} else if (parent is TypecastExpression && parent.type == DataType.UWORD && parent.parent is Assignment) {
val assign = parent.parent as Assignment
if (assign.target.inferType(program).isWords) {
modifications += IAstModification.ReplaceNode(expr.left, leftConstAsWord, expr)
if(rightDt.isBytes)
modifications += IAstModification.ReplaceNode(expr.right, TypecastExpression(expr.right, leftConstAsWord.type, true, expr.right.position), expr)
}
}
if(modifications.isNotEmpty())
return modifications
}
}
if(expr.operator in LogicalOperators && leftDt.isInteger && rightDt.isInteger) {
// see if any of the operands needs conversion to bool
val modifications = mutableListOf<IAstModification>()

View File

@ -3,13 +3,19 @@ package prog8tests.ast
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.types.instanceOf
import prog8.ast.IFunctionCall
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteral
import prog8.ast.expressions.StringLiteral
import prog8.ast.statements.Assignment
import prog8.ast.statements.InlineAssembly
import prog8.ast.statements.VarDecl
import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.code.target.C64Target
import prog8.compiler.printProgram
import prog8tests.helpers.compileText
class TestVarious: FunSpec({
@ -129,5 +135,31 @@ main {
}"""
compileText(C64Target(), optimize=false, src, writeAssembly=false) shouldNotBe null
}
test("bitshift left of const byte converted to word") {
val src="""
main {
sub start() {
ubyte shift = 10
uword value = 1<<shift
value++
value = 1<<shift
value++
}
}"""
val result = compileText(C64Target(), optimize=false, src, writeAssembly=false)!!
printProgram(result.program)
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 7
val assign1expr = (stmts[3] as Assignment).value as BinaryExpression
val assign2expr = (stmts[5] as Assignment).value as BinaryExpression
assign1expr.operator shouldBe "<<"
val leftval1 = assign1expr.left.constValue(result.program)!!
leftval1.type shouldBe DataType.UWORD
leftval1.number shouldBe 1.0
val leftval2 = assign2expr.left.constValue(result.program)!!
leftval2.type shouldBe DataType.UWORD
leftval2.number shouldBe 1.0
}
})

View File

@ -3,7 +3,6 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- make it so that uword xx = <byte constant> <op> expr is treated as <word constant> <op> <expr> instead (or inverse order)
- ir/vm: allow label in block scope
- regression test the various projects
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)

View File

@ -7,6 +7,16 @@ alsostart:
sub start() {
internalstart:
ubyte fact = 10
uword ww = 1<<fact
txt.print_uw(ww)
txt.nl()
ww++
ww = 1<<fact
txt.print_uw(ww)
txt.nl()
txt.nl()
txt.print_uwhex(start, true)
txt.nl()
txt.print_uwhex(alsostart, true)