/* Menes - C++ High-Level Utility Library * Copyright (C) 2004-2005 Jay Freeman (saurik) */ /* * Redistribution and use in source and binary * forms, with or without modification, are permitted * provided that the following conditions are met: * * 1. Redistributions of source code must retain the * above copyright notice, this list of conditions * and the following disclaimer. * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions * and the following disclaimer in the documentation * and/or other materials provided with the * distribution. * 3. The name of the author may not be used to endorse * or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "cxx/standard.hh" #pragma hdrstop("build/cxx/standard.pch") #include "clr/codeds/fielddeforref.hpp" #include "clr/codeds/member.hpp" #include "clr/codeds/methoddeforref.hpp" #include "clr/codeds/typedeforref.hpp" #include "clr/net/instructions.hpp" #include "clr/net/parse.hpp" #include "clr/tokens/standalonesig.hpp" #include "clr/metadata.hpp" #include "clr/utils.hpp" #include "ext/byteorder.hpp" #include "ext/exception.hpp" #include "ext/vector.hpp" #include "opt/profile.hpp" namespace clr { namespace Net { namespace be { Instruction *ParseInstruction_(Metadata &metadata, const char *base, const char *code, InstructionList &cache) { Instruction * &begin = cache[code - base]; if (begin != NULL) return begin; Instruction *end(NULL); //api::Cout << "0x" << ios::SetBase(16) << ios::SetFill('0') << ios::SetWidth(2) << *reinterpret_cast(code) << ios::SetFill(' ') << ios::SetBase(10) << ios::NewLine; switch (*reinterpret_cast(code++)) { case 0x0: { // nop end = begin = new NoOp(); } break; case 0x1: { // break end = begin = new Break(); } break; case 0x2: { // ldarg.0 end = begin = new LoadArgument(0); } break; case 0x3: { // ldarg.1 end = begin = new LoadArgument(1); } break; case 0x4: { // ldarg.2 end = begin = new LoadArgument(2); } break; case 0x5: { // ldarg.3 end = begin = new LoadArgument(3); } break; case 0x6: { // ldloc.0 end = begin = new LoadLocal(0); } break; case 0x7: { // ldloc.1 end = begin = new LoadLocal(1); } break; case 0x8: { // ldloc.2 end = begin = new LoadLocal(2); } break; case 0x9: { // ldloc.3 end = begin = new LoadLocal(3); } break; case 0xa: { // stloc.0 end = begin = new StoreLocal(0); } break; case 0xb: { // stloc.1 end = begin = new StoreLocal(1); } break; case 0xc: { // stloc.2 end = begin = new StoreLocal(2); } break; case 0xd: { // stloc.3 end = begin = new StoreLocal(3); } break; case 0xe: { // ldarg.s uint32_t index(ios::GetLittle(code)); end = begin = new LoadArgument(index); } break; case 0xf: { // ldarga.s uint32_t index(ios::GetLittle(code)); end = begin = new LoadArgumentAddress(index); } break; case 0x10: { // starg.s uint32_t index(ios::GetLittle(code)); end = begin = new StoreArgument(index); } break; case 0x11: { // ldloc.s uint32_t index(ios::GetLittle(code)); end = begin = new LoadLocal(index); } break; case 0x12: { // ldloca.s uint32_t index(ios::GetLittle(code)); end = begin = new LoadLocalAddress(index); } break; case 0x13: { // stloc.s uint32_t index(ios::GetLittle(code)); end = begin = new StoreLocal(index); } break; case 0x14: { // ldnull end = begin = new LoadNull(); } break; case 0x15: { // ldc.i4.m1 end = begin = new LoadConstant(-1); } break; case 0x16: { // ldc.i4.0 end = begin = new LoadConstant(0); } break; case 0x17: { // ldc.i4.1 end = begin = new LoadConstant(1); } break; case 0x18: { // ldc.i4.2 end = begin = new LoadConstant(2); } break; case 0x19: { // ldc.i4.3 end = begin = new LoadConstant(3); } break; case 0x1a: { // ldc.i4.4 end = begin = new LoadConstant(4); } break; case 0x1b: { // ldc.i4.5 end = begin = new LoadConstant(5); } break; case 0x1c: { // ldc.i4.6 end = begin = new LoadConstant(6); } break; case 0x1d: { // ldc.i4.7 end = begin = new LoadConstant(7); } break; case 0x1e: { // ldc.i4.8 end = begin = new LoadConstant(8); } break; case 0x1f: { // ldc.i4.s uint32_t value(ios::GetLittle(code)); end = begin = new LoadConstant(value); } break; case 0x20: { // ldc.i4 end = begin = new LoadConstant(code); } break; case 0x21: { // idc.i8 end = begin = new LoadConstant(code); } break; case 0x22: { // ldc.r4 end = begin = new LoadConstant(code); } break; case 0x23: { // ldc.r8 end = begin = new LoadConstant(code); } break; case 0x25: { // dup end = begin = new Dup(0); } break; case 0x26: { // pop end = begin = new Pop(); } break; case 0x27: { // jmp uint32_t token(ios::GetLittle(code)); MethodDefOrRef *method(metadata.GetToken(token)); return end = begin = new Jump(method); } break; case 0x28: { // call uint32_t token(ios::GetLittle(code)); MethodDefOrRef *method(metadata.GetToken(token)); end = begin = new Call(method); } break; case 0x29: { // calli uint32_t token(ios::GetLittle(code)); StandAloneSig *signature(metadata.GetToken(token)); end = begin = new CallIndirect(signature->GetSignature()); } break; case 0x2a: { // ret return end = begin = new Return(); } break; case 0x2b: { // br.s