CIL_newarr ParseNewarr(string label, string str) { CILScanner scanner = new CILScanner(fin, str); if(scanner.NextToken() != "newarr") throw new Exception("Unknown exception"); string elementType = scanner.NextToken(); switch(elementType) { case "[mscorlib]System.Int32": return new CIL_newarr(label, new CILVar_int32("")); case "[mscorlib]System.Int64": return new CIL_newarr(label, new CILVar_int64("")); case "[mscorlib]System.Double": return new CIL_newarr(label, new CILVar_double("")); default: throw new Exception("Unknown array type"); } }
CIL_ldfld ParseLdfld(string label, string str) { CILScanner scanner = new CILScanner(fin, str); if(scanner.NextToken() != "ldfld") throw new Exception("parse error: ldfld expected"); string fieldtype = scanner.NextToken(); if(fieldtype == "class") fieldtype = "class " + scanner.NextToken(); string classname = scanner.NextToken(); if(classname == "modreq") { scanner.NextToken(); // skip "[" scanner.NextToken(); // skip "mscorlib...IsVolatile" scanner.NextToken(); // skip "]" classname = scanner.NextToken(); } scanner.NextToken(); // skip "::"; string fieldname = scanner.NextToken(); if(nextAccessIsVolatile) { nextAccessIsVolatile = false; return new CIL_ldfld(label, fieldtype, classname, fieldname, true); } else return new CIL_ldfld(label, fieldtype, classname, fieldname, false); }
CILMethod ParseMethod(CILClass parentclass, string str) { // TODO: Need cleanup and reparse using Scanner List<string> argNames = new List<string>(); // count how much deep we are in a try block so that we // dont confuse } of the try-s as } of the method int try_counter = 0; int catch_counter; bool isStatic = false; CILScanner scanner = new CILScanner(fin, str); string st; string methodName = null; while(methodName == null) { st = scanner.NextToken(); if(st == "static") isStatic = true; if((st == "int32") || (st == "int64") || (st == "void") || (st == "float64") || (st == "bool")) methodName = scanner.NextToken(); else if(st == "class") { st = scanner.NextToken(); methodName = scanner.NextToken(); } } // skips "(" st = scanner.NextToken(); string methodSig = "("; int paramCount = 0; while(true) { st = scanner.NextToken(); if(st == ")") break; if(st != ",") { if(st == "class") { paramCount++; if(paramCount > 1) methodSig += ","; methodSig += scanner.NextToken(); } else { paramCount++; if(paramCount > 1) methodSig += ","; methodSig += st; } argNames.Add(scanner.NextToken()); } } methodSig += ")"; CILMethod themethod = parentclass.GetMethod(methodName, methodSig); themethod.SetArgumentNames(argNames); themethod.IsStatic = isStatic; currentMethod = themethod; // parse the method body bool done = false; str = GetNextLine(); // skips "{" while(done == false) { str = GetNextLine(); string[] ss = str.Split(' '); switch(ss[0]) { case ".maxstack": // TODO // can optimize stack allocation break; case ".try": // ignore exception handling // increase the try counter so that we know next } // is not end of the method try_counter++; GetNextLine(); // skip the { of the try block break; case "finally": try_counter++; GetNextLine(); // skip the { of the finally block break; case "catch": // ignore the whole catch block, find } to stop // first ignore the {, then count to find the end GetNextLine(); catch_counter = 1; while(true) { string sc = GetNextLine(); sc = sc.TrimStart(); if(sc.Length > 1) { if(sc[0] == '{') catch_counter++; else if(sc[0] == '}') catch_counter--; } if(catch_counter == 0) break; } break; case ".locals": bool endlocals = false; while(endlocals == false) { if(str.IndexOf("(") >= 0) str = str.Substring(str.IndexOf("(") + 1); string s2; if(str.IndexOf(",") >= 0) s2 = str.Substring(0, str.IndexOf(",")); else if(str.IndexOf(")") >= 0) { s2 = str.Substring(0, str.IndexOf(")")); endlocals = true; } else { Console.WriteLine("Unknown local variable declaration {0}", str); throw new Exception("Unknown local variable declaration"); } themethod.AddLocalVariable(ParseLocalVariable(s2)); if(endlocals == false) str = GetNextLine(); } break; case "}": if(try_counter == 0) done = true; else try_counter--; break; case ".entrypoint": program.EntryPoint = themethod; break; default: string label = str.Substring(0, str.IndexOf(":")); CILInstruction inst = ParseInstruction(label, str.Substring(10, str.Length - 10)); if(inst != null) themethod.AddInstruction(inst); break; } } return themethod; }
CIL_callvirt ParseCallvirt(string label, string str) { // TODO: Need cleanup and reparse using Scanner CILScanner scanner = new CILScanner(fin, str); string st = scanner.NextToken(); if(st != "callvirt") throw new Exception("unrecognized call"); string className = null; string methodName = null; while(className == null) { st = scanner.NextToken(); if((st == "int32") || (st == "int64") || (st == "void") || (st == "class")) { if(st == "class") scanner.NextToken(); className = scanner.NextToken(); scanner.NextToken(); methodName = scanner.NextToken(); } } string methodSig = "("; scanner.NextToken(); // skips "("; int paramCount = 0; while(true) { st = scanner.NextToken(); if(st == ")") break; if(st != ",") { if(st == "class") { paramCount++; if(paramCount == 2) methodSig += ","; methodSig += scanner.NextToken(); } else methodSig += st; } } methodSig += ")"; CILClass theclass = program.GetClass(className); CILMethod themethod = theclass.GetMethod(methodName, methodSig); return new CIL_callvirt(label, themethod); }