|
2 | 2 |
|
3 | 3 | import com.google.common.collect.Lists; |
4 | 4 | import de.peeeq.wurstio.TimeTaker; |
| 5 | +import de.peeeq.wurstscript.WurstOperator; |
5 | 6 | import de.peeeq.wurstscript.WLogger; |
6 | 7 | import de.peeeq.wurstscript.intermediatelang.optimizer.BranchMerger; |
7 | 8 | import de.peeeq.wurstscript.intermediatelang.optimizer.ConstantAndCopyPropagation; |
@@ -201,10 +202,34 @@ private List<ImExpr> collectSideEffects(ImExpr expr, SideEffectAnalyzer analyzer |
201 | 202 | if (expr == null) { |
202 | 203 | return Collections.emptyList(); |
203 | 204 | } |
| 205 | + if (mayTrapAtRuntime(expr)) { |
| 206 | + return Collections.singletonList(expr); |
| 207 | + } |
204 | 208 | if (analyzer.hasObservableSideEffects(expr, func -> func.isNative() |
205 | 209 | && UselessFunctionCallsRemover.isFunctionWithoutSideEffect(func.getName()))) { |
206 | 210 | return Collections.singletonList(expr); |
207 | 211 | } |
208 | 212 | return Collections.emptyList(); |
209 | 213 | } |
| 214 | + |
| 215 | + private boolean mayTrapAtRuntime(Element elem) { |
| 216 | + if (elem instanceof ImOperatorCall) { |
| 217 | + ImOperatorCall opCall = (ImOperatorCall) elem; |
| 218 | + WurstOperator op = opCall.getOp(); |
| 219 | + if ((op == WurstOperator.DIV_INT || op == WurstOperator.MOD_INT) && opCall.getArguments().size() >= 2) { |
| 220 | + ImExpr denominator = opCall.getArguments().get(1); |
| 221 | + // Preserve integer div/mod unless denominator is provably non-zero. |
| 222 | + if (!(denominator instanceof ImIntVal) || ((ImIntVal) denominator).getValI() == 0) { |
| 223 | + return true; |
| 224 | + } |
| 225 | + } |
| 226 | + } |
| 227 | + for (int i = 0; i < elem.size(); i++) { |
| 228 | + Element child = elem.get(i); |
| 229 | + if (mayTrapAtRuntime(child)) { |
| 230 | + return true; |
| 231 | + } |
| 232 | + } |
| 233 | + return false; |
| 234 | + } |
210 | 235 | } |
0 commit comments