| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250 |
- //
- // 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
- //
- // Author:
- // Paolo Molaro ([email protected])
- //
- // (C) 2001 Ximian, Inc. http://www.ximian.com
- //
- #if MONO_FEATURE_SRE
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics.SymbolStore;
- using System.Runtime.InteropServices;
- namespace System.Reflection.Emit {
- internal struct ILExceptionBlock {
- public const int CATCH = 0;
- public const int FILTER = 1;
- public const int FINALLY = 2;
- public const int FAULT = 4;
- public const int FILTER_START = -1;
- internal Type extype;
- internal int type;
- internal int start;
- internal int len;
- internal int filter_offset;
-
- internal void Debug () {
- #if NO
- System.Console.Write ("\ttype="+type.ToString()+" start="+start.ToString()+" len="+len.ToString());
- if (extype != null)
- System.Console.WriteLine (" extype="+extype.ToString());
- else
- System.Console.WriteLine (String.Empty);
- #endif
- }
- }
- internal struct ILExceptionInfo {
- #pragma warning disable 169
- #pragma warning disable 414
- internal ILExceptionBlock[] handlers;
- internal int start;
- internal int len;
- internal Label end;
- #pragma warning restore 169
- #pragma warning restore 414
- internal int NumHandlers ()
- {
- return handlers.Length;
- }
-
- internal void AddCatch (Type extype, int offset)
- {
- int i;
- End (offset);
- add_block (offset);
- i = handlers.Length - 1;
- handlers [i].type = ILExceptionBlock.CATCH;
- handlers [i].start = offset;
- handlers [i].extype = extype;
- }
- internal void AddFinally (int offset)
- {
- int i;
- End (offset);
- add_block (offset);
- i = handlers.Length - 1;
- handlers [i].type = ILExceptionBlock.FINALLY;
- handlers [i].start = offset;
- 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_START;
- handlers [i].extype = null;
- handlers [i].filter_offset = offset;
- }
- internal void End (int offset)
- {
- if (handlers == null)
- return;
- int i = handlers.Length - 1;
- if (i >= 0)
- handlers [i].len = offset - handlers [i].start;
- }
- internal int LastClauseType ()
- {
- if (handlers != null)
- return handlers [handlers.Length-1].type;
- else
- return ILExceptionBlock.CATCH;
- }
- internal void PatchFilterClause (int start)
- {
- if (handlers != null && handlers.Length > 0) {
- handlers [handlers.Length - 1].start = start;
- handlers [handlers.Length - 1].type = ILExceptionBlock.FILTER;
- }
- }
- internal void Debug (int b)
- {
- #if NO
- System.Console.WriteLine ("Handler {0} at {1}, len: {2}", b, start, len);
- for (int i = 0; i < handlers.Length; ++i)
- handlers [i].Debug ();
- #endif
- }
- void add_block (int offset)
- {
- if (handlers != null) {
- int i = handlers.Length;
- ILExceptionBlock[] new_b = new ILExceptionBlock [i + 1];
- System.Array.Copy (handlers, new_b, i);
- handlers = new_b;
- handlers [i].len = offset - handlers [i].start;
- } else {
- handlers = new ILExceptionBlock [1];
- len = offset - start;
- }
- }
- }
-
- internal struct ILTokenInfo {
- public MemberInfo member;
- public int code_pos;
- }
- internal interface TokenGenerator {
- int GetToken (string str);
- int GetToken (MemberInfo member, bool create_open_instance);
- int GetToken (MethodBase method, Type[] opt_param_types);
- int GetToken (SignatureHelper helper);
- }
- #if !MOBILE
- partial class ILGenerator : _ILGenerator
- {
- 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 ();
- }
- }
- #endif
- [StructLayout (LayoutKind.Sequential)]
- public partial class ILGenerator {
- private struct LabelFixup {
- public int offset; // The number of bytes between pos and the
- // offset of the jump
- public int pos; // Where offset of the label is placed
- public int label_idx; // The label to jump to
- };
-
- struct LabelData {
- public LabelData (int addr, int maxStack)
- {
- this.addr = addr;
- this.maxStack = maxStack;
- }
-
- public int addr;
- public int maxStack;
- }
-
- #region Sync with reflection.h
- private byte[] code;
- private int code_len;
- private int max_stack;
- private int cur_stack;
- private LocalBuilder[] locals;
- private ILExceptionInfo[] ex_handlers;
- private int num_token_fixups;
- private ILTokenInfo[] token_fixups;
- #endregion
-
- private LabelData [] labels;
- private int num_labels;
- private LabelFixup[] fixups;
- private int num_fixups;
- internal Module module;
- private int cur_block;
- private Stack open_blocks;
- private TokenGenerator token_gen;
-
- 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 = new byte [size];
- token_fixups = new ILTokenInfo [8];
- module = m;
- this.token_gen = token_gen;
- }
-
- private void add_token_fixup (MemberInfo mi)
- {
- if (num_token_fixups == token_fixups.Length) {
- ILTokenInfo[] ntf = new ILTokenInfo [num_token_fixups * 2];
- token_fixups.CopyTo (ntf, 0);
- token_fixups = ntf;
- }
- token_fixups [num_token_fixups].member = mi;
- token_fixups [num_token_fixups++].code_pos = code_len;
- }
- private void make_room (int nbytes)
- {
- if (code_len + nbytes < code.Length)
- return;
- byte[] new_code = new byte [(code_len + nbytes) * 2 + 128];
- System.Array.Copy (code, 0, new_code, 0, code.Length);
- code = new_code;
- }
- private void emit_int (int val)
- {
- code [code_len++] = (byte) (val & 0xFF);
- code [code_len++] = (byte) ((val >> 8) & 0xFF);
- code [code_len++] = (byte) ((val >> 16) & 0xFF);
- code [code_len++] = (byte) ((val >> 24) & 0xFF);
- }
- /* change to pass by ref to avoid copy */
- private void ll_emit (OpCode opcode)
- {
- /*
- * there is already enough room allocated in code.
- */
- // access op1 and op2 directly since the Value property is useless
- if (opcode.Size == 2)
- code [code_len++] = opcode.op1;
- code [code_len++] = opcode.op2;
- /*
- * We should probably keep track of stack needs here.
- * Or we may want to run the verifier on the code before saving it
- * (this may be needed anyway when the ILGenerator is not used...).
- */
- switch (opcode.StackBehaviourPush) {
- case StackBehaviour.Push1:
- case StackBehaviour.Pushi:
- case StackBehaviour.Pushi8:
- case StackBehaviour.Pushr4:
- case StackBehaviour.Pushr8:
- case StackBehaviour.Pushref:
- case StackBehaviour.Varpush: /* again we are conservative and assume it pushes 1 */
- cur_stack ++;
- break;
- case StackBehaviour.Push1_push1:
- cur_stack += 2;
- break;
- }
- if (max_stack < cur_stack)
- max_stack = cur_stack;
- /*
- * Note that we adjust for the pop behaviour _after_ setting max_stack.
- */
- switch (opcode.StackBehaviourPop) {
- case StackBehaviour.Varpop:
- break; /* we are conservative and assume it doesn't decrease the stack needs */
- case StackBehaviour.Pop1:
- case StackBehaviour.Popi:
- case StackBehaviour.Popref:
- cur_stack --;
- break;
- case StackBehaviour.Pop1_pop1:
- case StackBehaviour.Popi_pop1:
- case StackBehaviour.Popi_popi:
- case StackBehaviour.Popi_popi8:
- case StackBehaviour.Popi_popr4:
- case StackBehaviour.Popi_popr8:
- case StackBehaviour.Popref_pop1:
- case StackBehaviour.Popref_popi:
- cur_stack -= 2;
- break;
- case StackBehaviour.Popi_popi_popi:
- case StackBehaviour.Popref_popi_popi:
- case StackBehaviour.Popref_popi_popi8:
- case StackBehaviour.Popref_popi_popr4:
- case StackBehaviour.Popref_popi_popr8:
- case StackBehaviour.Popref_popi_popref:
- cur_stack -= 3;
- break;
- }
- }
- private static int target_len (OpCode opcode)
- {
- if (opcode.OperandType == OperandType.InlineBrTarget)
- return 4;
- return 1;
- }
- private void InternalEndClause ()
- {
- switch (ex_handlers [cur_block].LastClauseType ()) {
- case ILExceptionBlock.CATCH:
- case ILExceptionBlock.FILTER:
- case ILExceptionBlock.FILTER_START:
- // how could we optimize code size here?
- Emit (OpCodes.Leave, ex_handlers [cur_block].end);
- break;
- case ILExceptionBlock.FAULT:
- case ILExceptionBlock.FINALLY:
- Emit (OpCodes.Endfinally);
- 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");
- if (exceptionType != null && exceptionType.IsUserType)
- throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported.");
- if (ex_handlers [cur_block].LastClauseType () == ILExceptionBlock.FILTER_START) {
- if (exceptionType != null)
- throw new ArgumentException ("Do not supply an exception type for filter clause");
- Emit (OpCodes.Endfilter);
- ex_handlers [cur_block].PatchFilterClause (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);
- }
- public virtual void BeginExceptFilterBlock ()
- {
- 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;
- ILExceptionInfo[] new_ex = new ILExceptionInfo [cur_block + 1];
- System.Array.Copy (ex_handlers, new_ex, cur_block);
- ex_handlers = new_ex;
- } else {
- ex_handlers = new ILExceptionInfo [1];
- cur_block = 0;
- }
- open_blocks.Push (cur_block);
- ex_handlers [cur_block].start = code_len;
- return ex_handlers [cur_block].end = DefineLabel ();
- }
- 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");
- if (ex_handlers [cur_block].LastClauseType () == ILExceptionBlock.FILTER_START) {
- Emit (OpCodes.Leave, ex_handlers [cur_block].end);
- ex_handlers [cur_block].PatchFilterClause (code_len);
- }
-
- InternalEndClause ();
- //System.Console.WriteLine ("Begin fault Block");
- 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 ();
- if (ex_handlers [cur_block].LastClauseType () == ILExceptionBlock.FILTER_START) {
- Emit (OpCodes.Leave, ex_handlers [cur_block].end);
- ex_handlers [cur_block].PatchFilterClause (code_len);
- }
- //System.Console.WriteLine ("Begin finally Block");
- ex_handlers [cur_block].AddFinally (code_len);
- }
-
- public virtual void BeginScope ()
- { }
- public virtual LocalBuilder DeclareLocal (Type localType)
- {
- return DeclareLocal (localType, false);
- }
- public virtual LocalBuilder DeclareLocal (Type localType, bool pinned)
- {
- if (localType == null)
- throw new ArgumentNullException ("localType");
- if (localType.IsUserType)
- throw new NotSupportedException ("User defined subclasses of System.Type are not yet supported.");
- 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);
- new_l [locals.Length] = res;
- locals = new_l;
- } else {
- locals = new LocalBuilder [1];
- locals [0] = res;
- }
- res.position = (ushort)(locals.Length - 1);
- return res;
- }
-
- public virtual Label DefineLabel ()
- {
- if (labels == null)
- labels = new LabelData [defaultLabelsSize];
- else if (num_labels >= labels.Length) {
- LabelData [] t = new LabelData [labels.Length * 2];
- Array.Copy (labels, t, labels.Length);
- labels = t;
- }
-
- labels [num_labels] = new LabelData (-1, 0);
-
- return new Label (num_labels++);
- }
-
- public virtual void Emit (OpCode opcode)
- {
- make_room (2);
- ll_emit (opcode);
- }
-
- public virtual void Emit (OpCode opcode, Byte arg)
- {
- make_room (3);
- ll_emit (opcode);
- code [code_len++] = arg;
- }
-
- [ComVisible (true)]
- public virtual void Emit (OpCode opcode, ConstructorInfo con)
- {
- int token = token_gen.GetToken (con, true);
- make_room (6);
- ll_emit (opcode);
- if (con.DeclaringType.Module == module || (con is ConstructorOnTypeBuilderInst) || (con is ConstructorBuilder))
- add_token_fixup (con);
- emit_int (token);
-
- if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
- cur_stack -= con.GetParametersCount ();
- }
-
- public virtual void Emit (OpCode opcode, double arg)
- {
- byte[] s = System.BitConverter.GetBytes (arg);
- make_room (10);
- ll_emit (opcode);
- if (BitConverter.IsLittleEndian){
- System.Array.Copy (s, 0, code, code_len, 8);
- code_len += 8;
- } else {
- code [code_len++] = s [7];
- code [code_len++] = s [6];
- code [code_len++] = s [5];
- code [code_len++] = s [4];
- code [code_len++] = s [3];
- code [code_len++] = s [2];
- code [code_len++] = s [1];
- code [code_len++] = s [0];
- }
- }
-
- public virtual void Emit (OpCode opcode, FieldInfo field)
- {
- int token = token_gen.GetToken (field, true);
- make_room (6);
- ll_emit (opcode);
- if (field.DeclaringType.Module == module || (field is FieldOnTypeBuilderInst) || (field is FieldBuilder))
- add_token_fixup (field);
- emit_int (token);
- }
-
- public virtual void Emit (OpCode opcode, Int16 arg)
- {
- make_room (4);
- ll_emit (opcode);
- code [code_len++] = (byte) (arg & 0xFF);
- code [code_len++] = (byte) ((arg >> 8) & 0xFF);
- }
-
- public virtual void Emit (OpCode opcode, int arg)
- {
- make_room (6);
- ll_emit (opcode);
- emit_int (arg);
- }
-
- public virtual void Emit (OpCode opcode, long arg)
- {
- make_room (10);
- ll_emit (opcode);
- code [code_len++] = (byte) (arg & 0xFF);
- code [code_len++] = (byte) ((arg >> 8) & 0xFF);
- code [code_len++] = (byte) ((arg >> 16) & 0xFF);
- code [code_len++] = (byte) ((arg >> 24) & 0xFF);
- code [code_len++] = (byte) ((arg >> 32) & 0xFF);
- code [code_len++] = (byte) ((arg >> 40) & 0xFF);
- code [code_len++] = (byte) ((arg >> 48) & 0xFF);
- code [code_len++] = (byte) ((arg >> 56) & 0xFF);
- }
-
- public virtual void Emit (OpCode opcode, Label label)
- {
- int tlen = target_len (opcode);
- make_room (6);
- ll_emit (opcode);
- if (cur_stack > labels [label.label].maxStack)
- labels [label.label].maxStack = cur_stack;
-
- if (fixups == null)
- fixups = new LabelFixup [defaultFixupSize];
- else if (num_fixups >= fixups.Length) {
- LabelFixup[] newf = new LabelFixup [fixups.Length * 2];
- System.Array.Copy (fixups, newf, fixups.Length);
- fixups = newf;
- }
- fixups [num_fixups].offset = tlen;
- fixups [num_fixups].pos = code_len;
- fixups [num_fixups].label_idx = label.label;
- num_fixups++;
- code_len += tlen;
- }
-
- public virtual void Emit (OpCode opcode, Label[] labels)
- {
- if (labels == null)
- throw new ArgumentNullException ("labels");
- /* opcode needs to be switch. */
- int count = labels.Length;
- make_room (6 + count * 4);
- ll_emit (opcode);
- for (int i = 0; i < count; ++i)
- if (cur_stack > this.labels [labels [i].label].maxStack)
- this.labels [labels [i].label].maxStack = cur_stack;
- emit_int (count);
- if (fixups == null)
- fixups = new LabelFixup [defaultFixupSize + count];
- else if (num_fixups + count >= fixups.Length) {
- LabelFixup[] newf = new LabelFixup [count + fixups.Length * 2];
- System.Array.Copy (fixups, newf, fixups.Length);
- fixups = newf;
- }
-
- // ECMA 335, Partition III, p94 (7-10)
- //
- // The switch instruction implements a jump table. The format of
- // the instruction is an unsigned int32 representing the number of targets N,
- // followed by N int32 values specifying jump targets: these targets are
- // represented as offsets (positive or negative) from the beginning of the
- // instruction following this switch instruction.
- //
- // We must make sure it gets an offset from the *end* of the last label
- // (eg, the beginning of the instruction following this).
- //
- // remaining is the number of bytes from the current instruction to the
- // instruction that will be emitted.
-
- for (int i = 0, remaining = count * 4; i < count; ++i, remaining -= 4) {
- fixups [num_fixups].offset = remaining;
- fixups [num_fixups].pos = code_len;
- fixups [num_fixups].label_idx = labels [i].label;
- num_fixups++;
- code_len += 4;
- }
- }
- public virtual void Emit (OpCode opcode, LocalBuilder local)
- {
- if (local == null)
- throw new ArgumentNullException ("local");
- if (local.ilgen != this)
- throw new ArgumentException ("Trying to emit a local from a different ILGenerator.");
- uint pos = local.position;
- bool load_addr = false;
- bool is_store = false;
- bool is_load = false;
- make_room (6);
- /* inline the code from ll_emit () to optimize il code size */
- if (opcode.StackBehaviourPop == StackBehaviour.Pop1) {
- cur_stack --;
- is_store = true;
- } else if (opcode.StackBehaviourPush == StackBehaviour.Push1 || opcode.StackBehaviourPush == StackBehaviour.Pushi) {
- cur_stack++;
- is_load = true;
- if (cur_stack > max_stack)
- max_stack = cur_stack;
- load_addr = opcode.StackBehaviourPush == StackBehaviour.Pushi;
- }
- if (load_addr) {
- if (pos < 256) {
- code [code_len++] = (byte)0x12;
- code [code_len++] = (byte)pos;
- } else {
- code [code_len++] = (byte)0xfe;
- code [code_len++] = (byte)0x0d;
- code [code_len++] = (byte)(pos & 0xff);
- code [code_len++] = (byte)((pos >> 8) & 0xff);
- }
- } else {
- if (is_store) {
- if (pos < 4) {
- code [code_len++] = (byte)(0x0a + pos);
- } else if (pos < 256) {
- code [code_len++] = (byte)0x13;
- code [code_len++] = (byte)pos;
- } else {
- code [code_len++] = (byte)0xfe;
- code [code_len++] = (byte)0x0e;
- code [code_len++] = (byte)(pos & 0xff);
- code [code_len++] = (byte)((pos >> 8) & 0xff);
- }
- } else if (is_load) {
- if (pos < 4) {
- code [code_len++] = (byte)(0x06 + pos);
- } else if (pos < 256) {
- code [code_len++] = (byte)0x11;
- code [code_len++] = (byte)pos;
- } else {
- code [code_len++] = (byte)0xfe;
- code [code_len++] = (byte)0x0c;
- code [code_len++] = (byte)(pos & 0xff);
- code [code_len++] = (byte)((pos >> 8) & 0xff);
- }
- } else {
- ll_emit (opcode);
- }
- }
- }
- public virtual void Emit (OpCode opcode, MethodInfo meth)
- {
- if (meth == null)
- throw new ArgumentNullException ("meth");
- // For compatibility with MS
- if ((meth is DynamicMethod) && ((opcode == OpCodes.Ldftn) || (opcode == OpCodes.Ldvirtftn) || (opcode == OpCodes.Ldtoken)))
- throw new ArgumentException ("Ldtoken, Ldftn and Ldvirtftn OpCodes cannot target DynamicMethods.");
- int token = token_gen.GetToken (meth, true);
- make_room (6);
- ll_emit (opcode);
- Type declaringType = meth.DeclaringType;
- // Might be a DynamicMethod with no declaring type
- if (declaringType != null) {
- if (declaringType.Module == module || meth is MethodOnTypeBuilderInst || meth is MethodBuilder)
- add_token_fixup (meth);
- }
- emit_int (token);
- if (meth.ReturnType != typeof (void))
- cur_stack ++;
- if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
- cur_stack -= meth.GetParametersCount ();
- }
- private void Emit (OpCode opcode, MethodInfo method, int token)
- {
- make_room (6);
- ll_emit (opcode);
- // Might be a DynamicMethod with no declaring type
- Type declaringType = method.DeclaringType;
- if (declaringType != null) {
- if (declaringType.Module == module || method is MethodBuilder)
- add_token_fixup (method);
- }
- emit_int (token);
- if (method.ReturnType != typeof (void))
- cur_stack ++;
- if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
- cur_stack -= method.GetParametersCount ();
- }
- [CLSCompliant(false)]
- public void Emit (OpCode opcode, sbyte arg)
- {
- make_room (3);
- ll_emit (opcode);
- code [code_len++] = (byte)arg;
- }
- public virtual void Emit (OpCode opcode, SignatureHelper signature)
- {
- int token = token_gen.GetToken (signature);
- make_room (6);
- ll_emit (opcode);
- emit_int (token);
- }
- public virtual void Emit (OpCode opcode, float arg)
- {
- byte[] s = System.BitConverter.GetBytes (arg);
- make_room (6);
- ll_emit (opcode);
- if (BitConverter.IsLittleEndian){
- System.Array.Copy (s, 0, code, code_len, 4);
- code_len += 4;
- } else {
- code [code_len++] = s [3];
- code [code_len++] = s [2];
- code [code_len++] = s [1];
- code [code_len++] = s [0];
- }
- }
- public virtual void Emit (OpCode opcode, string str)
- {
- int token = token_gen.GetToken (str);
- make_room (6);
- ll_emit (opcode);
- emit_int (token);
- }
- public virtual void Emit (OpCode opcode, Type cls)
- {
- if (cls != null && cls.IsByRef)
- throw new ArgumentException ("Cannot get TypeToken for a ByRef type.");
- make_room (6);
- ll_emit (opcode);
- int token = token_gen.GetToken (cls, opcode != OpCodes.Ldtoken);
- if (cls is TypeBuilderInstantiation || cls is SymbolType || cls is TypeBuilder || cls is GenericTypeParameterBuilder || cls is EnumBuilder)
- add_token_fixup (cls);
- emit_int (token);
- }
- [MonoLimitation ("vararg methods are not supported")]
- public virtual void EmitCall (OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
- {
- if (methodInfo == null)
- throw new ArgumentNullException ("methodInfo");
- short value = opcode.Value;
- if (!(value == OpCodes.Call.Value || value == OpCodes.Callvirt.Value))
- throw new NotSupportedException ("Only Call and CallVirt are allowed");
- if ((methodInfo.CallingConvention & CallingConventions.VarArgs) == 0)
- optionalParameterTypes = null;
- if (optionalParameterTypes != null){
- if ((methodInfo.CallingConvention & CallingConventions.VarArgs) == 0){
- throw new InvalidOperationException ("Method is not VarArgs method and optional types were passed");
- }
- int token = token_gen.GetToken (methodInfo, optionalParameterTypes);
- Emit (opcode, methodInfo, token);
- return;
- }
- Emit (opcode, methodInfo);
- }
- public virtual void EmitCalli (OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes)
- {
- // GetMethodSigHelper expects a ModuleBuilder or null, and module might be
- // a normal module when using dynamic methods.
- SignatureHelper helper = SignatureHelper.GetMethodSigHelper (module as ModuleBuilder, 0, unmanagedCallConv, returnType, parameterTypes);
- Emit (opcode, helper);
- }
- public virtual void EmitCalli (OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
- {
- if (optionalParameterTypes != null)
- throw new NotImplementedException ();
- SignatureHelper helper = SignatureHelper.GetMethodSigHelper (module as ModuleBuilder, callingConvention, 0, returnType, parameterTypes);
- Emit (opcode, helper);
- }
-
- public virtual void EmitWriteLine (FieldInfo fld)
- {
- if (fld == null)
- throw new ArgumentNullException ("fld");
-
- // The MS implementation does not check for valuetypes here but it
- // should. Also, it should check that if the field is not static,
- // then it is a member of this type.
- if (fld.IsStatic)
- Emit (OpCodes.Ldsfld, fld);
- else {
- Emit (OpCodes.Ldarg_0);
- Emit (OpCodes.Ldfld, fld);
- }
- Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type[1] { fld.FieldType }));
- }
- public virtual void EmitWriteLine (LocalBuilder localBuilder)
- {
- if (localBuilder == null)
- throw new ArgumentNullException ("localBuilder");
- if (localBuilder.LocalType is TypeBuilder)
- throw new ArgumentException ("Output streams do not support TypeBuilders.");
- // The MS implementation does not check for valuetypes here but it
- // should.
- Emit (OpCodes.Ldloc, localBuilder);
- Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type[1] { localBuilder.LocalType }));
- }
-
- public virtual void EmitWriteLine (string value)
- {
- Emit (OpCodes.Ldstr, value);
- Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type[1] { typeof(string)}));
- }
- 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");
- if (ex_handlers [cur_block].LastClauseType () == ILExceptionBlock.FILTER_START)
- throw new InvalidOperationException ("Incorrect code generation for exception block.");
- InternalEndClause ();
- MarkLabel (ex_handlers [cur_block].end);
- ex_handlers [cur_block].End (code_len);
- ex_handlers [cur_block].Debug (cur_block);
- //System.Console.WriteLine ("End Block {0} (handlers: {1})", cur_block, ex_handlers [cur_block].NumHandlers ());
- open_blocks.Pop ();
- if (open_blocks.Count > 0)
- cur_block = (int)open_blocks.Peek ();
- //Console.WriteLine ("curblock restored to {0}", cur_block);
- //throw new NotImplementedException ();
- }
- public virtual void EndScope ()
- { }
- public virtual void MarkLabel (Label loc)
- {
- if (loc.label < 0 || loc.label >= num_labels)
- throw new System.ArgumentException ("The label is not valid");
- if (labels [loc.label].addr >= 0)
- throw new System.ArgumentException ("The label was already defined");
- labels [loc.label].addr = code_len;
- if (labels [loc.label].maxStack > cur_stack)
- cur_stack = labels [loc.label].maxStack;
- }
- public virtual void MarkSequencePoint (ISymbolDocumentWriter document, int startLine,
- int startColumn, int endLine, int endColumn)
- {
- 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 as ModuleBuilder);
- 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 excType)
- {
- if (excType == null)
- throw new ArgumentNullException ("excType");
- if (! ((excType == typeof (Exception)) ||
- excType.IsSubclassOf (typeof (Exception))))
- throw new ArgumentException ("Type should be an exception type", "excType");
- ConstructorInfo ctor = excType.GetConstructor (Type.EmptyTypes);
- if (ctor == null)
- throw new ArgumentException ("Type should have a default constructor", "excType");
- Emit (OpCodes.Newobj, ctor);
- Emit (OpCodes.Throw);
- }
- [MonoTODO("Not implemented")]
- public virtual void UsingNamespace (String usingNamespace)
- {
- throw new NotImplementedException ();
- }
- internal void label_fixup (MethodBase mb)
- {
- for (int i = 0; i < num_fixups; ++i) {
- if (labels [fixups [i].label_idx].addr < 0)
- throw new ArgumentException (string.Format ("Label #{0} is not marked in method `{1}'", fixups [i].label_idx + 1, mb.Name));
- // Diff is the offset from the end of the jump instruction to the address of the label
- int diff = labels [fixups [i].label_idx].addr - (fixups [i].pos + fixups [i].offset);
- if (fixups [i].offset == 1) {
- code [fixups [i].pos] = (byte)((sbyte) diff);
- } else {
- int old_cl = code_len;
- code_len = fixups [i].pos;
- emit_int (diff);
- code_len = old_cl;
- }
- }
- }
- internal void FixupTokens (Dictionary<int, int> token_map, Dictionary<int, MemberInfo> member_map) {
- for (int i = 0; i < num_token_fixups; ++i) {
- int pos = token_fixups [i].code_pos;
- int old_token = code [pos] | (code [pos + 1] << 8) | (code [pos + 2] << 16) | (code [pos + 3] << 24);
- int new_token;
- if (token_map.TryGetValue (old_token, out new_token)) {
- token_fixups [i].member = member_map [old_token];
- int old_cl = code_len;
- code_len = pos;
- emit_int (new_token);
- code_len = old_cl;
- }
- }
- }
- // Used by MethodBuilder.SetMethodBody
- internal void SetExceptionHandlers (ILExceptionInfo[] exHandlers) {
- this.ex_handlers = exHandlers;
- }
- // Used by MethodBuilder.SetMethodBody
- internal void SetTokenFixups (ILTokenInfo[] tokenFixups) {
- this.token_fixups = tokenFixups;
- }
- // Used by DynamicILGenerator and MethodBuilder.SetMethodBody
- internal void SetCode (byte[] code, int max_stack) {
- // Make a copy to avoid possible security problems
- this.code = (byte[])code.Clone ();
- this.code_len = code.Length;
- this.max_stack = max_stack;
- this.cur_stack = 0;
- }
- internal unsafe void SetCode (byte *code, int code_size, int max_stack) {
- // Make a copy to avoid possible security problems
- this.code = new byte [code_size];
- for (int i = 0; i < code_size; ++i)
- this.code [i] = code [i];
- this.code_len = code_size;
- this.max_stack = max_stack;
- this.cur_stack = 0;
- }
- internal void Init (byte[] il, int maxStack, byte[] localSignature,
- IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
- {
- SetCode (il, maxStack);
- // FIXME: Process local signature
- // Process exception handlers
- if (exceptionHandlers != null) {
- // Group exception handlers by try blocks
- var tryBlocks = new Dictionary <Tuple<int, int>, List<ExceptionHandler>> ();
- foreach (var h in exceptionHandlers) {
- List<ExceptionHandler> list;
- var key = new Tuple <int, int> (h.TryOffset, h.TryLength);
- if (!tryBlocks.TryGetValue (key, out list)) {
- list = new List<ExceptionHandler> ();
- tryBlocks.Add (key, list);
- }
- list.Add (h);
- }
- // Generate ILExceptionInfo from tryBlocks
- var infos = new List<ILExceptionInfo> ();
- foreach (var kv in tryBlocks) {
- var info = new ILExceptionInfo () {
- start = kv.Key.Item1,
- len = kv.Key.Item2,
- handlers = new ILExceptionBlock [kv.Value.Count],
- };
- infos.Add (info);
- var i = 0;
- foreach (var b in kv.Value) {
- info.handlers [i++] = new ILExceptionBlock () {
- start = b.HandlerOffset,
- len = b.HandlerLength,
- filter_offset = b.FilterOffset,
- type = (int) b.Kind,
- extype = module.ResolveType (b.ExceptionTypeToken),
- };
- }
- }
- SetExceptionHandlers (infos.ToArray ());
- }
- // Process token fixups
- if (tokenFixups != null) {
- var tokenInfos = new List<ILTokenInfo> ();
- foreach (var pos in tokenFixups) {
- var token = (int) BitConverter.ToUInt32 (il, pos);
- var tokenInfo = new ILTokenInfo () {
- code_pos = pos,
- member = ((ModuleBuilder) module).ResolveOrGetRegisteredToken (token, null, null)
- };
- tokenInfos.Add (tokenInfo);
- }
- SetTokenFixups (tokenInfos.ToArray ());
- }
- }
- internal TokenGenerator TokenGenerator {
- get {
- return token_gen;
- }
- }
- // Still used by symbolwriter
- [Obsolete ("Use ILOffset", true)]
- internal static int Mono_GetCurrentOffset (ILGenerator ig)
- {
- return ig.code_len;
- }
- public
- virtual int ILOffset {
- get { return code_len; }
- }
- }
-
- 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;
- }
- }
- #endif
|