Mono & the .NET Framework
by Miguel de Icaza and Brian Jepson

Example 1:
(a)
struct MyStruct {
  int high;
  int low;
}
class MyObject {
  int high;
  int low;
}

(b)
 .class private sequential ansi sealed beforefieldinit MyStruct
       extends [mscorlib]System.ValueType
 {
   .field private int32 high
   .field private int32 low 
 } // end of class MyStruct

(c) 
 .class private auto ansi beforefieldinit MyObject
       extends [mscorlib]System.Object
 {
   .field private int32 high
   .field private int32 low
   .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
   {
     // Code size       7 (0x7)
     .maxstack  1
     IL_0000:  ldarg.0
     IL_0001:  call instance void [mscorlib]System.Object::.ctor()

     IL_0006:  ret
   } // end of method MyObject::.ctor
 } // end of class MyObject

(d)
object[] my_array = new object[1];
my_array[0] = 1;               // boxed to (object)
int x = (int) my_array[0] + 1; // unboxed

Example 2:
(a)
using System;
public class Hello {
  public static void Main() {
    int a = 23 + 67;
    Console.WriteLine(++a);
  }
}

(b)
bjepson@VMWARE /cygdrive/o/mono/mono-test
$ compiler Hello.cs
Parsing successful

bjepson@VMWARE /cygdrive/o/mono/mono-test
$ ls -l Hello.exe
-rwxr-xr-x    1 bjepson  None         2048 Oct  4 21:54 Hello.exe

bjepson@VMWARE /cygdrive/o/mono/mono-test
$ file Hello.exe
Hello.exe: MS Windows PE 32-bit Intel 80386 console executable

(c)
.MEthod public static
       default void Main()  cil managed
{
    // Method begins at RVA 0x2064
    .entrypoint
    // Code size 17 (0x11)
    .maxstack 2
    .locals (
            int32   V_0)
    IL_0000: ldc.i4.s 0x17
    IL_0002: ldc.i4.s 0x43
    IL_0004: add
    IL_0005: stloc.0
    IL_0006: ldloc.0
    IL_0007: ldc.i4.1
    IL_0008: add
    IL_0009: dup
    IL_000a: stloc.0
    IL_000b: call void System.Console::WriteLine(int32)
    IL_0010: ret
}

(d)
bjepson@VMWARE /cygdrive/o/mono/mono-test
$ mint Hello.exe
91


Example 3:
(a)
[DllImport("libc.so.6", EntryPoint="puts", CharSet=CharSet.Ansi)]
public static extern int puts(string name);

(b)
using System;
using System.Runtime.InteropServices;

class PInvokeTest {

  [DllImport("libncurses.so", EntryPoint="initscr")]
  public extern static void initscr();

  [DllImport("libncurses.so", EntryPoint="getch")]
  public extern static int getch();

  [DllImport("libncurses.so", EntryPoint="mvaddstr")]
  public extern static void mvaddstr(int x, int y, string c);

  [DllImport("libncurses.so", EntryPoint="endwin")]
  public extern static void endwin();

  [DllImport("libncurses.so", EntryPoint="refresh")]
  public extern static void refresh();

  public static void Main() {
    initscr(); // Initialize ncurses
    mvaddstr(11, 24, "Hello, from ncurses!");
    mvaddstr(12, 20, "(press any key to continue)");
    refresh();
    getch();  // Wait for keypress
    endwin(); // clean up
  }
}



Listing One
lreg: ADD (lreg, lreg) {
  if (tree->reg1 != tree->left->reg1)
    x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
  if (tree->reg2 != tree->left->reg2)
    x86_mov_reg_reg (s->code, tree->reg2, tree->left->reg2, 4);
  x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
  x86_alu_reg_reg (s->code, X86_ADC, tree->reg2, tree->right->reg2);
}

Listing Two
public enum ExprClass {
  Invalid,
  Value,
  Variable,
  Namespace,
  Type,
  MethodGroup,
  PropertyAccess,
  EventAccess,
  IndexerAccess,
  Nothing,
}
public abstract class Expression {
  protected ExprClass eclass;
  protected System.Type type;

  // <summary>
  //   Performs semantic analysis on the Expression
  // </summary>
  // <remarks>
  //   The DoResolve method performs semantic analysis on the node. The 
  //   return value is an expression (it can be the same expression
  //   in some cases) or a new expression that better represents this node.
  //   For example, optimizations of Unary (LiteralInt) would return a 
  //   new LiteralInt with a negated value.
  //   If there is an error during semantic analysis, then an
  //   error should be reported and a null value should be returned.
  //   There are two side effects expected from calling
  //   DoResolve(): the field variable "eclass" should be set to
  //   any value of the enumeration `ExprClass' and the type variable 
  //   should be set to a valid type (this is the type of the expression).
  // </remarks>
  public abstract Expression DoResolve (TypeContainer tc);

  // <remarks>
  //   This is just a wrapper around DoResolve used to perform sanity checks
  //   on the various Resolve implentations, helpful during debugging.
  // </remarks>
  public Expression Resolve (TypeContainer tc)
  {
    Expression e = DoResolve (tc);

    if (e != null){
      if (e.eclass == ExprClass.Invalid)
        throw new Exception ("Expression " + e +
                 " ExprClass is Invalid after resolve");
      if (e.eclass != ExprClass.MethodGroup)
        if (e.type == null)
          throw new Exception ("Expression " + e +
                   " did not set its type after Resolve");
    }
    return e;
  }
  // <summary>
  //   Emits the code for the expression
  // </summary>
  // <remarks>
  //   The Emit method is invoked to generate the code for the expression.
  // </remarks>
  public abstract void Emit (EmitContext ec);

  // <summary>
  //   Protected constructor. Only derivate types should be able to be created
  // </summary>
  protected Expression ()
  {
    eclass = ExprClass.Invalid;
    type = null;
  }
}

Listing Three
reg: ADDR_L {
  x86_mov_reg_reg (s->code, tree->reg1, X86_EBP, 4);
  x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, tree->data.i);
} cost {
  return 1;
}

Listing Four
reg: ADDR_L 1 {
  x86_mov_reg_reg (s->code, tree->reg1, X86_EBP, 4);
  x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, tree->data.i);
}
reg: CONST_I4 1 {
  x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
}
base: acon
base: reg {
  tree->data.ainfo.offset = 0;
  tree->data.ainfo.basereg = tree->reg1;
  tree->data.ainfo.amode = AMBase;
}
addr: base
stmt: STIND_I4 (addr, reg) {
  switch (tree->left->data.ainfo.amode) {
  case AMImmediate:
    x86_mov_mem_reg(s->code, tree->left->data.ainfo.offset, 
               tree->right->reg1, 4);
    break;
  case AMBase:
    x86_mov_membase_reg(s->code, tree->left->data.ainfo.basereg,
                        tree->left->data.ainfo.offset, tree->right->reg1, 4);
    break;
  case AMIndex:
    x86_mov_memindex_reg(s->code, X86_NOBASEREG,
          tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
          tree->left->data.ainfo.shift, tree->right->reg1, 4);
    break;
  case AMBaseIndex:
    x86_mov_memindex_reg(s->code, tree->left->data.ainfo.basereg,
          tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg,
          tree->left->data.ainfo.shift, tree->right->reg1, 4);
    break;
  }
}









5


