+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
//
// System.Reflection.Emit/ILGenerator.cs
//
using System.Collections;
using System.Diagnostics.SymbolStore;
using System.Runtime.InteropServices;
-using Mono.CSharp.Debugger;
namespace System.Reflection.Emit {
if (extype != null)
System.Console.WriteLine (" extype="+extype.ToString());
else
- System.Console.WriteLine ("");
+ System.Console.WriteLine (String.Empty);
#endif
}
}
handlers [i].extype = null;
}
+ internal void AddFault (int offset)
+ {
+ int i;
+ End (offset);
+ add_block (offset);
+ i = handlers.Length - 1;
+ handlers [i].type = ILExceptionBlock.FAULT;
+ handlers [i].start = offset;
+ handlers [i].extype = null;
+ }
+
+ internal void AddFilter (int offset)
+ {
+ int i;
+ End (offset);
+ add_block (offset);
+ i = handlers.Length - 1;
+ handlers [i].type = ILExceptionBlock.FILTER;
+ handlers [i].extype = null;
+ handlers [i].filter_offset = offset;
+ }
+
internal void End (int offset)
{
if (handlers == null)
return ILExceptionBlock.CATCH;
}
+ internal void PatchLastClauseStart (int start)
+ {
+ if (handlers != null && handlers.Length > 0)
+ handlers [handlers.Length - 1].start = start;
+ }
+
internal void Debug (int b)
{
#if NO
int GetToken (SignatureHelper helper);
}
- public class ILGenerator: Object {
+#if NET_2_0
+ [ComVisible (true)]
+#endif
+ [ClassInterface (ClassInterfaceType.None)]
+ public class ILGenerator: _ILGenerator {
private struct LabelFixup {
public int offset; // The number of bytes between pos and the
// offset of the jump
private LabelFixup[] fixups;
private int num_fixups;
internal Module module;
- internal IMonoSymbolWriter sym_writer;
private Stack scopes;
private int cur_block;
private Stack open_blocks;
private TokenGenerator token_gen;
- const int defaultFixupSize = 8;
- const int defaultLabelsSize = 8;
+ const int defaultFixupSize = 4;
+ const int defaultLabelsSize = 4;
+ const int defaultExceptionStackSize = 2;
+
+ ArrayList sequencePointLists;
+ SequencePointList currentSequence;
internal ILGenerator (Module m, TokenGenerator token_gen, int size)
{
if (size < 0)
size = 128;
- code_len = 0;
code = new byte [size];
- cur_stack = max_stack = 0;
- num_fixups = num_labels = 0;
token_fixups = new ILTokenInfo [8];
- num_token_fixups = 0;
module = m;
- if (module is ModuleBuilder)
- sym_writer = ((ModuleBuilder)module).symbol_writer;
- open_blocks = new Stack ();
this.token_gen = token_gen;
}
-
+
private void add_token_fixup (MemberInfo mi)
{
if (num_token_fixups == token_fixups.Length) {
{
switch (ex_handlers [cur_block].LastClauseType ()) {
case ILExceptionBlock.CATCH:
+ case ILExceptionBlock.FILTER:
// how could we optimize code size here?
Emit (OpCodes.Leave, ex_handlers [cur_block].end);
break;
case ILExceptionBlock.FINALLY:
Emit (OpCodes.Endfinally);
break;
- case ILExceptionBlock.FILTER:
- Emit (OpCodes.Endfilter);
- break;
}
}
public virtual void BeginCatchBlock (Type exceptionType)
{
+ if (open_blocks == null)
+ open_blocks = new Stack (defaultExceptionStackSize);
+
if (open_blocks.Count <= 0)
throw new NotSupportedException ("Not in an exception block");
- InternalEndClause ();
- ex_handlers [cur_block].AddCatch (exceptionType, code_len);
+
+ if (ex_handlers [cur_block].LastClauseType () == ILExceptionBlock.FILTER) {
+ if (exceptionType != null)
+ throw new ArgumentException ("Do not supply an exception type for filter clause");
+ Emit (OpCodes.Endfilter);
+ ex_handlers [cur_block].PatchLastClauseStart (code_len);
+ } else {
+ InternalEndClause ();
+ ex_handlers [cur_block].AddCatch (exceptionType, code_len);
+ }
+
cur_stack = 1; // the exception object is on the stack by default
if (max_stack < cur_stack)
max_stack = cur_stack;
+
//System.Console.WriteLine ("Begin catch Block: {0} {1}",exceptionType.ToString(), max_stack);
- //throw new NotImplementedException ();
}
- [MonoTODO]
public virtual void BeginExceptFilterBlock ()
{
- throw new NotImplementedException ();
+ if (open_blocks == null)
+ open_blocks = new Stack (defaultExceptionStackSize);
+
+ if (open_blocks.Count <= 0)
+ throw new NotSupportedException ("Not in an exception block");
+ InternalEndClause ();
+
+ ex_handlers [cur_block].AddFilter (code_len);
}
public virtual Label BeginExceptionBlock ()
{
//System.Console.WriteLine ("Begin Block");
+ if (open_blocks == null)
+ open_blocks = new Stack (defaultExceptionStackSize);
if (ex_handlers != null) {
cur_block = ex_handlers.Length;
public virtual void BeginFaultBlock()
{
+ if (open_blocks == null)
+ open_blocks = new Stack (defaultExceptionStackSize);
+
if (open_blocks.Count <= 0)
throw new NotSupportedException ("Not in an exception block");
+ InternalEndClause ();
//System.Console.WriteLine ("Begin fault Block");
- //throw new NotImplementedException ();
+ ex_handlers [cur_block].AddFault (code_len);
}
public virtual void BeginFinallyBlock()
{
+ if (open_blocks == null)
+ open_blocks = new Stack (defaultExceptionStackSize);
+
if (open_blocks.Count <= 0)
throw new NotSupportedException ("Not in an exception block");
InternalEndClause ();
}
public virtual void BeginScope ()
- {
- if (sym_writer != null) {
- if (scopes == null)
- scopes = new Stack ();
- scopes.Push (sym_writer.OpenScope (code_len));
- }
- }
+ { }
public LocalBuilder DeclareLocal (Type localType)
{
+ return DeclareLocal (localType, false);
+ }
+
+
+#if NET_2_0
+ public
+#else
+ internal
+#endif
+ LocalBuilder DeclareLocal (Type localType, bool pinned)
+ {
+ if (localType == null)
+ throw new ArgumentNullException ("localType");
+
LocalBuilder res = new LocalBuilder (localType, this);
+ res.is_pinned = pinned;
+
if (locals != null) {
LocalBuilder[] new_l = new LocalBuilder [locals.Length + 1];
System.Array.Copy (locals, new_l, locals.Length);
code [code_len++] = val;
}
+#if NET_2_0
+ [ComVisible (true)]
+#endif
public virtual void Emit (OpCode opcode, ConstructorInfo constructor)
{
int token = token_gen.GetToken (constructor);
public virtual void Emit (OpCode opcode, double val)
{
- Double.AssertEndianity (out val);
-
byte[] s = System.BitConverter.GetBytes (val);
make_room (10);
ll_emit (opcode);
if (fixups == null)
fixups = new LabelFixup [defaultFixupSize];
else if (num_fixups >= fixups.Length) {
- LabelFixup[] newf = new LabelFixup [fixups.Length + 16];
+ LabelFixup[] newf = new LabelFixup [fixups.Length * 2];
System.Array.Copy (fixups, newf, fixups.Length);
fixups = newf;
}
if (fixups == null)
fixups = new LabelFixup [defaultFixupSize + count];
else if (num_fixups + count >= fixups.Length) {
- LabelFixup[] newf = new LabelFixup [fixups.Length + count + 16];
+ LabelFixup[] newf = new LabelFixup [count + fixups.Length * 2];
System.Array.Copy (fixups, newf, fixups.Length);
fixups = newf;
}
int token = token_gen.GetToken (method);
make_room (6);
ll_emit (opcode);
- if (method.DeclaringType.Module == module)
- add_token_fixup (method);
+ Type declaringType = method.DeclaringType;
+ // Might be a DynamicMethod with no declaring type
+ if (declaringType != null) {
+ if (declaringType.Module == module)
+ add_token_fixup (method);
+ }
emit_int (token);
if (method.ReturnType != void_type)
cur_stack ++;
{
make_room (6);
ll_emit (opcode);
- if (method.DeclaringType.Module == module)
- add_token_fixup (method);
+ // Might be a DynamicMethod with no declaring type
+ Type declaringType = method.DeclaringType;
+ if (declaringType != null) {
+ if (declaringType.Module == module)
+ add_token_fixup (method);
+ }
emit_int (token);
if (method.ReturnType != void_type)
cur_stack ++;
emit_int (token_gen.GetToken (type));
}
- [MonoTODO ("Do something about varargs method")]
+ [MonoTODO ("vararg methods are not supported")]
public void EmitCall (OpCode opcode, MethodInfo methodinfo, Type[] optionalParamTypes)
{
if (methodinfo == null)
public virtual void EndExceptionBlock ()
{
+ if (open_blocks == null)
+ open_blocks = new Stack (defaultExceptionStackSize);
+
if (open_blocks.Count <= 0)
throw new NotSupportedException ("Not in an exception block");
InternalEndClause ();
}
public virtual void EndScope ()
- {
- if (sym_writer != null) {
- sym_writer.CloseScope (code_len);
- if (scopes == null)
- throw new InvalidOperationException ();
- scopes.Pop ();
- }
- }
+ { }
public virtual void MarkLabel (Label loc)
{
public virtual void MarkSequencePoint (ISymbolDocumentWriter document, int startLine,
int startColumn, int endLine, int endColumn)
{
- if (sym_writer == null)
- return;
-
- sym_writer.MarkSequencePoint (code_len, startLine, startColumn);
+ if (currentSequence == null || currentSequence.Document != document) {
+ if (sequencePointLists == null)
+ sequencePointLists = new ArrayList ();
+ currentSequence = new SequencePointList (document);
+ sequencePointLists.Add (currentSequence);
+ }
+
+ currentSequence.AddSequencePoint (code_len, startLine, startColumn, endLine, endColumn);
+ }
+
+ internal void GenerateDebugInfo (ISymbolWriter symbolWriter)
+ {
+ if (sequencePointLists != null) {
+ SequencePointList first = (SequencePointList) sequencePointLists [0];
+ SequencePointList last = (SequencePointList) sequencePointLists [sequencePointLists.Count - 1];
+ symbolWriter.SetMethodSourceRange (first.Document, first.StartLine, first.StartColumn, last.Document, last.EndLine, last.EndColumn);
+
+ foreach (SequencePointList list in sequencePointLists)
+ symbolWriter.DefineSequencePoints (list.Document, list.GetOffsets(), list.GetLines(), list.GetColumns(), list.GetEndLines(), list.GetEndColumns());
+
+ if (locals != null) {
+ foreach (LocalBuilder local in locals) {
+ if (local.Name != null && local.Name.Length > 0) {
+ SignatureHelper sighelper = SignatureHelper.GetLocalVarSigHelper (module);
+ sighelper.AddArgument (local.LocalType);
+ byte[] signature = sighelper.GetSignature ();
+ symbolWriter.DefineLocalVariable (local.Name, FieldAttributes.Public, signature, SymAddressKind.ILOffset, local.position, 0, 0, local.StartOffset, local.EndOffset);
+ }
+ }
+ }
+ sequencePointLists = null;
+ }
+ }
+
+ internal bool HasDebugInfo
+ {
+ get { return sequencePointLists != null; }
}
public virtual void ThrowException (Type exceptionType)
}
}
}
+
+ internal static int Mono_GetCurrentOffset (ILGenerator ig)
+ {
+ return ig.code_len;
+ }
+
+ void _ILGenerator.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _ILGenerator.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _ILGenerator.GetTypeInfoCount (out uint pcTInfo)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _ILGenerator.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ internal class SequencePointList
+ {
+ ISymbolDocumentWriter doc;
+ SequencePoint[] points;
+ int count;
+ const int arrayGrow = 10;
+
+ public SequencePointList (ISymbolDocumentWriter doc)
+ {
+ this.doc = doc;
+ }
+
+ public ISymbolDocumentWriter Document {
+ get { return doc; }
+ }
+
+ public int[] GetOffsets()
+ {
+ int[] data = new int [count];
+ for (int n=0; n<count; n++) data [n] = points[n].Offset;
+ return data;
+ }
+ public int[] GetLines()
+ {
+ int[] data = new int [count];
+ for (int n=0; n<count; n++) data [n] = points[n].Line;
+ return data;
+ }
+ public int[] GetColumns()
+ {
+ int[] data = new int [count];
+ for (int n=0; n<count; n++) data [n] = points[n].Col;
+ return data;
+ }
+ public int[] GetEndLines()
+ {
+ int[] data = new int [count];
+ for (int n=0; n<count; n++) data [n] = points[n].EndLine;
+ return data;
+ }
+ public int[] GetEndColumns()
+ {
+ int[] data = new int [count];
+ for (int n=0; n<count; n++) data [n] = points[n].EndCol;
+ return data;
+ }
+ public int StartLine {
+ get { return points[0].Line; }
+ }
+ public int EndLine {
+ get { return points[count - 1].Line; }
+ }
+ public int StartColumn {
+ get { return points[0].Col; }
+ }
+ public int EndColumn {
+ get { return points[count - 1].Col; }
+ }
+
+ public void AddSequencePoint (int offset, int line, int col, int endLine, int endCol)
+ {
+ SequencePoint s = new SequencePoint ();
+ s.Offset = offset;
+ s.Line = line;
+ s.Col = col;
+ s.EndLine = endLine;
+ s.EndCol = endCol;
+
+ if (points == null) {
+ points = new SequencePoint [arrayGrow];
+ } else if (count >= points.Length) {
+ SequencePoint[] temp = new SequencePoint [count + arrayGrow];
+ Array.Copy (points, temp, points.Length);
+ points = temp;
+ }
+
+ points [count] = s;
+ count++;
+ }
+ }
+
+ struct SequencePoint {
+ public int Offset;
+ public int Line;
+ public int Col;
+ public int EndLine;
+ public int EndCol;
}
}