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 static readonly byte longInstrOffset = 13;
288 private int target = 0;
290 internal BranchInstr(int inst, CILLabel dst) : base(inst)
293 dest.AddBranch(this);
296 if (inst >= (int) BranchOp.br && inst != (int) BranchOp.leave_s) {
302 internal sealed override bool Check(MetaData md)
304 target = (int)dest.GetLabelOffset() - (int)(offset + size);
308 internal sealed override void Write(FileImage output)
312 output.Write((sbyte)target);
314 output.Write(target);
319 internal class SwitchInstr : Instr {
323 internal SwitchInstr(int inst, CILLabel[] dsts) : base(inst)
326 if (cases != null) numCases = (uint)cases.Length;
327 size += 4 + (numCases * 4);
328 for (int i=0; i < numCases; i++) {
329 cases[i].AddBranch(this);
333 internal sealed override void Write(FileImage output)
336 output.Write(numCases);
337 for (int i=0; i < numCases; i++) {
338 int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
339 output.Write(target);
345 /**************************************************************************/
347 /// The IL instructions for a method
349 public class CILInstructions {
350 private static readonly uint ExHeaderSize = 4;
351 private static readonly uint FatExClauseSize = 24;
352 private static readonly uint SmlExClauseSize = 12;
353 private static readonly sbyte maxByteVal = 127;
354 private static readonly sbyte minByteVal = -128;
355 private static readonly byte maxUByteVal = 255;
356 private static readonly int smallSize = 64;
357 private static readonly ushort TinyFormat = 0x2;
358 private static readonly ushort FatFormat = 0x3003;
359 private static readonly ushort MoreSects = 0x8;
360 private static readonly ushort InitLocals = 0x10;
361 private static readonly uint FatSize = 12;
362 private static readonly uint FatWords = FatSize/4;
363 private static readonly byte FatExceptTable = 0x41;
364 private static readonly byte SmlExceptTable = 0x01;
366 private MetaData metaData;
367 private ArrayList exceptions, blockStack;
368 //private bool codeChecked = false;
369 private static readonly int INITSIZE = 5;
370 private CILInstruction[] buffer = new CILInstruction[INITSIZE];
371 private int tide = 0;
372 private uint offset = 0;
373 private ushort headerFlags = 0;
374 private short maxStack;
375 private uint paddingNeeded = 0;
376 private byte exceptHeader = 0;
378 uint codeSize = 0, exceptSize = 0;
379 bool tinyFormat, fatExceptionFormat = false;
382 get { return offset; }
385 internal CILInstructions(MetaData md)
390 private void AddToBuffer(CILInstruction inst)
392 if (tide >= buffer.Length) {
393 CILInstruction[] tmp = buffer;
394 buffer = new CILInstruction[tmp.Length * 2];
395 for (int i=0; i < tide; i++) {
399 //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
400 inst.offset = offset;
402 buffer[tide++] = inst;
406 /// Add a simple IL instruction
408 /// <param name="inst">the IL instruction</param>
409 public void Inst(Op inst)
411 AddToBuffer(new Instr((int)inst));
415 /// Add an IL instruction with an integer parameter
417 /// <param name="inst">the IL instruction</param>
418 /// <param name="val">the integer parameter value</param>
419 public void IntInst(IntOp inst, int val)
421 int instr = (int)inst;
422 if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4))
423 AddToBuffer(new IntInstr(instr,val,(inst == IntOp.ldc_i4_s)));
425 AddToBuffer(new UIntInstr(instr,val,((inst < IntOp.ldc_i4_s) ||
426 (inst == IntOp.unaligned))));
430 /// Add the load long instruction
432 /// <param name="cVal">the long value</param>
433 public void ldc_i8(long cVal)
435 AddToBuffer(new LongInstr(0x21,cVal));
439 /// Add the load float32 instruction
441 /// <param name="cVal">the float value</param>
442 public void ldc_r4(float cVal)
444 AddToBuffer(new FloatInstr(0x22,cVal));
448 /// Add the load float64 instruction
450 /// <param name="cVal">the float value</param>
451 public void ldc_r8(double cVal)
453 AddToBuffer(new DoubleInstr(0x23,cVal));
457 /// Add the load string instruction
459 /// <param name="str">the string value</param>
460 public void ldstr(string str)
462 AddToBuffer(new StringInstr(0x72,str));
466 /// Add the load string instruction
468 public void ldstr (byte[] str)
470 AddToBuffer (new StringInstr (0x72, str));
474 /// Add the calli instruction
476 /// <param name="sig">the signature for the calli</param>
477 public void calli(CalliSig sig)
479 AddToBuffer(new SigInstr(0x29,sig));
483 /// Add a label to the CIL instructions
485 /// <param name="lab">the label to be added</param>
486 public void CodeLabel(CILLabel lab)
488 AddToBuffer(new LabelInstr(lab));
492 /// Add an instruction with a field parameter
494 /// <param name="inst">the CIL instruction</param>
495 /// <param name="f">the field parameter</param>
496 public void FieldInst(FieldOp inst, Field f)
498 AddToBuffer(new FieldInstr((int)inst,f));
502 /// Add an instruction with a method parameter
504 /// <param name="inst">the CIL instruction</param>
505 /// <param name="m">the method parameter</param>
506 public void MethInst(MethodOp inst, Method m)
508 AddToBuffer(new MethInstr((int)inst,m));
512 /// Add an instruction with a type parameter
514 /// <param name="inst">the CIL instruction</param>
515 /// <param name="t">the type argument for the CIL instruction</param>
516 public void TypeInst(TypeOp inst, Type aType)
518 AddToBuffer(new TypeInstr((int)inst,aType,metaData));
522 /// Add a branch instruction
524 /// <param name="inst">the branch instruction</param>
525 /// <param name="lab">the label that is the target of the branch</param>
526 public void Branch(BranchOp inst, CILLabel lab)
528 AddToBuffer(new BranchInstr((int)inst,lab));
532 /// Add a switch instruction
534 /// <param name="labs">the target labels for the switch</param>
535 public void Switch(CILLabel[] labs)
537 AddToBuffer(new SwitchInstr(0x45,labs));
541 /// Add a byte to the CIL instructions (.emitbyte)
543 /// <param name="bVal"></param>
544 public void emitbyte(byte bVal)
546 AddToBuffer(new CILByte(bVal));
550 /// Add an instruction which puts an integer on TOS. This method
551 /// selects the correct instruction based on the value of the integer.
553 /// <param name="i">the integer value</param>
554 public void PushInt(int i)
557 AddToBuffer(new Instr((int)Op.ldc_i4_m1));
558 } else if ((i >= 0) && (i <= 8)) {
559 Op op = (Op)(Op.ldc_i4_0 + i);
560 AddToBuffer(new Instr((int)op));
561 } else if ((i >= minByteVal) && (i <= maxByteVal)) {
562 AddToBuffer(new IntInstr((int)IntOp.ldc_i4_s,i,true));
564 AddToBuffer(new IntInstr((int)IntOp.ldc_i4,i,false));
569 /// Add the instruction to load a long on TOS
571 /// <param name="l">the long value</param>
572 public void PushLong(long l)
574 AddToBuffer(new LongInstr(0x21,l));
578 /// Add an instruction to push the boolean value true on TOS
580 public void PushTrue()
582 AddToBuffer(new Instr((int)Op.ldc_i4_1));
586 /// Add an instruction to push the boolean value false on TOS
588 public void PushFalse()
590 AddToBuffer(new Instr((int)Op.ldc_i4_0));
594 /// Add the instruction to load an argument on TOS. This method
595 /// selects the correct instruction based on the value of argNo
597 /// <param name="argNo">the number of the argument</param>
598 public void LoadArg(int argNo)
601 int op = (int)Op.ldarg_0 + argNo;
602 AddToBuffer(new Instr(op));
603 } else if (argNo <= maxUByteVal) {
604 AddToBuffer(new UIntInstr((int)IntOp.ldarg,argNo,true));
606 AddToBuffer(new UIntInstr(0x09,argNo,false));
611 /// Add the instruction to load the address of an argument on TOS.
612 /// This method selects the correct instruction based on the value
615 /// <param name="argNo">the number of the argument</param>
616 public void LoadArgAdr(int argNo)
618 if (argNo <= maxUByteVal) {
619 AddToBuffer(new UIntInstr((int)IntOp.ldarga,argNo,true));
621 AddToBuffer(new UIntInstr(0x0A,argNo,false));
626 /// Add the instruction to load a local on TOS. This method selects
627 /// the correct instruction based on the value of locNo.
629 /// <param name="locNo">the number of the local to load</param>
630 public void LoadLocal(int locNo)
633 int op = (int)Op.ldloc_0 + locNo;
634 AddToBuffer(new Instr(op));
635 } else if (locNo <= maxUByteVal) {
636 AddToBuffer(new UIntInstr((int)IntOp.ldloc,locNo,true));
638 AddToBuffer(new UIntInstr(0x0C,locNo,false));
643 /// Add the instruction to load the address of a local on TOS.
644 /// This method selects the correct instruction based on the
647 /// <param name="locNo">the number of the local</param>
648 public void LoadLocalAdr(int locNo)
650 if (locNo <= maxUByteVal) {
651 AddToBuffer(new UIntInstr((int)IntOp.ldloca,locNo,true));
653 AddToBuffer(new UIntInstr(0x0D,locNo,false));
658 /// Add the instruction to store to an argument. This method
659 /// selects the correct instruction based on the value of argNo.
661 /// <param name="argNo">the argument to be stored to</param>
662 public void StoreArg(int argNo)
664 if (argNo <= maxUByteVal) {
665 AddToBuffer(new UIntInstr((int)IntOp.starg,argNo,true));
667 AddToBuffer(new UIntInstr(0x0B,argNo,false));
672 /// Add the instruction to store to a local. This method selects
673 /// the correct instruction based on the value of locNo.
675 /// <param name="locNo">the local to be stored to</param>
676 public void StoreLocal(int locNo)
679 int op = (int)Op.stloc_0 + locNo;
680 AddToBuffer(new Instr(op));
681 } else if (locNo <= maxUByteVal) {
682 AddToBuffer(new UIntInstr((int)IntOp.stloc,locNo,true));
684 AddToBuffer(new UIntInstr(0x0E,locNo,false));
689 /// Create a new CIL label. To place the label in the CIL instruction
690 /// stream use CodeLabel.
692 /// <returns>a new CIL label</returns>
693 public CILLabel NewLabel()
695 return new CILLabel();
698 public void AddTryBlock(TryBlock tryBlock)
700 if (exceptions == null)
701 exceptions = new ArrayList();
702 else if (exceptions.Contains(tryBlock)) return;
703 exceptions.Add(tryBlock);
707 /// Create a new label at this position in the code buffer
709 /// <returns>the label at the current position</returns>
710 public CILLabel NewCodedLabel()
712 CILLabel lab = new CILLabel();
713 AddToBuffer(new LabelInstr(lab));
718 /// Mark this position as the start of a new block
719 /// (try, catch, filter, finally or fault)
721 public void StartBlock()
723 if (blockStack == null) blockStack = new ArrayList();
724 blockStack.Insert(0,NewCodedLabel());
728 /// Mark this position as the end of the last started block and
729 /// make it a try block. This try block is added to the current
730 /// instructions (ie do not need to call AddTryBlock)
732 /// <returns>The try block just ended</returns>
733 public TryBlock EndTryBlock()
735 TryBlock tBlock = new TryBlock((CILLabel)blockStack[0],NewCodedLabel());
736 blockStack.RemoveAt(0);
742 /// Mark this position as the end of the last started block and
743 /// make it a catch block. This catch block is associated with the
744 /// specified try block.
746 /// <param name="exceptType">the exception type to be caught</param>
747 /// <param name="tryBlock">the try block associated with this catch block</param>
748 public void EndCatchBlock(Class exceptType, TryBlock tryBlock)
750 Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack[0],
752 tryBlock.AddHandler(catchBlock);
756 /// Mark this position as the end of the last started block and
757 /// make it a filter block. This filter block is associated with the
758 /// specified try block.
760 /// <param name="filterLab">the label where the filter code is</param>
761 /// <param name="tryBlock">the try block associated with this filter block</param>
762 public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock)
764 Filter filBlock = new Filter(filterLab,(CILLabel)blockStack[0],NewCodedLabel());
765 tryBlock.AddHandler(filBlock);
769 /// Mark this position as the end of the last started block and
770 /// make it a finally block. This finally block is associated with the
771 /// specified try block.
773 /// <param name="tryBlock">the try block associated with this finally block</param>
774 public void EndFinallyBlock(TryBlock tryBlock)
776 Finally finBlock= new Finally((CILLabel)blockStack[0],NewCodedLabel());
777 tryBlock.AddHandler(finBlock);
781 /// Mark this position as the end of the last started block and
782 /// make it a fault block. This fault block is associated with the
783 /// specified try block.
785 /// <param name="tryBlock">the try block associated with this fault block</param>
786 public void EndFaultBlock(TryBlock tryBlock)
788 Fault fBlock= new Fault((CILLabel)blockStack[0],NewCodedLabel());
789 tryBlock.AddHandler(fBlock);
792 internal uint GetCodeSize()
794 return codeSize + paddingNeeded + exceptSize;
797 internal void CheckCode(uint locSigIx, bool initLocals, int maxStack)
799 if (tide == 0) return;
803 for (int i=0; i < tide; i++) {
804 changed = buffer[i].Check(metaData) || changed;
807 for (int i=1; i < tide; i++) {
808 buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
810 offset = buffer[tide-1].offset + buffer[tide-1].size;
814 // Console.WriteLine("codeSize before header added = " + codeSize);
815 if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
816 // can use tiny header
817 //Console.WriteLine("Tiny Header");
819 headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
821 if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
823 //Console.WriteLine("Fat Header");
825 localSigIx = locSigIx;
826 this.maxStack = (short)maxStack;
827 headerFlags = FatFormat;
828 if (exceptions != null) {
829 // Console.WriteLine("Got exceptions");
830 headerFlags |= MoreSects;
831 uint numExceptClauses = 0;
832 for (int i=0; i < exceptions.Count; i++) {
833 TryBlock tryBlock = (TryBlock)exceptions[i];
835 numExceptClauses += (uint)tryBlock.NumHandlers();
836 if (tryBlock.isFat()) fatExceptionFormat = true;
839 uint data_size = ExHeaderSize + numExceptClauses *
840 (fatExceptionFormat ? FatExClauseSize : SmlExClauseSize);
843 fatExceptionFormat = true;
845 // Console.WriteLine("numexceptclauses = " + numExceptClauses);
846 if (fatExceptionFormat) {
847 // Console.WriteLine("Fat exception format");
848 exceptHeader = FatExceptTable;
849 exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
851 // Console.WriteLine("Tiny exception format");
852 exceptHeader = SmlExceptTable;
853 exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
855 // Console.WriteLine("exceptSize = " + exceptSize);
857 if (initLocals) headerFlags |= InitLocals;
858 if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
861 // Console.WriteLine("codeSize = " + codeSize + " headerFlags = " +
862 // Hex.Short(headerFlags));
865 internal void Write(FileImage output)
867 // Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
869 // Console.WriteLine("Writing tiny code");
870 output.Write((byte)headerFlags);
872 // Console.WriteLine("Writing fat code");
873 output.Write(headerFlags);
874 output.Write((ushort)maxStack);
875 output.Write(offset);
876 output.Write(localSigIx);
878 // Console.WriteLine(Hex.Int(tide) + " CIL instructions");
879 // Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
880 for (int i=0; i < tide; i++) {
881 buffer[i].Write(output);
883 // Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
884 for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
885 if (exceptions != null) {
886 // Console.WriteLine("Writing exceptions");
887 // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
888 output.Write(exceptHeader);
889 output.Write3Bytes((uint)exceptSize);
890 for (int i=0; i < exceptions.Count; i++) {
891 TryBlock tryBlock = (TryBlock)exceptions[i];
892 tryBlock.Write(output,fatExceptionFormat);
899 /**************************************************************************/
900 public abstract class CodeBlock {
902 private static readonly int maxCodeSize = 255;
903 protected CILLabel start, end;
904 protected bool small = true;
906 public CodeBlock(CILLabel start, CILLabel end)
912 internal virtual bool isFat()
914 // Console.WriteLine("block start = " + start.GetLabelOffset() +
915 // " block end = " + end.GetLabelOffset());
916 return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
919 internal virtual void Write(FileImage output, bool fatFormat)
921 if (fatFormat) output.Write(start.GetLabelOffset());
922 else output.Write((short)start.GetLabelOffset());
923 uint len = end.GetLabelOffset() - start.GetLabelOffset();
924 if (fatFormat) output.Write(len);
925 else output.Write((byte)len);
931 /// The descriptor for a guarded block (.try)
933 public class TryBlock : CodeBlock {
934 protected bool fatFormat = false;
935 protected int flags = 0;
936 ArrayList handlers = new ArrayList();
939 /// Create a new try block
941 /// <param name="start">start label for the try block</param>
942 /// <param name="end">end label for the try block</param>
943 public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
946 /// Add a handler to this try block
948 /// <param name="handler">a handler to be added to the try block</param>
949 public void AddHandler(HandlerBlock handler)
951 flags = handler.GetFlag();
952 handlers.Add(handler);
955 internal void SetSize()
957 fatFormat = base.isFat();
958 if (fatFormat) return;
959 for (int i=0; i < handlers.Count; i++) {
960 HandlerBlock handler = (HandlerBlock)handlers[i];
961 if (handler.isFat()) {
968 internal int NumHandlers()
970 return handlers.Count;
973 internal override bool isFat()
978 internal override void Write(FileImage output, bool fatFormat)
980 // Console.WriteLine("writing exception details");
981 for (int i=0; i < handlers.Count; i++) {
982 // Console.WriteLine("Except block " + i);
983 HandlerBlock handler = (HandlerBlock)handlers[i];
984 if (fatFormat) output.Write(flags);
985 else output.Write((short)flags);
986 // Console.WriteLine("flags = " + Hex.Short(flags));
987 base.Write(output,fatFormat);
988 handler.Write(output,fatFormat);
993 public abstract class HandlerBlock : CodeBlock {
995 protected static readonly short ExceptionFlag = 0;
996 protected static readonly short FilterFlag = 0x01;
997 protected static readonly short FinallyFlag = 0x02;
998 protected static readonly short FaultFlag = 0x04;
1000 public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
1002 internal virtual short GetFlag() { return ExceptionFlag; }
1004 internal override void Write(FileImage output, bool fatFormat)
1006 base.Write(output,fatFormat);
1012 /// The descriptor for a catch clause (.catch)
1014 public class Catch : HandlerBlock {
1019 /// Create a new catch clause
1021 /// <param name="except">the exception to be caught</param>
1022 /// <param name="handlerStart">start of the handler code</param>
1023 /// <param name="handlerEnd">end of the handler code</param>
1024 public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
1025 : base(handlerStart,handlerEnd)
1027 exceptType = except;
1030 internal override void Write(FileImage output, bool fatFormat)
1032 base.Write(output,fatFormat);
1033 output.Write(exceptType.Token());
1038 /// The descriptor for a filter clause (.filter)
1040 public class Filter : HandlerBlock {
1042 CILLabel filterLabel;
1045 /// Create a new filter clause
1047 /// <param name="filterLabel">the label where the filter code starts</param>
1048 /// <param name="handlerStart">the start of the handler code</param>
1049 /// <param name="handlerEnd">the end of the handler code</param>
1050 public Filter(CILLabel filterLabel, CILLabel handlerStart,
1051 CILLabel handlerEnd) : base(handlerStart,handlerEnd)
1053 this.filterLabel = filterLabel;
1056 internal override short GetFlag()
1061 internal override void Write(FileImage output, bool fatFormat)
1063 base.Write(output,fatFormat);
1064 output.Write(filterLabel.GetLabelOffset());
1070 /// Descriptor for a finally block (.finally)
1072 public class Finally : HandlerBlock {
1075 /// Create a new finally clause
1077 /// <param name="finallyStart">start of finally code</param>
1078 /// <param name="finallyEnd">end of finally code</param>
1079 public Finally(CILLabel finallyStart, CILLabel finallyEnd)
1080 : base(finallyStart,finallyEnd) { }
1082 internal override short GetFlag()
1087 internal override void Write(FileImage output, bool fatFormat)
1089 base.Write(output,fatFormat);
1090 output.Write((int)0);
1096 /// Descriptor for a fault block (.fault)
1098 public class Fault : HandlerBlock {
1101 /// Create a new fault clause
1103 /// <param name="faultStart">start of the fault code</param>
1104 /// <param name="faultEnd">end of the fault code</param>
1105 public Fault(CILLabel faultStart, CILLabel faultEnd)
1106 : base(faultStart,faultEnd) { }
1108 internal override short GetFlag()
1113 internal override void Write(FileImage output, bool fatFormat)
1115 base.Write(output,fatFormat);
1116 output.Write((int)0);
1121 /**************************************************************************/
1123 /// Descriptor for the locals for a method
1125 public class LocalSig : Signature {
1127 private static readonly byte LocalSigByte = 0x7;
1130 public LocalSig(Local[] locals)
1132 this.locals = locals;
1133 tabIx = MDTable.StandAloneSig;
1136 internal sealed override void BuildTables(MetaData md)
1139 MemoryStream sig = new MemoryStream();
1140 sig.WriteByte(LocalSigByte);
1141 MetaData.CompressNum((uint)locals.Length,sig);
1142 for (int i=0; i < locals.Length; i++) {
1143 ((Local)locals[i]).TypeSig(sig);
1145 sigIx = md.AddToBlobHeap(sig.ToArray());
1151 /**************************************************************************/
1153 /// Signature for calli instruction
1155 public class CalliSig : Signature {
1157 private static readonly byte Sentinel = 0x41;
1160 Type[] parameters, optParams;
1161 uint numPars = 0, numOptPars = 0;
1164 /// Create a signature for a calli instruction
1166 /// <param name="cconv">calling conventions</param>
1167 /// <param name="retType">return type</param>
1168 /// <param name="pars">parameter types</param>
1169 public CalliSig(CallConv cconv, Type retType, Type[] pars)
1171 tabIx = MDTable.StandAloneSig;
1173 returnType = retType;
1175 if (pars != null) numPars = (uint)pars.Length;
1179 /// Add the optional parameters to a vararg method
1180 /// This method sets the vararg calling convention
1182 /// <param name="optPars">the optional pars for the vararg call</param>
1183 public void AddVarArgs(Type[] optPars)
1185 optParams = optPars;
1186 if (optPars != null) numOptPars = (uint)optPars.Length;
1187 callConv |= CallConv.Vararg;
1191 /// Add extra calling conventions to this callsite signature
1193 /// <param name="cconv"></param>
1194 public void AddCallingConv(CallConv cconv)
1199 internal sealed override void BuildTables(MetaData md)
1202 MemoryStream sig = new MemoryStream();
1203 sig.WriteByte((byte)callConv);
1204 MetaData.CompressNum(numPars+numOptPars,sig);
1205 returnType.TypeSig(sig);
1206 for (int i=0; i < numPars; i++) {
1207 parameters[i].TypeSig(sig);
1209 sigIx = md.AddToBlobHeap(sig.ToArray());
1210 if (numOptPars > 0) {
1211 sig.WriteByte(Sentinel);
1212 for (int i=0; i < numOptPars; i++) {
1213 optParams[i].TypeSig(sig);
1221 /**************************************************************************/
1223 /// Descriptor for a local of a method
1225 public class Local {
1227 private static readonly byte Pinned = 0x45;
1230 bool pinned = false, byref = false;
1233 /// Create a new local variable
1235 /// <param name="lName">name of the local variable</param>
1236 /// <param name="lType">type of the local variable</param>
1237 public Local(string lName, Type lType)
1244 /// Create a new local variable that is byref and/or pinned
1246 /// <param name="lName">local name</param>
1247 /// <param name="lType">local type</param>
1248 /// <param name="byRef">is byref</param>
1249 /// <param name="isPinned">has pinned attribute</param>
1250 public Local(string lName, Type lType, bool byRef, bool isPinned)
1258 internal void TypeSig(MemoryStream str)
1260 if (pinned) str.WriteByte(Pinned);
1266 /**************************************************************************/
1268 /// A label in the IL
1270 public class CILLabel {
1272 CILInstruction branch;
1273 CILInstruction[] multipleBranches;
1275 CILInstruction labInstr;
1278 public CILLabel (uint offset)
1280 this.offset = offset;
1288 internal void AddBranch(CILInstruction instr)
1290 if (branch == null) {
1294 if (multipleBranches == null) {
1295 multipleBranches = new CILInstruction[2];
1296 } else if (tide >= multipleBranches.Length) {
1297 CILInstruction[] tmp = multipleBranches;
1298 multipleBranches = new CILInstruction[tmp.Length*2];
1299 for (int i=0; i < tide; i++) {
1300 multipleBranches[i] = tmp[i];
1303 multipleBranches[tide++] = instr;
1306 internal void AddLabelInstr(LabelInstr lInstr)
1311 internal uint GetLabelOffset()
1313 if (labInstr == null) return 0;
1314 return labInstr.offset + offset;