public void AddSpecPoint(SpecPoint sp) { if (f_container.ContainsKey(sp.P) == false) { f_container.Add(sp.P, new List<SpecPoint>()); } f_container[sp.P].Add(sp); }
private static FunctionSpecializationResult SpecializeFunction( ILFunction function, Dictionary<string, object> pars, List<string> forceDynamic) { var source = new StringBuilder(1024 * 1024); int LabelId = 1; var visited = new SpecPointContainer(); var q = new Queue<SpecPoint>(); var initEnv = new AbstractEnvironment(); foreach (var kvp in pars) { initEnv.SetValue(kvp.Key, kvp.Value); } foreach (var kvp in function.LocalTypes) { if (pars.ContainsKey(kvp.Key)) continue; object val = null; if (kvp.Value.TypeEnum == L1Runtime.SyntaxTree.VariableTypeEnum.Integer) val = 0; if (kvp.Value.TypeEnum == L1Runtime.SyntaxTree.VariableTypeEnum.Bool) val = false; if (kvp.Value.TypeEnum == L1Runtime.SyntaxTree.VariableTypeEnum.Char) val = (char)0; initEnv.SetValue(kvp.Key, val); } foreach (var d in forceDynamic) { initEnv.SetValue(d, Dynamic.Value); } initEnv = _bindTimeAnalyze(function, initEnv); initEnv.Trace(); Dictionary<VariableType, List<string>> localVarsInfo = new Dictionary<VariableType, List<string>>(); foreach (var kvp in function.LocalTypes) { if (initEnv.IsDynamic(kvp.Key) && !function.Parameters.Contains(kvp.Key)) { if (localVarsInfo.ContainsKey(kvp.Value) == false) { localVarsInfo.Add(kvp.Value, new List<string>()); } localVarsInfo[kvp.Value].Add(kvp.Key); } } foreach (var kvp in localVarsInfo) { source.Append("\t"); source.Append(kvp.Key.ToCompileableString()); source.Append(" "); for (int i = 0; i < kvp.Value.Count; ++i) { source.Append(kvp.Value[i]); if (i != kvp.Value.Count - 1) source.Append(", "); } source.Append(";"); source.Append(System.Environment.NewLine); } foreach (var kvp in pars) { if (kvp.Value != Dynamic.Value && initEnv.IsDynamic(kvp.Key)) { source.Append("\t"); source.Append(function.LocalTypes[kvp.Key].ToCompileableString()); source.Append(" "); source.Append(kvp.Key); source.Append(" := "); source.Append(RenderConst(kvp.Value)); source.Append(";"); source.AppendLine(); } } source.Append("* Begin of function specialized body"); source.Append(System.Environment.NewLine); var initialSp = new SpecPoint { Env = initEnv, P = 1, L = LabelId++ } ; q.Enqueue(initialSp); initialSp.Env.Freeze(); visited.AddSpecPoint(initialSp); int operations = 0; var calls = new List<FunctionCallContainer>(); while (q.Count != 0) { operations++; var sp = q.Dequeue(); var env = sp.Env.Clone(); source.Append("L_"); source.Append(sp.L); source.Append(":"); source.Append(System.Environment.NewLine); bool stopped = false; int p = sp.P; while (!stopped) { var instr = function.Body[p - 1]; if (instr is ILExpression) { var expr = instr as ILExpression; stopped = SpecializeExpression(function, expr, env, source, calls); p++; } else if (instr is ILBranch) { var br = (instr as ILBranch); var condVar = br.Condition.Const.ToString(); if (env.IsDynamic(condVar)) { env.Freeze(); var succSp = visited.GetSpecPoint(br.SuccessJump, env); var failSp = visited.GetSpecPoint(br.FailJump, env); if (succSp == null) { succSp = new SpecPoint { Env = env, P = br.SuccessJump, L = LabelId++ }; q.Enqueue(succSp); visited.AddSpecPoint(succSp); } if (failSp == null) { failSp = new SpecPoint { Env = env, P = br.FailJump, L = LabelId++ }; q.Enqueue(failSp); visited.AddSpecPoint(failSp); } source.Append("\tif "); source.Append(condVar); source.Append(" then "); source.Append("goto "); source.Append("L_"); source.Append(succSp.L); source.Append(" else "); source.Append("goto "); source.Append("L_"); source.Append(failSp.L); source.Append(" end;"); source.Append(System.Environment.NewLine); stopped = true; } else { var cond = (bool)env.GetValue(condVar); if (cond) p = br.SuccessJump; else p = br.FailJump; } } else if (instr is ILGoto) { p = (instr as ILGoto).GoTo; } else if (instr is ILReturn) { var ret = (instr as ILReturn); if (ret.Return == null) { source.Append("\treturn;"); source.Append(System.Environment.NewLine); } else { source.Append("\treturn "); var retVar = ret.Return.Const.ToString(); if (env.IsDynamic(retVar)) { source.Append(retVar); } else { m_renderConst(source, env.GetValue(retVar)); } source.Append(";"); source.Append(System.Environment.NewLine); } stopped = true; } } //TODO: Stop if too big query and try with more dynamic variables if (operations >= MaximimOperations) { var ch = visited.GetMostChangeableVariables(); forceDynamic = forceDynamic.Union(ch).ToList(); var res1 = SpecializeFunction(function, pars, forceDynamic); return res1; } } source.Append("0").AppendLine(); //System.Console.WriteLine(source.ToString()); var r = new FunctionSpecializationResult { FunctionCallsNeedToResolve = calls, Source = source, Function = function, SpecializationRules = pars }; return r; }