* MethodDef.cs: Add ability to add and emit labels
authorJackson Harper <jackson@novell.com>
Tue, 6 May 2003 06:54:58 +0000 (06:54 -0000)
committerJackson Harper <jackson@novell.com>
Tue, 6 May 2003 06:54:58 +0000 (06:54 -0000)
* BranchInstr.cs: New file - Branch instructions

svn path=/trunk/mcs/; revision=14319

mcs/ilasm/codegen/BranchInstr.cs [new file with mode: 0644]
mcs/ilasm/codegen/ChangeLog
mcs/ilasm/codegen/MethodDef.cs

diff --git a/mcs/ilasm/codegen/BranchInstr.cs b/mcs/ilasm/codegen/BranchInstr.cs
new file mode 100644 (file)
index 0000000..a3d2723
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Mono.ILASM.BranchInstr
+//
+// Author(s):
+//  Jackson Harper (Jackson@LatitudeGeo.com)
+//
+// (C) 2003 Jackson Harper, All rights reserved
+//
+
+
+using System;
+
+
+namespace Mono.ILASM {
+
+        public class BranchInstr : IInstr {
+
+                private PEAPI.BranchOp op;
+                private MethodDef method;
+                private string label;
+
+                public BranchInstr (PEAPI.BranchOp op, MethodDef method, string label)
+                {
+                        this.op = op;
+                        this.method = method;
+                        this.label = label;
+                }
+
+                public void Emit (CodeGen code_gen, PEAPI.CILInstructions cil)
+                {
+                        cil.Branch (op, method.GetLabelDef (label));
+                }
+        }
+
+}
+
index 7f52f53d92bc323bb760074eaf2e6103eab87a47..c56f9960ecddd524e6c540beee07c56c4dcc7727 100644 (file)
@@ -1,3 +1,8 @@
+2003-05-04 Jackson Harper <jackson@lattidegeo.com>
+
+       * MethodDef.cs: Add ability to add and emit labels
+       * BranchInstr.cs: New file - Branch instructions
+               
 2003-05-04 Jackson Harper <jackson@latitudegeo.com>
 
        * LdcInstr.cs: New file - lcd* instructions
index 41f695b0d731264fd25e1036f5aa58d279023251..05555b816b33f522b3edeed91966242af8ab466d 100644 (file)
@@ -17,6 +17,35 @@ namespace Mono.ILASM {
 
         public class MethodDef {
 
+                protected class LabelInfo : IComparable {
+
+                        public readonly string Name;
+                        public readonly int Pos;
+                        public PEAPI.CILLabel Label;
+
+                        public LabelInfo (string name, int pos)
+                        {
+                                Name = name;
+                                Pos = pos;
+                                Label = null;
+                        }
+
+                        public void Define (PEAPI.CILLabel label)
+                        {
+                                Label = label;
+                        }
+
+                        public int CompareTo (object obj)
+                        {
+                                LabelInfo other = obj as LabelInfo;
+
+                                if(other != null)
+                                        return Pos.CompareTo(other.Pos);
+
+                                throw new ArgumentException ("object is not a LabelInfo");
+                        }
+                }
+
                 private PEAPI.MethAttr meth_attr;
                 private PEAPI.ImplAttr impl_attr;
                 private string name;
@@ -24,6 +53,7 @@ namespace Mono.ILASM {
                 private ITypeRef ret_type;
                 private ArrayList param_list;
                 private ArrayList inst_list;
+                private Hashtable label_table;
                 private PEAPI.MethodDef methoddef;
                 private bool is_defined;
 
@@ -37,6 +67,8 @@ namespace Mono.ILASM {
                         this.param_list = param_list;
 
                         inst_list = new ArrayList ();
+                        label_table = new Hashtable ();
+
                         is_defined = false;
                         CreateSignature ();
                 }
@@ -72,6 +104,9 @@ namespace Mono.ILASM {
 
                         methoddef = code_gen.PEFile.AddMethod (meth_attr, impl_attr,
                                         name, ret_type.PeapiType, param_array);
+
+                        WriteCode (code_gen, methoddef);
+
                         is_defined = true;
                 }
 
@@ -95,11 +130,7 @@ namespace Mono.ILASM {
                         methoddef = classdef.AddMethod (meth_attr, impl_attr,
                                         name, ret_type.PeapiType, param_array);
 
-                        if (inst_list.Count > 0) {
-                                PEAPI.CILInstructions cil = methoddef.CreateCodeBuffer ();
-                                foreach (IInstr instr in inst_list)
-                                        instr.Emit (code_gen, cil);
-                        }
+                        WriteCode (code_gen, methoddef);
 
                         is_defined = true;
                 }
@@ -109,6 +140,53 @@ namespace Mono.ILASM {
                         inst_list.Add (instr);
                 }
 
+                protected void WriteCode (CodeGen code_gen, PEAPI.MethodDef methoddef)
+                {
+                        if (inst_list.Count < 1)
+                                return;
+
+                        PEAPI.CILInstructions cil = methoddef.CreateCodeBuffer ();
+                        /// Create all the labels
+                        /// TODO: Most labels don't actually need to be created so we could
+                        /// probably only create the ones that need to be
+                        LabelInfo[] label_info = new LabelInfo[label_table.Count];
+                        label_table.Values.CopyTo (label_info, 0);
+                        Array.Sort (label_info);
+
+                        foreach (LabelInfo label in label_info)
+                                label.Define (cil.NewLabel ());
+
+                        int label_pos = 0;
+                        int next_label_pos = (label_info.Length > 0 ? label_info[0].Pos : -1);
+
+                        for (int i=0; i<inst_list.Count; i++) {
+                                IInstr instr = (IInstr) inst_list[i];
+                                if (next_label_pos == i) {
+                                        cil.CodeLabel (label_info[label_pos].Label);
+                                        if (++label_pos < label_info.Length)
+                                                next_label_pos = label_info[label_pos].Pos;
+                                        else
+                                                next_label_pos = -1;
+                                }
+                                instr.Emit (code_gen, cil);
+                        }
+
+                }
+
+                public void AddLabel (string name)
+                {
+                        LabelInfo label_info = new LabelInfo (name, inst_list.Count);
+
+                        label_table.Add (name, label_info);
+                }
+
+                public PEAPI.CILLabel GetLabelDef (string name)
+                {
+                        LabelInfo label_info = (LabelInfo) label_table[name];
+
+                        return label_info.Label;
+                }
+
                 private void CreateSignature ()
                 {
                         StringBuilder builder = new StringBuilder ();