// 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);
			}