// Emit a token value to the current method's code and register it // to have a token fixup at the end of the assembly output process. private void EmitTokenWithFixup(int token) { TokenFixup fixup = new TokenFixup(); fixup.next = tokenFixups; fixup.offset = offset; fixup.clrHandle = AssemblyBuilder.ClrGetItemFromToken (module.assembly.privateData, token); tokenFixups = fixup; EmitByte(token); EmitByte(token >> 8); EmitByte(token >> 16); EmitByte(token >> 24); }
// Build the method's exception blocks. private void BuildExceptionBlocks (ref byte[][] e, ref TokenFixup fixups, bool fatExceptions) { if (exceptionList == null) { return; } // Count the number of exception blocks int numExceptions = 0; ExceptionTry exception = exceptionList; while (exception != null) { ExceptionClause clause = exception.clauses; while (clause != null) { ++numExceptions; clause = clause.prev; } exception = exception.next; } // Switch formats if the section size is too big for tiny if (!fatExceptions && ((numExceptions * 12) + 4) > 0xFF) { fatExceptions = true; } e = new byte[numExceptions+1][]; int index = 0; // What type of exception header should we use? if (fatExceptions) { // Use the fat format for the exception information int tmp = (numExceptions * 24) + 4; e[index] = new byte[4]; e[index][0] = (byte)0x41; e[index][1] = (byte)(tmp); e[index][2] = (byte)(tmp >> 8); e[index][3] = (byte)(tmp >> 16); ++index; exception = exceptionList; while (exception != null) { ExceptionClause clause = exception.clauses; while (clause != null) { int flags; int tryOffset; int tryLength; int handlerOffset; int handlerLength; flags = clause.clauseType; tryOffset = exception.beginTry; tryLength = exception.endTry - tryOffset; handlerOffset = clause.beginClause; handlerLength = clause.endClause - handlerOffset; e[index] = new byte[24]; e[index][0] = (byte)(flags); e[index][1] = (byte)(flags >> 8); e[index][2] = (byte)(flags >> 16); e[index][3] = (byte)(flags >> 24); e[index][4] = (byte)(tryOffset); e[index][5] = (byte)(tryOffset >> 8); e[index][6] = (byte)(tryOffset >> 16); e[index][7] = (byte)(tryOffset >> 24); e[index][8] = (byte)(tryLength); e[index][9] = (byte)(tryLength >> 8); e[index][10] = (byte)(tryLength >> 16); e[index][11] = (byte)(tryLength >> 24); e[index][12] = (byte)(handlerOffset); e[index][13] = (byte)(handlerOffset >> 8); e[index][14] = (byte)(handlerOffset >> 16); e[index][15] = (byte)(handlerOffset >> 24); e[index][16] = (byte)(handlerLength); e[index][17] = (byte)(handlerLength >> 8); e[index][18] = (byte)(handlerLength >> 16); e[index][19] = (byte)(handlerLength >> 24); if (flags == Except_Filter) { // ?? TODO ?? e[index][20] = (byte)(handlerOffset); e[index][21] = (byte)(handlerOffset >> 8); e[index][22] = (byte)(handlerOffset >> 16); e[index][23] = (byte)(handlerOffset >> 24); } else if (clause.classInfo != null) { int token; IntPtr handle; IClrProgramItem item; item = (IClrProgramItem)clause.classInfo; handle = item.ClrHandle; token = AssemblyBuilder.ClrGetItemToken(handle); e[index][20] = (byte)(token); e[index][21] = (byte)(token >> 8); e[index][22] = (byte)(token >> 16); e[index][23] = (byte)(token >> 24); TokenFixup fixup = new TokenFixup(); fixup.next = fixups; fixup.offset = index*24; fixup.clrHandle = handle; fixups = fixup; } else { e[index][20] = (byte)0x00; e[index][21] = (byte)0x00; e[index][22] = (byte)0x00; e[index][23] = (byte)0x00; } clause = clause.prev; ++index; } exception = exception.next; } } else { // Use the tiny format for the exception information int tmp = (numExceptions * 12) + 4; e[index] = new byte[4]; e[index][0] = (byte)0x01; e[index][1] = (byte)tmp; e[index][2] = (byte)0x00; e[index][3] = (byte)0x00; ++index; exception = exceptionList; while(exception != null) { ExceptionClause clause = exception.clauses; while (clause != null) { int flags; int tryOffset; int tryLength; int handlerOffset; int handlerLength; flags = clause.clauseType; tryOffset = exception.beginTry; tryLength = exception.endTry - tryOffset; handlerOffset = clause.beginClause; handlerLength = clause.endClause - handlerOffset; e[index] = new byte[12]; e[index][0] = (byte)(flags); e[index][1] = (byte)(flags >> 8); e[index][2] = (byte)(tryOffset); e[index][3] = (byte)(tryOffset >> 8); e[index][4] = (byte)(tryLength); e[index][5] = (byte)(handlerOffset); e[index][6] = (byte)(handlerOffset >> 8); e[index][7] = (byte)(handlerLength); if (flags == Except_Filter) { // ?? TODO ?? e[index][8] = (byte)(handlerOffset); e[index][9] = (byte)(handlerOffset >> 8); e[index][10] = (byte)(handlerOffset >> 16); e[index][11] = (byte)(handlerOffset >> 24); } else if (clause.classInfo != null) { int token; IntPtr handle; IClrProgramItem item; item = (IClrProgramItem)clause.classInfo; handle = item.ClrHandle; token = AssemblyBuilder.ClrGetItemToken(handle); e[index][8] = (byte)(token); e[index][9] = (byte)(token >> 8); e[index][10] = (byte)(token >> 16); e[index][11] = (byte)(token >> 24); TokenFixup fixup = new TokenFixup(); fixup.next = fixups; fixup.offset = index*12; fixup.clrHandle = handle; fixups = fixup; } else { e[index][8] = (byte)0x00; e[index][9] = (byte)0x00; e[index][10] = (byte)0x00; e[index][11] = (byte)0x00; } clause = clause.prev; ++index; } exception = exception.next; } } }
// Detach this item. void IDetachItem.Detach() { tokenFixups = null; }
// Copy the fixup data to the given arrays. private static void FixupsToArrays (ref IntPtr[] ptrs, ref int[] offsets, TokenFixup fixups) { if (fixups == null) { return; } System.Collections.ArrayList p = new System.Collections.ArrayList(); System.Collections.ArrayList o = new System.Collections.ArrayList(); while (fixups != null) { p.Add(fixups.clrHandle); o.Add(fixups.offset); fixups = fixups.next; } ptrs = (IntPtr[])p.ToArray(typeof(IntPtr)); offsets = (int[])o.ToArray(typeof(int)); }
}; // class ExceptionClause // Constructor. internal ILGenerator(ModuleBuilder module, int size) { this.module = module; if(size < 16) { size = 16; } code = new byte [size]; offset = 0; height = 0; maxHeight = 0; labels = null; numLabels = 0; locals = null; exceptionStack = null; exceptionList = null; exceptionListEnd = null; tokenFixups = null; module.assembly.AddDetach(this); }