/* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com This file is part of the db4o open source object database. db4o is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation and as clarified by db4objects' GPL interpretation policy, available at http://www.db4o.com/about/company/legalpolicies/gplinterpretation/ Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street, Suite 350, San Mateo, CA 94403, USA. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ namespace Mono.Cecil.Cil { using System; using System.Collections; using SR = System.Reflection; using Mono.Cecil; public sealed class CilWorker : ICilWorker { MethodBody m_mbody; InstructionCollection m_instrs; internal CilWorker (MethodBody body) { m_mbody = body; m_instrs = m_mbody.Instructions as InstructionCollection; } public MethodBody GetBody () { return m_mbody; } public Instruction Create (OpCode opcode) { if (opcode.OperandType != OperandType.InlineNone) throw new ArgumentException ("opcode"); return FinalCreate (opcode); } public Instruction Create (OpCode opcode, TypeReference type) { if (opcode.OperandType != OperandType.InlineType && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return FinalCreate (opcode, type); } public Instruction Create (OpCode opcode, MethodReference meth) { if (opcode.OperandType != OperandType.InlineMethod && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return FinalCreate (opcode, meth); } public Instruction Create (OpCode opcode, FieldReference field) { if (opcode.OperandType != OperandType.InlineField && opcode.OperandType != OperandType.InlineTok) throw new ArgumentException ("opcode"); return FinalCreate (opcode, field); } public Instruction Create (OpCode opcode, string str) { if (opcode.OperandType != OperandType.InlineString) throw new ArgumentException ("opcode"); return FinalCreate (opcode, str); } public Instruction Create (OpCode opcode, sbyte b) { if (opcode.OperandType != OperandType.ShortInlineI && opcode != OpCodes.Ldc_I4_S) throw new ArgumentException ("opcode"); return FinalCreate (opcode, b); } public Instruction Create (OpCode opcode, byte b) { if (opcode.OperandType != OperandType.ShortInlineI || opcode == OpCodes.Ldc_I4_S) throw new ArgumentException ("opcode"); return FinalCreate (opcode, b); } public Instruction Create (OpCode opcode, int i) { if (opcode.OperandType != OperandType.InlineI) throw new ArgumentException ("opcode"); return FinalCreate (opcode, i); } public Instruction Create (OpCode opcode, long l) { if (opcode.OperandType != OperandType.InlineI8) throw new ArgumentException ("opcode"); return FinalCreate (opcode, l); } public Instruction Create (OpCode opcode, float f) { if (opcode.OperandType != OperandType.ShortInlineR) throw new ArgumentException ("opcode"); return FinalCreate (opcode, f); } public Instruction Create (OpCode opcode, double d) { if (opcode.OperandType != OperandType.InlineR) throw new ArgumentException ("opcode"); return FinalCreate (opcode, d); } public Instruction Create (OpCode opcode, Instruction label) { if (opcode.OperandType != OperandType.InlineBrTarget && opcode.OperandType != OperandType.ShortInlineBrTarget) throw new ArgumentException ("opcode"); return FinalCreate (opcode, label); } public Instruction Create (OpCode opcode, Instruction [] labels) { if (opcode.OperandType != OperandType.InlineSwitch) throw new ArgumentException ("opcode"); return FinalCreate (opcode, labels); } public Instruction Create (OpCode opcode, VariableDefinition var) { if (opcode.OperandType != OperandType.ShortInlineVar && opcode.OperandType != OperandType.InlineVar) throw new ArgumentException ("opcode"); return FinalCreate (opcode, var); } public Instruction Create (OpCode opcode, ParameterDefinition param) { if (opcode.OperandType != OperandType.ShortInlineParam && opcode.OperandType != OperandType.InlineParam) throw new ArgumentException ("opcode"); return FinalCreate (opcode, param); } Instruction FinalCreate (OpCode opcode) { return FinalCreate (opcode, null); } Instruction FinalCreate (OpCode opcode, object operand) { return new Instruction (opcode, operand); } public Instruction Emit (OpCode opcode) { Instruction instr = Create (opcode); Append (instr); return instr; } public Instruction Emit (OpCode opcode, TypeReference type) { Instruction instr = Create (opcode, type); Append (instr); return instr; } public Instruction Emit (OpCode opcode, MethodReference meth) { Instruction instr = Create (opcode, meth); Append (instr); return instr; } public Instruction Emit (OpCode opcode, FieldReference field) { Instruction instr = Create (opcode, field); Append (instr); return instr; } public Instruction Emit (OpCode opcode, string str) { Instruction instr = Create (opcode, str); Append (instr); return instr; } public Instruction Emit (OpCode opcode, byte b) { Instruction instr = Create (opcode, b); Append (instr); return instr; } public Instruction Emit (OpCode opcode, sbyte b) { Instruction instr = Create (opcode, b); Append (instr); return instr; } public Instruction Emit (OpCode opcode, int i) { Instruction instr = Create (opcode, i); Append (instr); return instr; } public Instruction Emit (OpCode opcode, long l) { Instruction instr = Create (opcode, l); Append (instr); return instr; } public Instruction Emit (OpCode opcode, float f) { Instruction instr = Create (opcode, f); Append (instr); return instr; } public Instruction Emit (OpCode opcode, double d) { Instruction instr = Create (opcode, d); Append (instr); return instr; } public Instruction Emit (OpCode opcode, Instruction target) { Instruction instr = Create (opcode, target); Append (instr); return instr; } public Instruction Emit (OpCode opcode, Instruction [] targets) { Instruction instr = Create (opcode, targets); Append (instr); return instr; } public Instruction Emit (OpCode opcode, VariableDefinition var) { Instruction instr = Create (opcode, var); Append (instr); return instr; } public Instruction Emit (OpCode opcode, ParameterDefinition param) { Instruction instr = Create (opcode, param); Append (instr); return instr; } public void InsertBefore (Instruction target, Instruction instr) { int index = m_instrs.IndexOf (target); if (index == -1) throw new ReflectionException ("Target instruction not in method body"); m_instrs.Insert (index, instr); instr.Previous = target.Previous; target.Previous = instr; instr.Next = target; } public void InsertAfter (Instruction target, Instruction instr) { int index = m_instrs.IndexOf (target); if (index == -1) throw new ReflectionException ("Target instruction not in method body"); m_instrs.Insert (index + 1, instr); instr.Next = target.Next; target.Next = instr; instr.Previous = target; } public void Append (Instruction instr) { Instruction last = null, current = instr; if (m_instrs.Count > 0) last = m_instrs [m_instrs.Count - 1]; if (last != null) { last.Next = instr; current.Previous = last; } m_instrs.Add (current); } public void Replace (Instruction old, Instruction instr) { int index = m_instrs.IndexOf (old); if (index == -1) throw new ReflectionException ("Target instruction not in method body"); InsertAfter (old, instr); Remove (old); } public void Remove (Instruction instr) { if (!m_instrs.Contains (instr)) throw new ReflectionException ("Instruction not in method body"); if (instr.Previous != null) instr.Previous.Next = instr.Next; if (instr.Next != null) instr.Next.Previous = instr.Previous; m_instrs.Remove (instr); } } }