3 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 // System.Reflection.Emit/ILGenerator.cs
29 // Paolo Molaro (lupus@ximian.com)
31 // (C) 2001 Ximian, Inc. http://www.ximian.com
35 using System.Collections;
36 using System.Diagnostics.SymbolStore;
37 using System.Runtime.InteropServices;
39 namespace System.Reflection.Emit {
41 internal struct ILExceptionBlock {
42 public const int CATCH = 0;
43 public const int FILTER = 1;
44 public const int FINALLY = 2;
45 public const int FAULT = 4;
51 internal int filter_offset;
53 internal void Debug () {
55 System.Console.Write ("\ttype="+type.ToString()+" start="+start.ToString()+" len="+len.ToString());
57 System.Console.WriteLine (" extype="+extype.ToString());
59 System.Console.WriteLine (String.Empty);
63 internal struct ILExceptionInfo {
64 ILExceptionBlock[] handlers;
69 internal int NumHandlers ()
71 return handlers.Length;
74 internal void AddCatch (Type extype, int offset)
79 i = handlers.Length - 1;
80 handlers [i].type = ILExceptionBlock.CATCH;
81 handlers [i].start = offset;
82 handlers [i].extype = extype;
85 internal void AddFinally (int offset)
90 i = handlers.Length - 1;
91 handlers [i].type = ILExceptionBlock.FINALLY;
92 handlers [i].start = offset;
93 handlers [i].extype = null;
96 internal void AddFault (int offset)
101 i = handlers.Length - 1;
102 handlers [i].type = ILExceptionBlock.FAULT;
103 handlers [i].start = offset;
104 handlers [i].extype = null;
107 internal void AddFilter (int offset)
112 i = handlers.Length - 1;
113 handlers [i].type = ILExceptionBlock.FILTER;
114 handlers [i].extype = null;
115 handlers [i].filter_offset = offset;
118 internal void End (int offset)
120 if (handlers == null)
122 int i = handlers.Length - 1;
124 handlers [i].len = offset - handlers [i].start;
127 internal int LastClauseType ()
129 if (handlers != null)
130 return handlers [handlers.Length-1].type;
132 return ILExceptionBlock.CATCH;
135 internal void PatchLastClauseStart (int start)
137 if (handlers != null && handlers.Length > 0)
138 handlers [handlers.Length - 1].start = start;
141 internal void Debug (int b)
144 System.Console.WriteLine ("Handler {0} at {1}, len: {2}", b, start, len);
145 for (int i = 0; i < handlers.Length; ++i)
146 handlers [i].Debug ();
150 void add_block (int offset)
152 if (handlers != null) {
153 int i = handlers.Length;
154 ILExceptionBlock[] new_b = new ILExceptionBlock [i + 1];
155 System.Array.Copy (handlers, new_b, i);
157 handlers [i].len = offset - handlers [i].start;
159 handlers = new ILExceptionBlock [1];
160 len = offset - start;
165 internal struct ILTokenInfo {
166 public MemberInfo member;
170 internal interface TokenGenerator {
171 int GetToken (string str);
173 int GetToken (MemberInfo member);
175 int GetToken (MethodInfo method, Type[] opt_param_types);
177 int GetToken (SignatureHelper helper);
183 [ClassInterface (ClassInterfaceType.None)]
184 public class ILGenerator: _ILGenerator {
185 private struct LabelFixup {
186 public int offset; // The number of bytes between pos and the
187 // offset of the jump
188 public int pos; // Where offset of the label is placed
189 public int label_idx; // The label to jump to
193 public LabelData (int addr, int maxStack)
196 this.maxStack = maxStack;
203 static readonly Type void_type = typeof (void);
204 #region Sync with reflection.h
206 private int code_len;
207 private int max_stack;
208 private int cur_stack;
209 private LocalBuilder[] locals;
210 private ILExceptionInfo[] ex_handlers;
211 private int num_token_fixups;
212 private ILTokenInfo[] token_fixups;
215 private LabelData [] labels;
216 private int num_labels;
217 private LabelFixup[] fixups;
218 private int num_fixups;
219 internal Module module;
220 private Stack scopes;
221 private int cur_block;
222 private Stack open_blocks;
223 private TokenGenerator token_gen;
225 const int defaultFixupSize = 4;
226 const int defaultLabelsSize = 4;
227 const int defaultExceptionStackSize = 2;
229 ArrayList sequencePointLists;
230 SequencePointList currentSequence;
232 internal ILGenerator (Module m, TokenGenerator token_gen, int size)
236 code = new byte [size];
237 token_fixups = new ILTokenInfo [8];
239 this.token_gen = token_gen;
242 private void add_token_fixup (MemberInfo mi)
244 if (num_token_fixups == token_fixups.Length) {
245 ILTokenInfo[] ntf = new ILTokenInfo [num_token_fixups * 2];
246 token_fixups.CopyTo (ntf, 0);
249 token_fixups [num_token_fixups].member = mi;
250 token_fixups [num_token_fixups++].code_pos = code_len;
253 private void make_room (int nbytes)
255 if (code_len + nbytes < code.Length)
257 byte[] new_code = new byte [(code_len + nbytes) * 2 + 128];
258 System.Array.Copy (code, 0, new_code, 0, code.Length);
262 private void emit_int (int val)
264 code [code_len++] = (byte) (val & 0xFF);
265 code [code_len++] = (byte) ((val >> 8) & 0xFF);
266 code [code_len++] = (byte) ((val >> 16) & 0xFF);
267 code [code_len++] = (byte) ((val >> 24) & 0xFF);
270 /* change to pass by ref to avoid copy */
271 private void ll_emit (OpCode opcode)
274 * there is already enough room allocated in code.
276 // access op1 and op2 directly since the Value property is useless
277 if (opcode.Size == 2)
278 code [code_len++] = opcode.op1;
279 code [code_len++] = opcode.op2;
281 * We should probably keep track of stack needs here.
282 * Or we may want to run the verifier on the code before saving it
283 * (this may be needed anyway when the ILGenerator is not used...).
285 switch (opcode.StackBehaviourPush) {
286 case StackBehaviour.Push1:
287 case StackBehaviour.Pushi:
288 case StackBehaviour.Pushi8:
289 case StackBehaviour.Pushr4:
290 case StackBehaviour.Pushr8:
291 case StackBehaviour.Pushref:
292 case StackBehaviour.Varpush: /* again we are conservative and assume it pushes 1 */
295 case StackBehaviour.Push1_push1:
299 if (max_stack < cur_stack)
300 max_stack = cur_stack;
303 * Note that we adjust for the pop behaviour _after_ setting max_stack.
305 switch (opcode.StackBehaviourPop) {
306 case StackBehaviour.Varpop:
307 break; /* we are conservative and assume it doesn't decrease the stack needs */
308 case StackBehaviour.Pop1:
309 case StackBehaviour.Popi:
310 case StackBehaviour.Popref:
313 case StackBehaviour.Pop1_pop1:
314 case StackBehaviour.Popi_pop1:
315 case StackBehaviour.Popi_popi:
316 case StackBehaviour.Popi_popi8:
317 case StackBehaviour.Popi_popr4:
318 case StackBehaviour.Popi_popr8:
319 case StackBehaviour.Popref_pop1:
320 case StackBehaviour.Popref_popi:
323 case StackBehaviour.Popi_popi_popi:
324 case StackBehaviour.Popref_popi_popi:
325 case StackBehaviour.Popref_popi_popi8:
326 case StackBehaviour.Popref_popi_popr4:
327 case StackBehaviour.Popref_popi_popr8:
328 case StackBehaviour.Popref_popi_popref:
334 private static int target_len (OpCode opcode)
336 if (opcode.OperandType == OperandType.InlineBrTarget)
341 private void InternalEndClause ()
343 switch (ex_handlers [cur_block].LastClauseType ()) {
344 case ILExceptionBlock.CATCH:
345 case ILExceptionBlock.FILTER:
346 // how could we optimize code size here?
347 Emit (OpCodes.Leave, ex_handlers [cur_block].end);
349 case ILExceptionBlock.FAULT:
350 case ILExceptionBlock.FINALLY:
351 Emit (OpCodes.Endfinally);
356 public virtual void BeginCatchBlock (Type exceptionType)
358 if (open_blocks == null)
359 open_blocks = new Stack (defaultExceptionStackSize);
361 if (open_blocks.Count <= 0)
362 throw new NotSupportedException ("Not in an exception block");
364 if (ex_handlers [cur_block].LastClauseType () == ILExceptionBlock.FILTER) {
365 if (exceptionType != null)
366 throw new ArgumentException ("Do not supply an exception type for filter clause");
367 Emit (OpCodes.Endfilter);
368 ex_handlers [cur_block].PatchLastClauseStart (code_len);
370 InternalEndClause ();
371 ex_handlers [cur_block].AddCatch (exceptionType, code_len);
374 cur_stack = 1; // the exception object is on the stack by default
375 if (max_stack < cur_stack)
376 max_stack = cur_stack;
378 //System.Console.WriteLine ("Begin catch Block: {0} {1}",exceptionType.ToString(), max_stack);
381 public virtual void BeginExceptFilterBlock ()
383 if (open_blocks == null)
384 open_blocks = new Stack (defaultExceptionStackSize);
386 if (open_blocks.Count <= 0)
387 throw new NotSupportedException ("Not in an exception block");
388 InternalEndClause ();
390 ex_handlers [cur_block].AddFilter (code_len);
393 public virtual Label BeginExceptionBlock ()
395 //System.Console.WriteLine ("Begin Block");
396 if (open_blocks == null)
397 open_blocks = new Stack (defaultExceptionStackSize);
399 if (ex_handlers != null) {
400 cur_block = ex_handlers.Length;
401 ILExceptionInfo[] new_ex = new ILExceptionInfo [cur_block + 1];
402 System.Array.Copy (ex_handlers, new_ex, cur_block);
403 ex_handlers = new_ex;
405 ex_handlers = new ILExceptionInfo [1];
408 open_blocks.Push (cur_block);
409 ex_handlers [cur_block].start = code_len;
410 return ex_handlers [cur_block].end = DefineLabel ();
413 public virtual void BeginFaultBlock()
415 if (open_blocks == null)
416 open_blocks = new Stack (defaultExceptionStackSize);
418 if (open_blocks.Count <= 0)
419 throw new NotSupportedException ("Not in an exception block");
420 InternalEndClause ();
421 //System.Console.WriteLine ("Begin fault Block");
422 ex_handlers [cur_block].AddFault (code_len);
425 public virtual void BeginFinallyBlock()
427 if (open_blocks == null)
428 open_blocks = new Stack (defaultExceptionStackSize);
430 if (open_blocks.Count <= 0)
431 throw new NotSupportedException ("Not in an exception block");
432 InternalEndClause ();
433 //System.Console.WriteLine ("Begin finally Block");
434 ex_handlers [cur_block].AddFinally (code_len);
437 public virtual void BeginScope ()
440 public LocalBuilder DeclareLocal (Type localType)
442 return DeclareLocal (localType, false);
451 LocalBuilder DeclareLocal (Type localType, bool pinned)
453 if (localType == null)
454 throw new ArgumentNullException ("localType");
456 LocalBuilder res = new LocalBuilder (localType, this);
457 res.is_pinned = pinned;
459 if (locals != null) {
460 LocalBuilder[] new_l = new LocalBuilder [locals.Length + 1];
461 System.Array.Copy (locals, new_l, locals.Length);
462 new_l [locals.Length] = res;
465 locals = new LocalBuilder [1];
468 res.position = (ushort)(locals.Length - 1);
472 public virtual Label DefineLabel ()
475 labels = new LabelData [defaultLabelsSize];
476 else if (num_labels >= labels.Length) {
477 LabelData [] t = new LabelData [labels.Length * 2];
478 Array.Copy (labels, t, labels.Length);
482 labels [num_labels] = new LabelData (-1, 0);
484 return new Label (num_labels++);
487 public virtual void Emit (OpCode opcode)
493 public virtual void Emit (OpCode opcode, Byte val)
497 code [code_len++] = val;
503 public virtual void Emit (OpCode opcode, ConstructorInfo constructor)
505 int token = token_gen.GetToken (constructor);
508 if (constructor.DeclaringType.Module == module)
509 add_token_fixup (constructor);
512 if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
513 cur_stack -= constructor.GetParameterCount ();
516 public virtual void Emit (OpCode opcode, double val)
518 byte[] s = System.BitConverter.GetBytes (val);
521 if (BitConverter.IsLittleEndian){
522 System.Array.Copy (s, 0, code, code_len, 8);
525 code [code_len++] = s [7];
526 code [code_len++] = s [6];
527 code [code_len++] = s [5];
528 code [code_len++] = s [4];
529 code [code_len++] = s [3];
530 code [code_len++] = s [2];
531 code [code_len++] = s [1];
532 code [code_len++] = s [0];
536 public virtual void Emit (OpCode opcode, FieldInfo field)
538 int token = token_gen.GetToken (field);
541 if (field.DeclaringType.Module == module)
542 add_token_fixup (field);
546 public virtual void Emit (OpCode opcode, Int16 val)
550 code [code_len++] = (byte) (val & 0xFF);
551 code [code_len++] = (byte) ((val >> 8) & 0xFF);
554 public virtual void Emit (OpCode opcode, int val)
561 public virtual void Emit (OpCode opcode, long val)
565 code [code_len++] = (byte) (val & 0xFF);
566 code [code_len++] = (byte) ((val >> 8) & 0xFF);
567 code [code_len++] = (byte) ((val >> 16) & 0xFF);
568 code [code_len++] = (byte) ((val >> 24) & 0xFF);
569 code [code_len++] = (byte) ((val >> 32) & 0xFF);
570 code [code_len++] = (byte) ((val >> 40) & 0xFF);
571 code [code_len++] = (byte) ((val >> 48) & 0xFF);
572 code [code_len++] = (byte) ((val >> 56) & 0xFF);
575 public virtual void Emit (OpCode opcode, Label label)
577 int tlen = target_len (opcode);
580 if (cur_stack > labels [label.label].maxStack)
581 labels [label.label].maxStack = cur_stack;
584 fixups = new LabelFixup [defaultFixupSize];
585 else if (num_fixups >= fixups.Length) {
586 LabelFixup[] newf = new LabelFixup [fixups.Length * 2];
587 System.Array.Copy (fixups, newf, fixups.Length);
590 fixups [num_fixups].offset = tlen;
591 fixups [num_fixups].pos = code_len;
592 fixups [num_fixups].label_idx = label.label;
598 public virtual void Emit (OpCode opcode, Label[] labels)
600 /* opcode needs to be switch. */
601 int count = labels.Length;
602 make_room (6 + count * 4);
605 for (int i = 0; i < count; ++i)
606 if (cur_stack > this.labels [labels [i].label].maxStack)
607 this.labels [labels [i].label].maxStack = cur_stack;
611 fixups = new LabelFixup [defaultFixupSize + count];
612 else if (num_fixups + count >= fixups.Length) {
613 LabelFixup[] newf = new LabelFixup [count + fixups.Length * 2];
614 System.Array.Copy (fixups, newf, fixups.Length);
618 // ECMA 335, Partition III, p94 (7-10)
620 // The switch instruction implements a jump table. The format of
621 // the instruction is an unsigned int32 representing the number of targets N,
622 // followed by N int32 values specifying jump targets: these targets are
623 // represented as offsets (positive or negative) from the beginning of the
624 // instruction following this switch instruction.
626 // We must make sure it gets an offset from the *end* of the last label
627 // (eg, the beginning of the instruction following this).
629 // remaining is the number of bytes from the current instruction to the
630 // instruction that will be emitted.
632 for (int i = 0, remaining = count * 4; i < count; ++i, remaining -= 4) {
633 fixups [num_fixups].offset = remaining;
634 fixups [num_fixups].pos = code_len;
635 fixups [num_fixups].label_idx = labels [i].label;
641 public virtual void Emit (OpCode opcode, LocalBuilder lbuilder)
643 uint pos = lbuilder.position;
644 bool load_addr = false;
645 bool is_store = false;
648 if (lbuilder.ilgen != this)
649 throw new Exception ("Trying to emit a local from a different ILGenerator.");
651 /* inline the code from ll_emit () to optimize il code size */
652 if (opcode.StackBehaviourPop == StackBehaviour.Pop1) {
657 if (cur_stack > max_stack)
658 max_stack = cur_stack;
659 load_addr = opcode.StackBehaviourPush == StackBehaviour.Pushi;
663 code [code_len++] = (byte)0x12;
664 code [code_len++] = (byte)pos;
666 code [code_len++] = (byte)0xfe;
667 code [code_len++] = (byte)0x0d;
668 code [code_len++] = (byte)(pos & 0xff);
669 code [code_len++] = (byte)((pos >> 8) & 0xff);
674 code [code_len++] = (byte)(0x0a + pos);
675 } else if (pos < 256) {
676 code [code_len++] = (byte)0x13;
677 code [code_len++] = (byte)pos;
679 code [code_len++] = (byte)0xfe;
680 code [code_len++] = (byte)0x0e;
681 code [code_len++] = (byte)(pos & 0xff);
682 code [code_len++] = (byte)((pos >> 8) & 0xff);
686 code [code_len++] = (byte)(0x06 + pos);
687 } else if (pos < 256) {
688 code [code_len++] = (byte)0x11;
689 code [code_len++] = (byte)pos;
691 code [code_len++] = (byte)0xfe;
692 code [code_len++] = (byte)0x0c;
693 code [code_len++] = (byte)(pos & 0xff);
694 code [code_len++] = (byte)((pos >> 8) & 0xff);
700 public virtual void Emit (OpCode opcode, MethodInfo method)
703 throw new ArgumentNullException ("method");
705 int token = token_gen.GetToken (method);
708 Type declaringType = method.DeclaringType;
709 // Might be a DynamicMethod with no declaring type
710 if (declaringType != null) {
711 if (declaringType.Module == module)
712 add_token_fixup (method);
715 if (method.ReturnType != void_type)
718 if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
719 cur_stack -= method.GetParameterCount ();
722 private void Emit (OpCode opcode, MethodInfo method, int token)
726 // Might be a DynamicMethod with no declaring type
727 Type declaringType = method.DeclaringType;
728 if (declaringType != null) {
729 if (declaringType.Module == module)
730 add_token_fixup (method);
733 if (method.ReturnType != void_type)
736 if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
737 cur_stack -= method.GetParameterCount ();
740 [CLSCompliant(false)]
741 public void Emit (OpCode opcode, sbyte val)
745 code [code_len++] = (byte)val;
748 public virtual void Emit (OpCode opcode, SignatureHelper shelper)
750 int token = token_gen.GetToken (shelper);
756 public virtual void Emit (OpCode opcode, float val)
758 byte[] s = System.BitConverter.GetBytes (val);
761 if (BitConverter.IsLittleEndian){
762 System.Array.Copy (s, 0, code, code_len, 4);
765 code [code_len++] = s [3];
766 code [code_len++] = s [2];
767 code [code_len++] = s [1];
768 code [code_len++] = s [0];
772 public virtual void Emit (OpCode opcode, string val)
774 int token = token_gen.GetToken (val);
780 public virtual void Emit (OpCode opcode, Type type)
784 emit_int (token_gen.GetToken (type));
787 [MonoTODO ("Do something about varargs method")]
788 public void EmitCall (OpCode opcode, MethodInfo methodinfo, Type[] optionalParamTypes)
790 if (methodinfo == null)
791 throw new ArgumentNullException ("methodinfo can not be null");
792 short value = opcode.Value;
793 if (!(value == OpCodes.Call.Value || value == OpCodes.Callvirt.Value))
794 throw new NotSupportedException ("Only Call and CallVirt are allowed");
795 if (optionalParamTypes != null){
796 if ((methodinfo.CallingConvention & CallingConventions.VarArgs) == 0){
797 throw new InvalidOperationException ("Method is not VarArgs method and optional types were passed");
800 int token = token_gen.GetToken (methodinfo, optionalParamTypes);
801 Emit (opcode, methodinfo, token);
804 Emit (opcode, methodinfo);
807 public void EmitCalli (OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] paramTypes)
809 SignatureHelper helper
810 = SignatureHelper.GetMethodSigHelper (module, 0, unmanagedCallConv, returnType, paramTypes);
811 Emit (opcode, helper);
814 public void EmitCalli (OpCode opcode, CallingConventions callConv, Type returnType, Type[] paramTypes, Type[] optionalParamTypes)
816 if (optionalParamTypes != null)
817 throw new NotImplementedException ();
819 SignatureHelper helper
820 = SignatureHelper.GetMethodSigHelper (module, callConv, 0, returnType, paramTypes);
821 Emit (opcode, helper);
824 public virtual void EmitWriteLine (FieldInfo field)
827 throw new ArgumentNullException ("field");
829 // The MS implementation does not check for valuetypes here but it
830 // should. Also, it should check that if the field is not static,
831 // then it is a member of this type.
833 Emit (OpCodes.Ldsfld, field);
835 Emit (OpCodes.Ldarg_0);
836 Emit (OpCodes.Ldfld, field);
839 typeof (Console).GetMethod ("WriteLine",
840 new Type[1] { field.FieldType }));
843 public virtual void EmitWriteLine (LocalBuilder lbuilder)
845 if (lbuilder == null)
846 throw new ArgumentNullException ("lbuilder");
847 if (lbuilder.LocalType is TypeBuilder)
848 throw new ArgumentException ("Output streams do not support TypeBuilders.");
849 // The MS implementation does not check for valuetypes here but it
851 Emit (OpCodes.Ldloc, lbuilder);
853 typeof (Console).GetMethod ("WriteLine",
854 new Type[1] { lbuilder.LocalType }));
857 public virtual void EmitWriteLine (string val)
859 Emit (OpCodes.Ldstr, val);
861 typeof (Console).GetMethod ("WriteLine",
862 new Type[1] { typeof(string)}));
865 public virtual void EndExceptionBlock ()
867 if (open_blocks == null)
868 open_blocks = new Stack (defaultExceptionStackSize);
870 if (open_blocks.Count <= 0)
871 throw new NotSupportedException ("Not in an exception block");
872 InternalEndClause ();
873 MarkLabel (ex_handlers [cur_block].end);
874 ex_handlers [cur_block].End (code_len);
875 ex_handlers [cur_block].Debug (cur_block);
876 //System.Console.WriteLine ("End Block {0} (handlers: {1})", cur_block, ex_handlers [cur_block].NumHandlers ());
878 if (open_blocks.Count > 0)
879 cur_block = (int)open_blocks.Peek ();
880 //Console.WriteLine ("curblock restored to {0}", cur_block);
881 //throw new NotImplementedException ();
884 public virtual void EndScope ()
887 public virtual void MarkLabel (Label loc)
889 if (loc.label < 0 || loc.label >= num_labels)
890 throw new System.ArgumentException ("The label is not valid");
891 if (labels [loc.label].addr >= 0)
892 throw new System.ArgumentException ("The label was already defined");
893 labels [loc.label].addr = code_len;
894 if (labels [loc.label].maxStack > cur_stack)
895 cur_stack = labels [loc.label].maxStack;
898 public virtual void MarkSequencePoint (ISymbolDocumentWriter document, int startLine,
899 int startColumn, int endLine, int endColumn)
901 if (currentSequence == null || currentSequence.Document != document) {
902 if (sequencePointLists == null)
903 sequencePointLists = new ArrayList ();
904 currentSequence = new SequencePointList (document);
905 sequencePointLists.Add (currentSequence);
908 currentSequence.AddSequencePoint (code_len, startLine, startColumn, endLine, endColumn);
911 internal void GenerateDebugInfo (ISymbolWriter symbolWriter)
913 if (sequencePointLists != null) {
914 SequencePointList first = (SequencePointList) sequencePointLists [0];
915 SequencePointList last = (SequencePointList) sequencePointLists [sequencePointLists.Count - 1];
916 symbolWriter.SetMethodSourceRange (first.Document, first.StartLine, first.StartColumn, last.Document, last.EndLine, last.EndColumn);
918 foreach (SequencePointList list in sequencePointLists)
919 symbolWriter.DefineSequencePoints (list.Document, list.GetOffsets(), list.GetLines(), list.GetColumns(), list.GetEndLines(), list.GetEndColumns());
921 if (locals != null) {
922 foreach (LocalBuilder local in locals) {
923 if (local.Name != null && local.Name.Length > 0) {
924 SignatureHelper sighelper = SignatureHelper.GetLocalVarSigHelper (module);
925 sighelper.AddArgument (local.LocalType);
926 byte[] signature = sighelper.GetSignature ();
927 symbolWriter.DefineLocalVariable (local.Name, FieldAttributes.Public, signature, SymAddressKind.ILOffset, local.position, 0, 0, local.StartOffset, local.EndOffset);
931 sequencePointLists = null;
935 internal bool HasDebugInfo
937 get { return sequencePointLists != null; }
940 public virtual void ThrowException (Type exceptionType)
942 if (exceptionType == null)
943 throw new ArgumentNullException ("exceptionType");
944 if (! ((exceptionType == typeof (Exception)) ||
945 exceptionType.IsSubclassOf (typeof (Exception))))
946 throw new ArgumentException ("Type should be an exception type", "exceptionType");
947 ConstructorInfo ctor = exceptionType.GetConstructor (new Type[0]);
949 throw new ArgumentException ("Type should have a default constructor", "exceptionType");
950 Emit (OpCodes.Newobj, ctor);
951 Emit (OpCodes.Throw);
955 public void UsingNamespace (String usingNamespace)
957 throw new NotImplementedException ();
960 internal void label_fixup ()
962 for (int i = 0; i < num_fixups; ++i) {
964 // Diff is the offset from the end of the jump instruction to the address of the label
965 int diff = labels [fixups [i].label_idx].addr - (fixups [i].pos + fixups [i].offset);
966 if (fixups [i].offset == 1) {
967 code [fixups [i].pos] = (byte)((sbyte) diff);
969 int old_cl = code_len;
970 code_len = fixups [i].pos;
977 internal static int Mono_GetCurrentOffset (ILGenerator ig)
982 void _ILGenerator.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
984 throw new NotImplementedException ();
987 void _ILGenerator.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
989 throw new NotImplementedException ();
992 void _ILGenerator.GetTypeInfoCount (out uint pcTInfo)
994 throw new NotImplementedException ();
997 void _ILGenerator.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
999 throw new NotImplementedException ();
1003 internal class SequencePointList
1005 ISymbolDocumentWriter doc;
1006 SequencePoint[] points;
1008 const int arrayGrow = 10;
1010 public SequencePointList (ISymbolDocumentWriter doc)
1015 public ISymbolDocumentWriter Document {
1019 public int[] GetOffsets()
1021 int[] data = new int [count];
1022 for (int n=0; n<count; n++) data [n] = points[n].Offset;
1025 public int[] GetLines()
1027 int[] data = new int [count];
1028 for (int n=0; n<count; n++) data [n] = points[n].Line;
1031 public int[] GetColumns()
1033 int[] data = new int [count];
1034 for (int n=0; n<count; n++) data [n] = points[n].Col;
1037 public int[] GetEndLines()
1039 int[] data = new int [count];
1040 for (int n=0; n<count; n++) data [n] = points[n].EndLine;
1043 public int[] GetEndColumns()
1045 int[] data = new int [count];
1046 for (int n=0; n<count; n++) data [n] = points[n].EndCol;
1049 public int StartLine {
1050 get { return points[0].Line; }
1052 public int EndLine {
1053 get { return points[count - 1].Line; }
1055 public int StartColumn {
1056 get { return points[0].Col; }
1058 public int EndColumn {
1059 get { return points[count - 1].Col; }
1062 public void AddSequencePoint (int offset, int line, int col, int endLine, int endCol)
1064 SequencePoint s = new SequencePoint ();
1068 s.EndLine = endLine;
1071 if (points == null) {
1072 points = new SequencePoint [arrayGrow];
1073 } else if (count >= points.Length) {
1074 SequencePoint[] temp = new SequencePoint [count + arrayGrow];
1075 Array.Copy (points, temp, points.Length);
1084 struct SequencePoint {