home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / MyC / Src / Exe.cs < prev    next >
Encoding:
Text File  |  2000-06-23  |  12.1 KB  |  487 lines

  1. namespace MyC
  2. {
  3. using System;
  4. using System.Reflection.Emit;
  5. using System.Reflection;
  6. using System.Collections;
  7.  
  8. public class Exe
  9. {
  10. AppDomain appdomain;        // assembly domain
  11. AssemblyName appname;        // assembly name
  12. AssemblyBuilder appbuild;    // assembly builder
  13. ModuleBuilder emodule;        // module builder
  14. TypeBuilder eclass;        // current class
  15. MethodBuilder emethod;        // current method
  16. String filename;
  17. String classname;
  18. Hashtable opcodehash;
  19. ILGenerator il;
  20. System.Diagnostics.SymbolStore.ISymbolDocumentWriter srcdoc;    // debug source file
  21. bool localsdone = false;    // track if we are now emitting instructions
  22.  
  23. public void initOpcodeHash()
  24.   {
  25.   opcodehash = new Hashtable(32); // default initial size
  26.   opcodehash["neg"] = OpCodes.Neg;
  27.   opcodehash["mul"] = OpCodes.Mul;
  28.   opcodehash["div"] = OpCodes.Div;
  29.   opcodehash["add"] = OpCodes.Add;
  30.   opcodehash["sub"] = OpCodes.Sub;
  31.   opcodehash["not"] = OpCodes.Not;
  32.   opcodehash["and"] = OpCodes.And;
  33.   opcodehash["or"] = OpCodes.Or;
  34.   opcodehash["xor"] = OpCodes.Xor;
  35.   opcodehash["pop"] = OpCodes.Pop;
  36.  
  37.   opcodehash["br"] = OpCodes.Br;
  38.   opcodehash["beq"] = OpCodes.Beq;
  39.   opcodehash["bge"] = OpCodes.Bge;
  40.   opcodehash["ble"] = OpCodes.Ble;
  41.   opcodehash["blt"] = OpCodes.Blt;
  42.   opcodehash["bgt"] = OpCodes.Bgt;
  43.   opcodehash["brtrue"] = OpCodes.Brtrue;
  44.   opcodehash["brfalse"] = OpCodes.Brfalse;
  45.  
  46.   opcodehash["cgt"] = OpCodes.Cgt;
  47.   opcodehash["clt"] = OpCodes.Clt;
  48.   opcodehash["ceq"] = OpCodes.Ceq;
  49.  
  50.   opcodehash["ldc.i4.-1"] = OpCodes.Ldc_I4_M1;
  51.   opcodehash["ldc.i4.0"] = OpCodes.Ldc_I4_0;
  52.   opcodehash["ldc.i4.1"] = OpCodes.Ldc_I4_1;
  53.   opcodehash["ldc.i4.2"] = OpCodes.Ldc_I4_2;
  54.   opcodehash["ldc.i4.3"] = OpCodes.Ldc_I4_3;
  55.   opcodehash["ldc.i4.4"] = OpCodes.Ldc_I4_4;
  56.   opcodehash["ldc.i4.5"] = OpCodes.Ldc_I4_5;
  57.   opcodehash["ldc.i4.6"] = OpCodes.Ldc_I4_6;
  58.   opcodehash["ldc.i4.7"] = OpCodes.Ldc_I4_7;
  59.   opcodehash["ldc.i4.8"] = OpCodes.Ldc_I4_8;
  60.   }
  61.  
  62. public Exe(String name)
  63.   {
  64.   filename = name;
  65.   initOpcodeHash();
  66.   }
  67.  
  68. AssemblyName getAssemblyName(string s)
  69.   {
  70.   AssemblyName a = new AssemblyName();
  71.   a.Name = filename+"_assembly";
  72.   a.Title =  "Title "+filename;
  73.   a.Description = "Description "+filename;
  74.   a.DefaultAlias = filename+".exe";
  75.   return a;
  76.   }
  77.  
  78. public void BeginModule(string ifile)
  79.   {
  80.   appdomain = System.Threading.Thread.GetDomain();
  81.   appname = getAssemblyName(filename);
  82.   appbuild = appdomain.DefineDynamicAssembly(appname,
  83.                          AssemblyBuilderAccess.Save,
  84.                          Io.genpath);
  85.   emodule = appbuild.DefineDynamicModule(
  86.           filename+"_module",
  87.           Io.GetOutputFilename(),
  88.         Io.gendebug);
  89.   Guid g = System.Guid.Empty;
  90.   if (Io.gendebug)
  91.     srcdoc = emodule.DefineDocument(ifile, g, g, g);
  92.  
  93.   }
  94.  
  95. public void EndModule()
  96.   {
  97.   try
  98.     {
  99.     String s = Io.GetOutputFilename();
  100.     appbuild.Save(s);
  101.     Console.WriteLine("Saving assembly as "+s);
  102.     }
  103.   catch (Exception e)
  104.     {
  105.     Io.ICE(e.ToString());
  106.     }
  107.   }
  108.  
  109. public void BeginClass(String name, TypeAttributes access)
  110.   {
  111.   classname = name;
  112.   eclass = emodule.DefineType(name, access);
  113.   }
  114.  
  115. public void EndClass()
  116.   {
  117.   eclass.CreateType();        // create the class
  118.   }
  119.  
  120. /*
  121.  * determine the IL static type
  122.  */
  123. Type ilSType(bool sign, int type)
  124.   {
  125.   if (sign)
  126.     {
  127.     switch (type)
  128.       {
  129.       case Tok.T_CHAR:      return Type.GetType("System.SByte");
  130.       case Tok.T_SHORT:     return Type.GetType("System.Int16");
  131.       case Tok.T_DEFTYPE:    return Type.GetType("System.Int32");
  132.       case Tok.T_INT:        return Type.GetType("System.Int32");
  133.       case Tok.T_LONG:        return Type.GetType("System.Int32");
  134.       case Tok.T_FLOAT:        return Type.GetType("System.Single");
  135.       case Tok.T_DOUBLE:    return Type.GetType("System.Double");
  136.       case Tok.T_VOID:        return null;
  137.       default:
  138.     Io.ICE("Unhandled type " + Int32.ToString(type));
  139.     return null;
  140.       }
  141.     }
  142.   else
  143.     {
  144.     switch (type)
  145.       {
  146.       case Tok.T_CHAR:      return Type.GetType("U1");
  147.       case Tok.T_SHORT:     return Type.GetType("U2");
  148.       case Tok.T_DEFTYPE:    return Type.GetType("U4");
  149.       case Tok.T_INT:        return Type.GetType("U4");
  150.       case Tok.T_LONG:        return Type.GetType("U4");
  151.       default:
  152.     Io.ICE("Unhandled type " + Int32.ToString(type));
  153.     return null;
  154.       }
  155.     }
  156.   }
  157.  
  158. /*
  159.  * common routine to construct a signature string for a given varlist item
  160.  * requires a destination ptr, will return the updated dest ptr
  161.  */
  162. private Type genDataTypeSig(Var e)
  163.   {
  164.   bool sign = true;
  165.   if (e == null)
  166.     return null;
  167.  
  168.   if (e.getSign() == Tok.T_UNSIGNED)    /* if var is unsigned, put it in sig */
  169.     sign = false;
  170.  
  171.   Type sig = ilSType(sign, e.getTypeId());    /* get the datatype */
  172.   return (sig);
  173.   }
  174.  
  175. void genLoad(Var e)
  176.   {
  177.   int id = e.getClassId();
  178.   if (e == null)
  179.     Io.ICE("Load instruction with no variable ptr");
  180.   if (e.getLocalToken() != null)
  181.     {
  182.     //    LocalToken lt = (LocalToken) e.getLocalToken();
  183.     LocalBuilder lt = (LocalBuilder) e.getLocalToken();
  184.     il.Emit(OpCodes.Ldloc, lt);
  185.     }
  186.   else if (e.getFieldBuilder() != null)
  187.     {
  188.     FieldBuilder fb = (FieldBuilder) e.getFieldBuilder();
  189.     if (id == Tok.T_STATIC)
  190.       il.Emit(OpCodes.Ldsfld, fb);
  191.     else
  192.       il.Emit(OpCodes.Ldfld, fb);
  193.     }
  194.   else
  195.     {
  196.     int index = e.getIndex();
  197.     if (id == Tok.T_PARAM)
  198.       {
  199.       if (index <= 256)
  200.     il.Emit(OpCodes.Ldarg_S, index);
  201.       else
  202.     il.Emit(OpCodes.Ldarg, index);
  203.       }
  204.     else if (id == Tok.T_AUTO || id == Tok.T_DEFCLASS)
  205.       {
  206.       if (index <= 256)
  207.     il.Emit(OpCodes.Ldloc_S, e.getIndex());
  208.       else
  209.     il.Emit(OpCodes.Ldloc, e.getIndex());
  210.       }
  211.     else
  212.       Io.ICE("Instruction load of unknown class ("
  213.                      + Int32.ToString(e.getClassId())+")");
  214.     }
  215.   }
  216.  
  217. public void Load(IAsm a)
  218.   {
  219.   Var e = a.getVar();
  220.   genLoad(e);
  221.   }
  222.  
  223. public void Store(IAsm a)
  224.   {
  225.   Var e = a.getVar();
  226.   int id = e.getClassId();
  227.   if (e == null)
  228.     Io.ICE("Store instruction with no variable ptr");
  229.   if (e.getLocalToken() != null)
  230.     {
  231.     //    LocalToken lt = (LocalToken) e.getLocalToken();
  232.     LocalBuilder lt = (LocalBuilder) e.getLocalToken();
  233.     il.Emit(OpCodes.Stloc, lt);
  234.     }
  235.   else if (e.getFieldBuilder() != null)
  236.     {
  237.     FieldBuilder fb = (FieldBuilder) e.getFieldBuilder();
  238.     if (id == Tok.T_STATIC)
  239.       il.Emit(OpCodes.Stsfld, fb);
  240.     else
  241.       il.Emit(OpCodes.Stfld, fb);
  242.     }
  243.   else
  244.     {
  245.     int index = e.getIndex();
  246.     if (id == Tok.T_PARAM)
  247.       {
  248.       if (index <= 256)
  249.     il.Emit(OpCodes.Starg_S, index);
  250.       else
  251.     il.Emit(OpCodes.Starg, index);
  252.       }
  253.     else if (id == Tok.T_AUTO || id == Tok.T_DEFCLASS)
  254.       il.Emit(OpCodes.Stloc, index);
  255.     else
  256.       Io.ICE("Instruction load of unknown class ("
  257.                      + Int32.ToString(e.getClassId())+")");
  258.     }
  259.   }
  260.  
  261. public void FuncBegin(IAsm a)
  262.   {
  263.   Var func = a.getVar();
  264.   Type funcsig = genDataTypeSig(a.getVar()); /* gen return type info */
  265.  
  266.   VarList paramlist = func.getParams(); /* get any params */
  267.   Type[] paramTypes = null;    // in case no params
  268.   if (paramlist.Length() > 0)
  269.     {
  270.     int max = paramlist.Length();
  271.     paramTypes = new Type[max];
  272.     for (int i = 0; i < max; i++)
  273.       {
  274.       Var e = paramlist.FindByIndex(i);
  275.       paramTypes[i] = genDataTypeSig(e);
  276.       }
  277.     }
  278.  
  279.   emethod = eclass.DefineMethod(func.getName(),
  280.             MethodAttributes.Static|MethodAttributes.Public,
  281.             funcsig, paramTypes);
  282.   func.setMethodBuilder(emethod); // save the method ref
  283.  
  284.   /*
  285.    * set the argument symbol info
  286.    */
  287.   for (int i = 0; i < paramlist.Length(); i++)
  288.     emethod.DefineParameter(i+1, 0, paramlist.FindByIndex(i).getName());
  289.  
  290.   il = emethod.GetILGenerator(); // create new il generator
  291.  
  292.   if (func.getName().Equals("main")) /* special entry point for main */
  293.     emodule.SetEntryPoint(emethod);
  294.     //    emodule.SetUserEntryPoint(emethod);
  295.  
  296.   /*
  297.    * must also re-init the label hashtable for each function
  298.    */
  299.   labelhash = new Hashtable();
  300.  
  301.   localsdone = false;
  302.   }
  303.  
  304. public void Call(IAsm a)
  305.   {
  306.   Var func = a.getVar();
  307.   Object o = func.getMethodBuilder(); // get previous declared reference
  308.   if (o == null)
  309.     Io.ICE("No previous extern for (" + func.getName() + ")");
  310.   MethodBuilder mb = (MethodBuilder) o;
  311. //  il.Emit(OpCodes.Ldc_I4_0);    // push 0 for the "this" ptr
  312. //  VarList x = func.getParams(); /* get any params */
  313. //  if (x.Length() > 0)
  314. //    {
  315. //    int max = x.Length();
  316. //    for (int i = 0; i < max; i++)
  317. //      {
  318. //      Var e = x.FindByIndex(i);
  319. //      genLoad(e);
  320. //      }
  321. //    }
  322.   il.Emit(OpCodes.Call, mb);    // call the MethodBuilder
  323.   }
  324.  
  325. public void Insn(IAsm a)
  326.   {
  327.   Object o = opcodehash[a.getInsn()];
  328.   if (o == null)
  329.     Io.ICE("Instruction opcode (" + a.getInsn() + ") not found in hash");
  330.   il.Emit((OpCode) o);
  331.   }
  332.  
  333. private Hashtable labelhash;    /* labelname hashtable */ 
  334. /*
  335.  * get and/or create IL label
  336.  * put it in hash for reuse
  337.  */
  338. private Object getILLabel(IAsm a)
  339.   {
  340.   String s = a.getLabel();
  341.   Object l = labelhash[s];
  342.   if (l == null)
  343.     {
  344.     l = (Object) il.DefineLabel();
  345.     labelhash[s] = l;
  346.     }
  347.   return l;
  348.   }
  349.  
  350. public void Label(IAsm a)
  351.   {
  352.   il.MarkLabel((Label) getILLabel(a));
  353.   }
  354.  
  355. public void Branch(IAsm a)
  356.   {
  357.   Object o = opcodehash[a.getInsn()];
  358.   if (o == null)
  359.     Io.ICE("Instruction branch opcode (" + a.getInsn() + ") not found in hash");
  360.   il.Emit((OpCode) o, (Label) getILLabel(a));
  361.   }
  362.  
  363. public void Ret(IAsm a)
  364.   {
  365.   il.Emit(OpCodes.Ret);
  366.   }
  367.  
  368. public void FuncEnd()
  369.   {
  370.   /*
  371.    * fill in the current IL stream for this method
  372.    */
  373.   //  emethod.CreateMethodBody(il);
  374.   il = null;
  375.   localsdone = false;
  376.   }
  377.  
  378. public void LocalVars(VarList v)
  379.   {
  380.   int max = v.Length();
  381.  
  382.   for (int i = 0; i < max; i++)    // loop thru the local params
  383.     {
  384.     Var e = v.FindByIndex(i);    // indexed by number
  385.     Type et = genDataTypeSig(e);
  386.     //    LocalToken t = emethod.DeclareLocal(et);
  387.     LocalBuilder t = il.DeclareLocal(et);
  388.     if (Io.gendebug)
  389.       t.SetLocalSymInfo(e.getName());
  390.     e.setLocalToken(t);
  391.     }
  392.   localsdone = true;
  393.   }
  394.  
  395. public void FieldDef(IAsm a)
  396.   {
  397.   Var e = a.getVar();            /* get the field var ptr */
  398.   FieldAttributes attr = FieldAttributes.Private; /* default attributes is private */
  399.  
  400.   if (e.getClassId() == Tok.T_STATIC)
  401.     attr |= FieldAttributes.Static;
  402.  
  403.   Type t = genDataTypeSig(e);        /* gen type info */
  404.  
  405.   FieldBuilder f = eclass.DefineField(e.getName(), t, attr); // returns token
  406.   e.setFieldBuilder((Object) f);            // store token for later usage
  407.   }
  408.  
  409. public void LoadConst(IAsm a)
  410.   {
  411.   int value = Convert.ToInt32(a.getInsn());
  412.  
  413.   if (value > 127 || value < -128) /* if must use long form */
  414.     {
  415.     il.Emit(OpCodes.Ldc_I4, value);
  416.     }
  417.   else if (value > 8 || value < -1)    /* if must use medium form */
  418.     {
  419.     il.Emit(OpCodes.Ldc_I4_S, value);
  420.     }
  421.   else if (value == -1)
  422.     {
  423.     il.Emit(OpCodes.Ldc_I4_M1);
  424.     }
  425.   else                /* else use short form */
  426.     {
  427.     Object o = opcodehash["ldc.i4."+a.getInsn()];
  428.     if (o == null)
  429.       Io.ICE("Could not find opcode for (Ldc_I4_" + a.getInsn() + ")");
  430.     il.Emit((OpCode) o);
  431.     }
  432.   }
  433.  
  434. public void Comment(IAsm a)
  435.   {
  436.   if (Io.gendebug)
  437.     {
  438.     if (localsdone)
  439.       {
  440.       if (a != null && il != null)
  441.     {
  442.     if (!IsNextNonInsnGen(a))
  443.       {
  444.  
  445.       //      Console.WriteLine("Line ("+a.getCommentLine().ToString()+")="+a.getComment());
  446.       int l = a.getCommentLine();
  447.       il.MarkSequencePoint(srcdoc, l, 0, l, 0);
  448.       }
  449.     }
  450.       }
  451.     }
  452.   }
  453.  
  454. /*
  455.  * is the next assembler directive an non-instruction generation
  456.  *
  457.  * this is used to keep marksequencepoint from getting multiple calls
  458.  * with no intervening instructions, which causes it to work incorrectly
  459.  */
  460. private bool IsNextNonInsnGen(IAsm a)
  461.   {
  462.   IAsm cur = a.getNext();
  463.   if (cur == null)
  464.     return true;
  465.   int type = cur.getIType();
  466.  
  467.   /*
  468.    * skip intervening labels
  469.    */
  470.   while (type == IAsm.I_LABEL)
  471.     {
  472.     cur = cur.getNext();
  473.     type = cur.getIType();
  474.     }
  475.  
  476.   /*
  477.    * if next is comment then return true
  478.    */
  479.   if (type == IAsm.I_COMMENT)
  480.     return true;
  481.   return false;
  482.   }
  483.  
  484. }
  485.  
  486. }
  487.