22
33import de .peeeq .wurstscript .WurstOperator ;
44import de .peeeq .wurstscript .jassIm .*;
5+ import de .peeeq .wurstscript .translation .imoptimizer .UselessFunctionCallsRemover ;
56import de .peeeq .wurstscript .translation .imoptimizer .OptimizerPass ;
67import de .peeeq .wurstscript .translation .imtranslation .ImTranslator ;
78
89import java .util .ArrayList ;
10+ import java .util .HashSet ;
911import java .util .IdentityHashMap ;
1012import java .util .Objects ;
1113import java .util .Set ;
@@ -21,12 +23,14 @@ public class DispatchCheckDeduplicator implements OptimizerPass {
2123
2224 private int rewrites ;
2325 private final IdentityHashMap <ImFunction , IdentityHashMap <ImVar , Boolean >> mayWriteTypeIdMemo = new IdentityHashMap <>();
26+ private SideEffectAnalyzer sideEffectAnalyzer ;
2427
2528 @ Override
2629 public int optimize (ImTranslator trans ) {
2730 rewrites = 0 ;
2831 mayWriteTypeIdMemo .clear ();
2932 ImProg prog = trans .getImProg ();
33+ sideEffectAnalyzer = new SideEffectAnalyzer (prog );
3034 for (ImFunction f : prog .getFunctions ()) {
3135 optimizeStmts (f .getBody ());
3236 }
@@ -107,9 +111,6 @@ private boolean invalidatesGuard(ImStmt s, GuardPattern guard) {
107111 }
108112 if (s instanceof ImFunctionCall ) {
109113 ImFunction f = ((ImFunctionCall ) s ).getFunc ();
110- if (isKnownNonMutatingFunction (f )) {
111- return false ;
112- }
113114 return mayWriteTypeId (f , guard .failedCond .typeIdVar );
114115 }
115116 if (s instanceof ImMethodCall ) {
@@ -130,72 +131,44 @@ private boolean mayWriteTypeId(ImFunction f, ImVar typeIdVar) {
130131 if (f == null ) {
131132 return true ;
132133 }
134+ if (f .isNative ()) {
135+ return !UselessFunctionCallsRemover .isFunctionWithoutSideEffect (f .getName ());
136+ }
137+ if (f .isExtern ()) {
138+ return true ;
139+ }
133140 IdentityHashMap <ImVar , Boolean > byTypeId = mayWriteTypeIdMemo .computeIfAbsent (f , k -> new IdentityHashMap <>());
134141 Boolean memo = byTypeId .get (typeIdVar );
135142 if (memo != null ) {
136143 return memo ;
137144 }
138- boolean result = mayWriteTypeIdImpl (f , typeIdVar , java . util . Collections . newSetFromMap ( new IdentityHashMap <>()) );
145+ boolean result = mayWriteTypeIdUsingAnalysis (f , typeIdVar );
139146 byTypeId .put (typeIdVar , result );
140147 return result ;
141148 }
142149
143- private boolean isKnownNonMutatingFunction (ImFunction f ) {
144- if (f == null ) return false ;
145- String n = f .getName ();
146- return "println" .equals (n )
147- || "print" .equals (n )
148- || "I2S" .equals (n )
149- || "R2S" .equals (n )
150- || "BJDebugMsg" .equals (n );
151- }
152-
153- private boolean mayWriteTypeIdImpl (ImFunction f , ImVar typeIdVar , Set <ImFunction > visiting ) {
154- if (f .isNative ()) {
155- return true ;
156- }
157- if (!visiting .add (f )) {
158- return true ;
159- }
160- final boolean [] writes = {false };
161- f .accept (new ImFunction .DefaultVisitor () {
162- @ Override
163- public void visit (ImSet e ) {
164- super .visit (e );
165- ImLExpr left = e .getLeft ();
166- if (left instanceof ImVarArrayAccess && ((ImVarArrayAccess ) left ).getVar () == typeIdVar ) {
167- writes [0 ] = true ;
168- } else if (left instanceof ImVarAccess && ((ImVarAccess ) left ).getVar () == typeIdVar ) {
169- writes [0 ] = true ;
170- } else if (left instanceof ImMemberAccess && ((ImMemberAccess ) left ).getVar () == typeIdVar ) {
171- writes [0 ] = true ;
172- }
150+ private boolean mayWriteTypeIdUsingAnalysis (ImFunction f , ImVar typeIdVar ) {
151+ Set <ImFunction > reachable = new HashSet <>();
152+ reachable .add (f );
153+ reachable .addAll (sideEffectAnalyzer .calledFunctions (f .getBody ()));
154+ for (ImFunction g : reachable ) {
155+ if (g == null ) {
156+ return true ;
173157 }
174-
175- @ Override
176- public void visit (ImFunctionCall e ) {
177- super .visit (e );
178- if (!writes [0 ] && mayWriteTypeIdImpl (e .getFunc (), typeIdVar , visiting )) {
179- writes [0 ] = true ;
180- }
158+ if (g .isExtern ()) {
159+ return true ;
181160 }
182-
183- @ Override
184- public void visit (ImMethodCall e ) {
185- super .visit (e );
186- if (!writes [0 ] && mayWriteTypeIdImpl (e .getMethod ().getImplementation (), typeIdVar , visiting )) {
187- writes [0 ] = true ;
161+ if (g .isNative ()) {
162+ if (!UselessFunctionCallsRemover .isFunctionWithoutSideEffect (g .getName ())) {
163+ return true ;
188164 }
165+ continue ;
189166 }
190-
191- @ Override
192- public void visit (ImDealloc e ) {
193- super .visit (e );
194- writes [0 ] = true ;
167+ if (sideEffectAnalyzer .directlySetVariables (g .getBody ()).contains (typeIdVar )) {
168+ return true ;
195169 }
196- });
197- visiting .remove (f );
198- return writes [0 ];
170+ }
171+ return false ;
199172 }
200173
201174 private GuardPattern extractDispatchGuard (ImStmt stmt ) {
0 commit comments