2 using System.Collections;
6 /**************************************************************************/
8 /// Descriptor for an IL instruction
10 internal abstract class CILInstruction {
11 protected static readonly sbyte maxByteVal = 127;
12 protected static readonly sbyte minByteVal = -128;
13 protected static readonly byte leadByte = 0xFE;
14 protected static readonly uint USHeapIndex = 0x70000000;
15 protected static readonly int longInstrStart = (int)Op.arglist;
16 public bool twoByteInstr = false;
20 internal virtual bool Check(MetaData md)
25 internal virtual void Write(FileImage output) { }
29 internal class CILByte : CILInstruction {
32 internal CILByte(byte bVal)
38 internal override void Write(FileImage output)
40 output.Write(byteVal);
45 internal class Instr : CILInstruction {
48 internal Instr(int inst)
50 if (inst >= longInstrStart) {
51 instr = inst - longInstrStart;
60 internal override void Write(FileImage output)
62 //Console.WriteLine("Writing instruction " + instr + " with size " + size);
63 if (twoByteInstr) output.Write(leadByte);
64 output.Write((byte)instr);
69 internal class IntInstr : Instr {
73 internal IntInstr(int inst, int num, bool byteSize) : base(inst)
81 internal sealed override void Write(FileImage output)
85 output.Write((sbyte)val);
92 internal class UIntInstr : Instr {
96 internal UIntInstr(int inst, int num, bool byteSize) : base(inst)
104 internal sealed override void Write(FileImage output)
108 output.Write((byte)val);
110 output.Write((ushort)val);
115 internal class LongInstr : Instr {
118 internal LongInstr(int inst, long l) : base(inst)
124 internal sealed override void Write(FileImage output)
132 internal class FloatInstr : Instr {
135 internal FloatInstr(int inst, float f) : base(inst)
141 internal sealed override void Write(FileImage output)
149 internal class DoubleInstr : Instr {
152 internal DoubleInstr(int inst, double d) : base(inst)
158 internal sealed override void Write(FileImage output)
166 internal class StringInstr : Instr {
171 internal StringInstr(int inst, string str) : base(inst)
177 internal StringInstr (int inst, byte[] str) : base (inst)
183 internal sealed override bool Check(MetaData md)
186 strIndex = md.AddToUSHeap(val);
188 strIndex = md.AddToUSHeap (bval);
192 internal sealed override void Write(FileImage output)
195 output.Write(USHeapIndex | strIndex);
200 internal class LabelInstr : CILInstruction {
203 internal LabelInstr(CILLabel lab)
206 label.AddLabelInstr(this);
210 internal class FieldInstr : Instr {
213 internal FieldInstr(int inst, Field f) : base(inst)
219 internal sealed override void Write(FileImage output)
222 output.Write(field.Token());
227 internal class MethInstr : Instr {
230 internal MethInstr(int inst, Method m) : base(inst)
236 internal sealed override void Write(FileImage output)
239 output.Write(meth.Token());
244 internal class SigInstr : Instr {
247 internal SigInstr(int inst, CalliSig sig) : base(inst)
253 internal sealed override bool Check(MetaData md)
255 md.AddToTable(MDTable.StandAloneSig,signature);
256 signature.BuildTables(md);
260 internal sealed override void Write(FileImage output)
263 output.Write(signature.Token());
267 internal class TypeInstr : Instr {
268 MetaDataElement theType;
270 internal TypeInstr(int inst, Type aType, MetaData md) : base(inst)
272 theType = aType.GetTypeSpec(md);
276 internal sealed override void Write(FileImage output)
279 output.Write(theType.Token());
284 internal class BranchInstr : Instr {
286 private bool shortVer = true;
287 private int target = 0;
289 internal BranchInstr(int inst, CILLabel dst) : base(inst)
292 dest.AddBranch(this);
295 if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
301 internal sealed override bool Check(MetaData md)
303 target = (int)dest.GetLabelOffset() - (int)(offset + size);
307 internal sealed override void Write(FileImage output)
311 output.Write((sbyte)target);
313 output.Write(target);
318 internal class SwitchInstr : Instr {
322 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst)
325 if (cases != null) numCases = (uint)cases.Length;
326 size += 4 + (numCases * 4);
327 for (int i=0; i < numCases; i++) {
328 cases[i].AddBranch(this);
332 internal sealed override void Write(FileImage output)
335 output.Write(numCases);
336 for (int i=0; i < numCases; i++) {
337 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
338 output.Write(target);
344 /**************************************************************************/
346 /// The IL instructions for a method
348 public class CILInstructions {
349 private static readonly uint ExHeaderSize = 4;
350 private static readonly uint FatExClauseSize = 24;
351 private static readonly uint SmlExClauseSize = 12;
352 private static readonly sbyte maxByteVal = 127;
353 private static readonly sbyte minByteVal = -128;
354 private static readonly byte maxUByteVal = 255;
355 private static readonly int smallSize = 64;
356 private static readonly ushort TinyFormat = 0x2;
357 private static readonly ushort FatFormat = 0x3003;
358 private static readonly ushort MoreSects = 0x8;
359 private static readonly ushort InitLocals = 0x10;
360 private static readonly uint FatSize = 12;
361 private static readonly byte FatExceptTable = 0x41;
362 private static readonly byte SmlExceptTable = 0x01;
364 private MetaData metaData;
365 private ArrayList exceptions, blockStack;
366 //private bool codeChecked = false;
367 private static readonly int INITSIZE = 5;
368 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
369 private int tide = 0;
370 private uint offset = 0;
371 private ushort headerFlags = 0;
372 private short maxStack;
373 private uint paddingNeeded = 0;
374 private byte exceptHeader = 0;
376 uint codeSize = 0, exceptSize = 0;
377 bool tinyFormat, fatExceptionFormat = false;
380 get { return offset; }
383 internal CILInstructions(MetaData md)
388 private void AddToBuffer(CILInstruction inst)
390 if (tide >= buffer.Length) {
391 CILInstruction[] tmp = buffer;
392 buffer = new CILInstruction[tmp.Length * 2];
393 for (int i=0; i < tide; i++) {
397 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
398 inst.offset = offset;
400 buffer[tide++] = inst;
404 /// Add a simple IL instruction
406 /// <param name="inst">the IL instruction</param>
407 public void Inst(Op inst)
409 AddToBuffer(new Instr((int)inst));
413 /// Add an IL instruction with an integer parameter
415 /// <param name="inst">the IL instruction</param>
416 /// <param name="val">the integer parameter value</param>
417 public void IntInst(IntOp inst, int val)
419 int instr = (int)inst;
420 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
421 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
423 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
424 (inst == IntOp.unaligned))));
428 /// Add the load long instruction
430 /// <param name="cVal">the long value</param>
431 public void ldc_i8(long cVal)
433 AddToBuffer(new LongInstr(0x21,cVal));
437 /// Add the load float32 instruction
439 /// <param name="cVal">the float value</param>
440 public void ldc_r4(float cVal)
442 AddToBuffer(new FloatInstr(0x22,cVal));
446 /// Add the load float64 instruction
448 /// <param name="cVal">the float value</param>
449 public void ldc_r8(double cVal)
451 AddToBuffer(new DoubleInstr(0x23,cVal));
455 /// Add the load string instruction
457 /// <param name="str">the string value</param>
458 public void ldstr(string str)
460 AddToBuffer(new StringInstr(0x72,str));
464 /// Add the load string instruction
466 public void ldstr (byte[] str)
468 AddToBuffer (new StringInstr (0x72, str));
472 /// Add the calli instruction
474 /// <param name="sig">the signature for the calli</param>
475 public void calli(CalliSig sig)
477 AddToBuffer(new SigInstr(0x29,sig));
481 /// Add a label to the CIL instructions
483 /// <param name="lab">the label to be added</param>
484 public void CodeLabel(CILLabel lab)
486 AddToBuffer(new LabelInstr(lab));
490 /// Add an instruction with a field parameter
492 /// <param name="inst">the CIL instruction</param>
493 /// <param name="f">the field parameter</param>
494 public void FieldInst(FieldOp inst, Field f)
496 AddToBuffer(new FieldInstr((int)inst,f));
500 /// Add an instruction with a method parameter
502 /// <param name="inst">the CIL instruction</param>
503 /// <param name="m">the method parameter</param>
504 public void MethInst(MethodOp inst, Method m)
506 AddToBuffer(new MethInstr((int)inst,m));
510 /// Add an instruction with a type parameter
512 /// <param name="inst">the CIL instruction</param>
513 /// <param name="t">the type argument for the CIL instruction</param>
514 public void TypeInst(TypeOp inst, Type aType)
516 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
520 /// Add a branch instruction
522 /// <param name="inst">the branch instruction</param>
523 /// <param name="lab">the label that is the target of the branch</param>
524 public void Branch(BranchOp inst, CILLabel lab)
526 AddToBuffer(new BranchInstr((int)inst,lab));
530 /// Add a switch instruction
532 /// <param name="labs">the target labels for the switch</param>
533 public void Switch(CILLabel[] labs)
535 AddToBuffer(new SwitchInstr(0x45,labs));
539 /// Add a byte to the CIL instructions (.emitbyte)
541 /// <param name="bVal"></param>
542 public void emitbyte(byte bVal)
544 AddToBuffer(new CILByte(bVal));
548 /// Add an instruction which puts an integer on TOS. This method
549 /// selects the correct instruction based on the value of the integer.
551 /// <param name="i">the integer value</param>
552 public void PushInt(int i)
555 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
556 } else if ((i >= 0) && (i <= 8)) {
557 Op op = (Op)(Op.ldc_i4_0 + i);
558 AddToBuffer(new Instr((int)op));
559 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
560 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
562 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
567 /// Add the instruction to load a long on TOS
569 /// <param name="l">the long value</param>
570 public void PushLong(long l)
572 AddToBuffer(new LongInstr(0x21,l));
576 /// Add an instruction to push the boolean value true on TOS
578 public void PushTrue()
580 AddToBuffer(new Instr((int)Op.ldc_i4_1));
584 /// Add an instruction to push the boolean value false on TOS
586 public void PushFalse()
588 AddToBuffer(new Instr((int)Op.ldc_i4_0));
592 /// Add the instruction to load an argument on TOS. This method
593 /// selects the correct instruction based on the value of argNo
595 /// <param name="argNo">the number of the argument</param>
596 public void LoadArg(int argNo)
599 int op = (int)Op.ldarg_0 + argNo;
600 AddToBuffer(new Instr(op));
601 } else if (argNo <= maxUByteVal) {
602 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
604 AddToBuffer(new UIntInstr(0x09,argNo,false));
609 /// Add the instruction to load the address of an argument on TOS.
610 /// This method selects the correct instruction based on the value
613 /// <param name="argNo">the number of the argument</param>
614 public void LoadArgAdr(int argNo)
616 if (argNo <= maxUByteVal) {
617 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
619 AddToBuffer(new UIntInstr(0x0A,argNo,false));
624 /// Add the instruction to load a local on TOS. This method selects
625 /// the correct instruction based on the value of locNo.
627 /// <param name="locNo">the number of the local to load</param>
628 public void LoadLocal(int locNo)
631 int op = (int)Op.ldloc_0 + locNo;
632 AddToBuffer(new Instr(op));
633 } else if (locNo <= maxUByteVal) {
634 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
636 AddToBuffer(new UIntInstr(0x0C,locNo,false));
641 /// Add the instruction to load the address of a local on TOS.
642 /// This method selects the correct instruction based on the
645 /// <param name="locNo">the number of the local</param>
646 public void LoadLocalAdr(int locNo)
648 if (locNo <= maxUByteVal) {
649 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
651 AddToBuffer(new UIntInstr(0x0D,locNo,false));
656 /// Add the instruction to store to an argument. This method
657 /// selects the correct instruction based on the value of argNo.
659 /// <param name="argNo">the argument to be stored to</param>
660 public void StoreArg(int argNo)
662 if (argNo <= maxUByteVal) {
663 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
665 AddToBuffer(new UIntInstr(0x0B,argNo,false));
670 /// Add the instruction to store to a local. This method selects
671 /// the correct instruction based on the value of locNo.
673 /// <param name="locNo">the local to be stored to</param>
674 public void StoreLocal(int locNo)
677 int op = (int)Op.stloc_0 + locNo;
678 AddToBuffer(new Instr(op));
679 } else if (locNo <= maxUByteVal) {
680 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
682 AddToBuffer(new UIntInstr(0x0E,locNo,false));
687 /// Create a new CIL label. To place the label in the CIL instruction
688 /// stream use CodeLabel.
690 /// <returns>a new CIL label</returns>
691 public CILLabel NewLabel()
693 return new CILLabel();
696 public void AddTryBlock(TryBlock tryBlock)
698 if (exceptions == null)
699 exceptions = new ArrayList();
700 else if (exceptions.Contains(tryBlock)) return;
701 exceptions.Add(tryBlock);
702 tryBlock.ResolveCatchBlocks (metaData);
706 /// Create a new label at this position in the code buffer
708 /// <returns>the label at the current position</returns>
709 public CILLabel NewCodedLabel()
711 CILLabel lab = new CILLabel();
712 AddToBuffer(new LabelInstr(lab));
717 /// Mark this position as the start of a new block
718 /// (try, catch, filter, finally or fault)
720 public void StartBlock()
722 if (blockStack == null) blockStack = new ArrayList();
723 blockStack.Insert(0,NewCodedLabel());
727 /// Mark this position as the end of the last started block and
728 /// make it a try block. This try block is added to the current
729 /// instructions (ie do not need to call AddTryBlock)
731 /// <returns>The try block just ended</returns>
732 public TryBlock EndTryBlock()
734 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
735 blockStack.RemoveAt(0);
741 /// Mark this position as the end of the last started block and
742 /// make it a catch block. This catch block is associated with the
743 /// specified try block.
745 /// <param name="exceptType">the exception type to be caught</param>
746 /// <param name="tryBlock">the try block associated with this catch block</param>
747 public void EndCatchBlock(Class exceptType, TryBlock tryBlock)
749 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
751 tryBlock.AddHandler(catchBlock);
755 /// Mark this position as the end of the last started block and
756 /// make it a filter block. This filter block is associated with the
757 /// specified try block.
759 /// <param name="filterLab">the label where the filter code is</param>
760 /// <param name="tryBlock">the try block associated with this filter block</param>
761 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock)
763 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
764 tryBlock.AddHandler(filBlock);
768 /// Mark this position as the end of the last started block and
769 /// make it a finally block. This finally block is associated with the
770 /// specified try block.
772 /// <param name="tryBlock">the try block associated with this finally block</param>
773 public void EndFinallyBlock(TryBlock tryBlock)
775 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
776 tryBlock.AddHandler(finBlock);
780 /// Mark this position as the end of the last started block and
781 /// make it a fault block. This fault block is associated with the
782 /// specified try block.
784 /// <param name="tryBlock">the try block associated with this fault block</param>
785 public void EndFaultBlock(TryBlock tryBlock)
787 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
788 tryBlock.AddHandler(fBlock);
791 internal uint GetCodeSize()
793 return codeSize + paddingNeeded + exceptSize;
796 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack)
798 if (tide == 0) return;
802 for (int i=0; i < tide; i++) {
803 changed = buffer[i].Check(metaData) || changed;
806 for (int i=1; i < tide; i++) {
807 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
809 offset = buffer[tide-1].offset + buffer[tide-1].size;
813 // Console.WriteLine("codeSize before header added = " + codeSize);
814 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
815 // can use tiny header
816 //Console.WriteLine("Tiny Header");
818 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
820 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
822 //Console.WriteLine("Fat Header");
824 localSigIx = locSigIx;
825 this.maxStack = (short)maxStack;
826 headerFlags = FatFormat;
827 if (exceptions != null) {
828 // Console.WriteLine("Got exceptions");
829 headerFlags |= MoreSects;
830 uint numExceptClauses = 0;
831 for (int i=0; i < exceptions.Count; i++) {
832 TryBlock tryBlock = (TryBlock)exceptions[i];
834 numExceptClauses += (uint)tryBlock.NumHandlers();
835 if (tryBlock.isFat()) fatExceptionFormat = true;
838 uint data_size = ExHeaderSize + numExceptClauses *
839 (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
842 fatExceptionFormat = true;
844 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
845 if (fatExceptionFormat) {
846 // Console.WriteLine("Fat exception format");
847 exceptHeader = FatExceptTable;
848 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
850 // Console.WriteLine("Tiny exception format");
851 exceptHeader = SmlExceptTable;
852 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
854 // Console.WriteLine("exceptSize = " + exceptSize);
856 if (initLocals) headerFlags |= InitLocals;
857 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
860 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
861 // Hex.Short(headerFlags));
864 internal void Write(FileImage output)
866 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
868 // Console.WriteLine("Writing tiny code");
869 output.Write((byte)headerFlags);
871 // Console.WriteLine("Writing fat code");
872 output.Write(headerFlags);
873 output.Write((ushort)maxStack);
874 output.Write(offset);
875 output.Write(localSigIx);
877 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
878 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
879 for (int i=0; i < tide; i++) {
880 buffer[i].Write(output);
882 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
883 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
884 if (exceptions != null) {
885 // Console.WriteLine("Writing exceptions");
886 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
887 output.Write(exceptHeader);
888 output.Write3Bytes((uint)exceptSize);
889 for (int i=0; i < exceptions.Count; i++) {
890 TryBlock tryBlock = (TryBlock)exceptions[i];
891 tryBlock.Write(output,fatExceptionFormat);
898 /**************************************************************************/
899 public abstract class CodeBlock {
901 private static readonly int maxCodeSize = 255;
902 protected CILLabel start, end;
903 protected bool small = true;
905 public CodeBlock(CILLabel start, CILLabel end)
911 internal virtual bool isFat()
913 // Console.WriteLine("block start = " + start.GetLabelOffset() +
914 // " block end = " + end.GetLabelOffset());
915 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
918 internal virtual void Write(FileImage output, bool fatFormat)
920 if (fatFormat) output.Write(start.GetLabelOffset());
921 else output.Write((short)start.GetLabelOffset());
922 uint len = end.GetLabelOffset() - start.GetLabelOffset();
923 if (fatFormat) output.Write(len);
924 else output.Write((byte)len);
930 /// The descriptor for a guarded block (.try)
932 public class TryBlock : CodeBlock {
933 protected bool fatFormat = false;
934 protected int flags = 0;
935 ArrayList handlers = new ArrayList();
938 /// Create a new try block
940 /// <param name="start">start label for the try block</param>
941 /// <param name="end">end label for the try block</param>
942 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
945 /// Add a handler to this try block
947 /// <param name="handler">a handler to be added to the try block</param>
948 public void AddHandler(HandlerBlock handler)
950 flags = handler.GetFlag();
951 handlers.Add(handler);
954 internal void SetSize()
956 fatFormat = base.isFat();
957 if (fatFormat) return;
958 for (int i=0; i < handlers.Count; i++) {
959 HandlerBlock handler = (HandlerBlock)handlers[i];
960 if (handler.isFat()) {
967 internal int NumHandlers()
969 return handlers.Count;
972 internal override bool isFat()
978 internal void ResolveCatchBlocks (MetaData md)
980 for (int i=0; i < handlers.Count; i++) {
981 Catch c = handlers [i] as Catch;
987 internal override void Write(FileImage output, bool fatFormat)
989 // Console.WriteLine("writing exception details");
990 for (int i=0; i < handlers.Count; i++) {
991 // Console.WriteLine("Except block " + i);
992 HandlerBlock handler = (HandlerBlock)handlers[i];
993 if (fatFormat) output.Write(flags);
994 else output.Write((short)flags);
995 // Console.WriteLine("flags = " + Hex.Short(flags));
996 base.Write(output,fatFormat);
997 handler.Write(output,fatFormat);
1002 public abstract class HandlerBlock : CodeBlock {
1004 protected static readonly short ExceptionFlag = 0;
1005 protected static readonly short FilterFlag = 0x01;
1006 protected static readonly short FinallyFlag = 0x02;
1007 protected static readonly short FaultFlag = 0x04;
1009 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
1011 internal virtual short GetFlag() { return ExceptionFlag; }
1013 internal override void Write(FileImage output, bool fatFormat)
1015 base.Write(output,fatFormat);
1021 /// The descriptor for a catch clause (.catch)
1023 public class Catch : HandlerBlock {
1025 MetaDataElement exceptType;
1028 /// Create a new catch clause
1030 /// <param name="except">the exception to be caught</param>
1031 /// <param name="handlerStart">start of the handler code</param>
1032 /// <param name="handlerEnd">end of the handler code</param>
1033 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
1034 : base(handlerStart, handlerEnd)
1036 exceptType = except;
1039 public Catch(Type except, CILLabel handlerStart, CILLabel handlerEnd)
1040 : base(handlerStart,handlerEnd)
1042 exceptType = except;
1045 internal void ResolveType (MetaData md)
1047 exceptType = ((Type) exceptType).GetTypeSpec (md);
1050 internal override void Write(FileImage output, bool fatFormat)
1052 base.Write(output,fatFormat);
1053 output.Write(exceptType.Token());
1058 /// The descriptor for a filter clause (.filter)
1060 public class Filter : HandlerBlock {
1062 CILLabel filterLabel;
1065 /// Create a new filter clause
1067 /// <param name="filterLabel">the label where the filter code starts</param>
1068 /// <param name="handlerStart">the start of the handler code</param>
1069 /// <param name="handlerEnd">the end of the handler code</param>
1070 public Filter(CILLabel filterLabel, CILLabel handlerStart,
1071 CILLabel handlerEnd) : base(handlerStart,handlerEnd)
1073 this.filterLabel = filterLabel;
1076 internal override short GetFlag()
1081 internal override void Write(FileImage output, bool fatFormat)
1083 base.Write(output,fatFormat);
1084 output.Write(filterLabel.GetLabelOffset());
1090 /// Descriptor for a finally block (.finally)
1092 public class Finally : HandlerBlock {
1095 /// Create a new finally clause
1097 /// <param name="finallyStart">start of finally code</param>
1098 /// <param name="finallyEnd">end of finally code</param>
1099 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
1100 : base(finallyStart,finallyEnd) { }
1102 internal override short GetFlag()
1107 internal override void Write(FileImage output, bool fatFormat)
1109 base.Write(output,fatFormat);
1110 output.Write((int)0);
1116 /// Descriptor for a fault block (.fault)
1118 public class Fault : HandlerBlock {
1121 /// Create a new fault clause
1123 /// <param name="faultStart">start of the fault code</param>
1124 /// <param name="faultEnd">end of the fault code</param>
1125 public Fault(CILLabel faultStart, CILLabel faultEnd)
1126 : base(faultStart,faultEnd) { }
1128 internal override short GetFlag()
1133 internal override void Write(FileImage output, bool fatFormat)
1135 base.Write(output,fatFormat);
1136 output.Write((int)0);
1141 /**************************************************************************/
1143 /// Descriptor for the locals for a method
1145 public class LocalSig : Signature {
1147 private static readonly byte LocalSigByte = 0x7;
1150 public LocalSig(Local[] locals)
1152 this.locals = locals;
1153 tabIx = MDTable.StandAloneSig;
1156 internal sealed override void BuildTables(MetaData md)
1159 MemoryStream sig = new MemoryStream();
1160 sig.WriteByte(LocalSigByte);
1161 MetaData.CompressNum((uint)locals.Length,sig);
1162 for (int i=0; i < locals.Length; i++) {
1163 ((Local)locals[i]).TypeSig(sig);
1165 sigIx = md.AddToBlobHeap(sig.ToArray());
1171 /**************************************************************************/
1173 /// Signature for calli instruction
1175 public class CalliSig : Signature {
1177 private static readonly byte Sentinel = 0x41;
1180 Type[] parameters, optParams;
1181 uint numPars = 0, numOptPars = 0;
1184 /// Create a signature for a calli instruction
1186 /// <param name="cconv">calling conventions</param>
1187 /// <param name="retType">return type</param>
1188 /// <param name="pars">parameter types</param>
1189 public CalliSig(CallConv cconv, Type retType, Type[] pars)
1191 tabIx = MDTable.StandAloneSig;
1193 returnType = retType;
1195 if (pars != null) numPars = (uint)pars.Length;
1199 /// Add the optional parameters to a vararg method
1200 /// This method sets the vararg calling convention
1202 /// <param name="optPars">the optional pars for the vararg call</param>
1203 public void AddVarArgs(Type[] optPars)
1205 optParams = optPars;
1206 if (optPars != null) numOptPars = (uint)optPars.Length;
1207 callConv |= CallConv.Vararg;
1211 /// Add extra calling conventions to this callsite signature
1213 /// <param name="cconv"></param>
1214 public void AddCallingConv(CallConv cconv)
1219 internal sealed override void BuildTables(MetaData md)
1222 MemoryStream sig = new MemoryStream();
1223 sig.WriteByte((byte)callConv);
1224 MetaData.CompressNum(numPars+numOptPars,sig);
1225 returnType.TypeSig(sig);
1226 for (int i=0; i < numPars; i++) {
1227 parameters[i].TypeSig(sig);
1229 sigIx = md.AddToBlobHeap(sig.ToArray());
1230 if (numOptPars > 0) {
1231 sig.WriteByte(Sentinel);
1232 for (int i=0; i < numOptPars; i++) {
1233 optParams[i].TypeSig(sig);
1241 /**************************************************************************/
1243 /// Descriptor for a local of a method
1245 public class Local {
1247 private static readonly byte Pinned = 0x45;
1250 bool pinned = false, byref = false;
1253 /// Create a new local variable
1255 /// <param name="lName">name of the local variable</param>
1256 /// <param name="lType">type of the local variable</param>
1257 public Local(string lName, Type lType)
1264 /// Create a new local variable that is byref and/or pinned
1266 /// <param name="lName">local name</param>
1267 /// <param name="lType">local type</param>
1268 /// <param name="byRef">is byref</param>
1269 /// <param name="isPinned">has pinned attribute</param>
1270 public Local(string lName, Type lType, bool byRef, bool isPinned)
1278 internal void TypeSig(MemoryStream str)
1280 if (pinned) str.WriteByte(Pinned);
1286 /**************************************************************************/
1288 /// A label in the IL
1290 public class CILLabel {
1292 CILInstruction branch;
1293 CILInstruction[] multipleBranches;
1295 CILInstruction labInstr;
1300 public CILLabel (uint offset, bool absolute)
1302 this.offset = offset;
1303 this.absolute = absolute;
1306 public CILLabel (uint offset) : this (offset, false)
1315 internal void AddBranch(CILInstruction instr)
1317 if (branch == null) {
1321 if (multipleBranches == null) {
1322 multipleBranches = new CILInstruction[2];
1323 } else if (tide >= multipleBranches.Length) {
1324 CILInstruction[] tmp = multipleBranches;
1325 multipleBranches = new CILInstruction[tmp.Length*2];
1326 for (int i=0; i < tide; i++) {
1327 multipleBranches[i] = tmp[i];
1330 multipleBranches[tide++] = instr;
1333 internal void AddLabelInstr(LabelInstr lInstr)
1338 internal uint GetLabelOffset()
1340 if (absolute) return offset;
1341 if (labInstr == null) return 0;
1342 return labInstr.offset + offset;