From 6830e15b4e657f21c62767fac15d31daf085c3dc Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 29 Oct 2022 15:23:39 +0200 Subject: [PATCH] print warning when bit shifts are too large and result in 0. #83 --- .../src/prog8/optimizer/ExpressionSimplifier.kt | 8 +++++++- codeOptimizers/src/prog8/optimizer/Extensions.kt | 4 ++-- compiler/src/prog8/compiler/Compiler.kt | 2 +- .../astprocessing/BeforeAsmTypecastCleaner.kt | 14 ++++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt index d7dec4d8b..18290b502 100644 --- a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt @@ -20,7 +20,9 @@ import kotlin.math.pow // TODO add more peephole expression optimizations? Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html -class ExpressionSimplifier(private val program: Program, private val compTarget: ICompilationTarget) : AstWalker() { +class ExpressionSimplifier(private val program: Program, + private val errors: IErrorReporter, + private val compTarget: ICompilationTarget) : AstWalker() { private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet() private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet() @@ -586,11 +588,13 @@ class ExpressionSimplifier(private val program: Program, private val compTarget: when (val targetDt = targetIDt.getOr(DataType.UNDEFINED)) { DataType.UBYTE, DataType.BYTE -> { if (amount >= 8) { + errors.warn("shift always results in 0", expr.position) return NumericLiteral(targetDt, 0.0, expr.position) } } DataType.UWORD, DataType.WORD -> { if (amount >= 16) { + errors.warn("shift always results in 0", expr.position) return NumericLiteral(targetDt, 0.0, expr.position) } else if(amount==8) { @@ -625,6 +629,7 @@ class ExpressionSimplifier(private val program: Program, private val compTarget: when (idt.getOr(DataType.UNDEFINED)) { DataType.UBYTE -> { if (amount >= 8) { + errors.warn("shift always results in 0", expr.position) return NumericLiteral.optimalInteger(0, expr.position) } } @@ -636,6 +641,7 @@ class ExpressionSimplifier(private val program: Program, private val compTarget: } DataType.UWORD -> { if (amount >= 16) { + errors.warn("shift always results in 0", expr.position) return NumericLiteral.optimalInteger(0, expr.position) } else if(amount==8) { diff --git a/codeOptimizers/src/prog8/optimizer/Extensions.kt b/codeOptimizers/src/prog8/optimizer/Extensions.kt index 78b9478fe..cb76ffa30 100644 --- a/codeOptimizers/src/prog8/optimizer/Extensions.kt +++ b/codeOptimizers/src/prog8/optimizer/Extensions.kt @@ -60,8 +60,8 @@ fun Program.inlineSubroutines(): Int { return inliner.applyModifications() } -fun Program.simplifyExpressions(target: ICompilationTarget) : Int { - val opti = ExpressionSimplifier(this, target) +fun Program.simplifyExpressions(errors: IErrorReporter, target: ICompilationTarget) : Int { + val opti = ExpressionSimplifier(this, errors, target) opti.visit(this) return opti.applyModifications() } diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index be28c90a6..ca2613bea 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -361,7 +361,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e remover.applyModifications() while (true) { // keep optimizing expressions and statements until no more steps remain - val optsDone1 = program.simplifyExpressions(compTarget) + val optsDone1 = program.simplifyExpressions(errors, compTarget) val optsDone2 = program.splitBinaryExpressions(compilerOptions) val optsDone3 = program.optimizeStatements(errors, functions, compTarget) val optsDone4 = program.inlineSubroutines() diff --git a/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt b/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt index 4ba484248..3eeebfff3 100644 --- a/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt +++ b/compiler/src/prog8/compiler/astprocessing/BeforeAsmTypecastCleaner.kt @@ -129,4 +129,18 @@ internal class BeforeAsmTypecastCleaner(val program: Program, } return noModifications } + + override fun after(expr: BinaryExpression, parent: Node): Iterable { + if(expr.operator=="<<" || expr.operator==">>") { + val shifts = expr.right.constValue(program) + if(shifts!=null) { + val dt = expr.left.inferType(program) + if(dt.istype(DataType.UBYTE) && shifts.number>=8.0) + errors.warn("shift always results in 0", expr.position) + if(dt.istype(DataType.UWORD) && shifts.number>=16.0) + errors.warn("shift always results in 0", expr.position) + } + } + return noModifications + } } \ No newline at end of file