context: using Editor_Mono.Cecil.Metadata;
  using Editor_Mono.Cecil.PE;
  using Editor_Mono.Collections.Generic;
  using System;
  using System.Collections.Generic;
  namespace Editor_Mono.Cecil.Cil
  {
  	internal sealed class CodeWriter : ByteBuffer
  	{
  		private readonly uint code_base;
  		internal readonly MetadataBuilder metadata;
  		private readonly Dictionary<uint, MetadataToken> standalone_signatures;
  		private uint current;
  		private MethodBody body;
  		public CodeWriter(MetadataBuilder metadata) : base(0)
  		{
  			this.code_base = metadata.text_map.GetNextRVA(TextSegment.CLIHeader);
  			this.current = this.code_base;
  			this.metadata = metadata;
  			this.standalone_signatures = new Dictionary<uint, MetadataToken>();
  		}
  		public uint WriteMethodBody(MethodDefinition method)
  		{
  			uint result = this.BeginMethod();
  			if (CodeWriter.IsUnresolved(method))
  			{
  				if (method.rva == 0u)
  				{
  					return 0u;
  				}
  				this.WriteUnresolvedMethodBody(method);
  			}
  			else
  			{
  				if (CodeWriter.IsEmptyMethodBody(method.Body))
  				{
  					return 0u;
  				}
  				this.WriteResolvedMethodBody(method);
  			}
  			this.Align(4);
  			this.EndMethod();
  			return result;
  		}
  		private static bool IsEmptyMethodBody(MethodBody body)
  		{
  			return body.instructions.IsNullOrEmpty<Instruction>() && body.variables.IsNullOrEmpty<VariableDefinition>();
  		}
  		private static bool IsUnresolved(MethodDefinition method)
  		{
  			return method.HasBody && method.HasImage && method.body == null;
  		}
  		private void WriteUnresolvedMethodBody(MethodDefinition method)
  		{
  			CodeReader codeReader = this.metadata.module.Read<MethodDefinition, CodeReader>(method, (MethodDefinition _, MetadataReader reader) => reader.code);
  			MethodSymbols methodSymbols;
  			ByteBuffer buffer = codeReader.PatchRawMethodBody(method, this, out methodSymbols);
  			base.WriteBytes(buffer);
  			if (methodSymbols.instructions.IsNullOrEmpty<InstructionSymbol>())
  			{
  				return;
  			}
  			methodSymbols.method_token = method.token;
  			methodSymbols.local_var_token = CodeWriter.GetLocalVarToken(buffer, methodSymbols);
  			ISymbolWriter symbol_writer = this.metadata.symbol_writer;
  			if (symbol_writer != null)
  			{
  				symbol_writer.Write(methodSymbols);
  			}
  		}
  		private static MetadataToken GetLocalVarToken(ByteBuffer buffer, MethodSymbols symbols)
  		{
  			if (symbols.variables.IsNullOrEmpty<VariableDefinition>())
  			{
  				return MetadataToken.Zero;
  			}
  			buffer.position = 8;
  			return new MetadataToken(buffer.ReadUInt32());
  		}
  		private void WriteResolvedMethodBody(MethodDefinition method)
  		{
  			this.body = method.Body;
  			this.ComputeHeader();
  			if (this.RequiresFatHeader())
  			{
  				this.WriteFatHeader();
  			}
  			else
  			{
  				base.WriteByte((byte)(2 | this.body.CodeSize << 2));
  			}
  			this.WriteInstructions();
  			if (this.body.HasExceptionHandlers)
  			{
  				this.WriteExceptionHandlers();
  			}
  			ISymbolWriter symbol_writer = this.metadata.symbol_writer;
  			if (symbol_writer != null)
  			{
  				symbol_writer.Write(this.body);
  			}
  		}
  		private void WriteFatHeader()
  		{
  			MethodBody methodBody = this.body;
  			byte b = 3;
  			if (methodBody.InitLocals)
  			{
  				b |= 16;
  			}
  			if (methodBody.HasExceptionHandlers)
  			{
  				b |= 8;
  			}
  			base.WriteByte(b);
  			base.WriteByte(48);
  			base.WriteInt16((short)methodBody.max_stack_size);
  			base.WriteInt32(methodBody.code_size);
  			methodBody.local_var_token = (methodBody.HasVariables ? this.GetStandAloneSignature(methodBody.Variables) : MetadataToken.Zero);
  			this.WriteMetadataToken(methodBody.local_var_token);
  		}
  		private void WriteInstructions()
  		{
  			Collection<Instruction> instructions = this.body.Instructions;
  			Instruction[] items = instructions.items;
  			int size = instructions.size;
  			for (int i = 0; i < size; i++)
  			{
  				Instruction instruction = items[i];
  				this.WriteOpCode(instruction.opcode);
  				this.WriteOperand(instruction);
  			}
  		}
  		private void WriteOpCode(OpCode opcode)
  		{
  			if (opcode.Size == 1)
  			{
  				base.WriteByte(opcode.Op2);
  				return;
  			}
  			base.WriteByte(opcode.Op1);
  			base.WriteByte(opcode.Op2);
  		}
  		private void WriteOperand(Instruction instruction)
  		{
  			OpCode opcode = instruction.opcode;
  			OperandType operandType = opcode.OperandType;
  			if (operandType == OperandType.InlineNone)
  			{
  				return;
  			}
  			object operand = instruction.operand;
  			if (operand == null)
  			{
  				throw new ArgumentException();
  			}
  			switch (operandType)
  			{
  			case OperandType.InlineBrTarget:
  			{
  				Instruction instruction2 = (Instruction)operand;
  				base.WriteInt32(this.GetTargetOffset(instruction2) - (instruction.Offset + opcode.Size + 4));
  				return;
  			}
  			case OperandType.InlineField:
  			case OperandType.InlineMethod:
  			case OperandType.InlineTok:
  			case OperandType.InlineType:
  				this.WriteMetadataToken(this.metadata.LookupToken((IMetadataTokenProvider)operand));
  				return;
  			case OperandType.InlineI:
  				base.WriteInt32((int)operand);
  				return;
  			case OperandType.InlineI8:
  				base.WriteInt64((long)operand);
  				return;
  			case OperandType.InlineR:
  				base.WriteDouble((double)operand);
  				return;
  			case OperandType.InlineSig:
  				this.WriteMetadataToken(this.GetStandAloneSignature((CallSite)operand));
  				return;
  			case OperandType.InlineString:
  				this.WriteMetadataToken(new MetadataToken(TokenType.String, this.GetUserStringIndex((string)operand)));
  				return;
  			case OperandType.InlineSwitch:
  			{
  				Instruction[] array = (Instruction[])operand;
  				base.WriteInt32(array.Length);
  				int num = instruction.Offset + opcode.Size + 4 * (array.Length + 1);
  				for (int i = 0; i < array.Length; i++)
  				{
  					base.WriteInt32(this.GetTargetOffset(array[i]) - num);
  				}
  				return;
  			}
  			case OperandType.InlineVar:
  				base.WriteInt16((short)CodeWriter.GetVariableIndex((VariableDefinition)operand));
  				return;
  			case OperandType.InlineArg:
  				base.WriteInt16((short)this.GetParameterIndex((ParameterDefinition)operand));
  				return;
  			case OperandType.ShortInlineBrTarget:
  			{
  				Instruction instruction3 = (Instruction)operand;
  				base.WriteSByte((sbyte)(this.GetTargetOffset(instruction3) - (instruction.Offset + opcode.Size + 1)));
  				return;
  			}
  			case OperandType.ShortInlineI:
  				if (opcode == OpCodes.Ldc_I4_S)
  				{
  					base.WriteSByte((sbyte)operand);
  					return;
  				}
  				base.WriteByte((byte)operand);
  				return;
  			case OperandType.ShortInlineR:
  				base.WriteSingle((float)operand);
  				return;
  			case OperandType.ShortInlineVar:
  				base.WriteByte((byte)CodeWriter.GetVariableIndex((VariableDefinition)operand));
  				return;
  			case OperandType.ShortInlineArg:
  				base.WriteByte((byte)this.GetParameterIndex((ParameterDefinition)operand));
  				return;
  			}
  			throw new ArgumentException();
  		}
  		private int GetTargetOffset(Instruction instruction)
  		{
  			if (instruction == null)
  			{
  				Instruction instruction2 = this.body.instructions[this.body.instructions.size - 1];
  				return instruction2.offset + instruction2.GetSize();
  			}
  			return instruction.offset;
  		}
  		private uint GetUserStringIndex(string @string)
  		{
  			if (@string == null)
  			{
  				return 0u;
  			}
  			return this.metadata.user_string_heap.GetStringIndex(@string);
  		}
  		private static int GetVariableIndex(VariableDefinition variable)
  		{
  			return variable.Index;
  		}
  		private int GetParameterIndex(ParameterDefinition parameter)
  		{
  			if (!this.body.method.HasThis)
  			{
  				return parameter.Index;
  			}
  			if (parameter == this.body.this_parameter)
  			{
  				return 0;
  			}
  			return parameter.Index + 1;
  		}
  		private bool RequiresFatHeader()
  		{
  			MethodBody methodBody = this.body;
  			return methodBody.CodeSize >= 64 || methodBody.InitLocals || methodBody.HasVariables || methodBody.HasExceptionHandlers || methodBody.MaxStackSize > 8;
  		}
  		private void ComputeHeader()
  		{
  			int num = 0;
  			Collection<Instruction> instructions = this.body.instructions;
  			Instruction[] items = instructions.items;
  			int size = instructions.size;
  			int num2 = 0;
  			int max_stack_size = 0;
  
gt: 			Dictionary<Instruction, int> dictionary = null;