HRESULT MethodCompiler::Opcode::Initialize( MethodCompiler* mc, CLR_OFFSET offset, CLR_OFFSET* targets ) { TINYCLR_HEADER(); CLR_PMETADATA ip = mc->m_ipStart + offset; //--// memset( this, 0, sizeof(*this) ); m_op = CLR_ReadNextOpcodeCompressed( ip ); m_ol = &c_CLR_RT_OpcodeLookup[ m_op ]; m_ipOffset = offset; m_stackPop = m_ol->StackPop (); m_stackPush = m_ol->StackPush(); m_token = CLR_EmptyToken; m_value.SetDataId( CLR_RT_HEAPBLOCK_RAW_ID(DATATYPE_FIRST_INVALID, 0, 1) ); //--// switch(m_ol->m_opParam) { case CLR_OpcodeParam_Field: { FETCH_ARG_COMPRESSED_FIELDTOKEN(arg,ip); m_token = arg; } break; case CLR_OpcodeParam_Method: { FETCH_ARG_COMPRESSED_METHODTOKEN(arg,ip); m_token = arg; } break; case CLR_OpcodeParam_Type: { FETCH_ARG_COMPRESSED_TYPETOKEN(arg,ip); m_token = arg; } break; case CLR_OpcodeParam_String: { FETCH_ARG_COMPRESSED_STRINGTOKEN(arg,ip); m_token = arg; } break; case CLR_OpcodeParam_Tok: { FETCH_ARG_TOKEN(arg,ip); m_token = arg; } break; case CLR_OpcodeParam_Sig: TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_UNSUPPORTED); case CLR_OpcodeParam_BrTarget: { FETCH_ARG_INT16(arg,ip); m_numTargets = 1; if(targets) { *targets++ = (CLR_OFFSET)(ip - mc->m_ipStart + arg); } } break; case CLR_OpcodeParam_ShortBrTarget: { FETCH_ARG_INT8(arg,ip); m_numTargets = 1; if(targets) { *targets++ = (CLR_OFFSET)(ip - mc->m_ipStart + arg); } } break; case CLR_OpcodeParam_I: { FETCH_ARG_INT32(arg,ip); m_value.SetInteger( arg ); } break; case CLR_OpcodeParam_I8: { FETCH_ARG_INT64(arg,ip); m_value.SetInteger( arg ); } break; case CLR_OpcodeParam_None: if(m_ol->m_flags & CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) { m_value.SetInteger( (CLR_UINT32)m_ol->m_index ); } if(m_ol->m_flags & CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) { m_value.SetInteger( (CLR_INT32)m_ol->m_index ); } break; case CLR_OpcodeParam_R: { FETCH_ARG_UINT64(arg,ip); m_value.SetDoubleFromBits( arg ); } break; case CLR_OpcodeParam_Switch: { FETCH_ARG_UINT8(arg,ip); m_numTargets = arg; CLR_UINT32 base = (CLR_UINT32)(ip - mc->m_ipStart + arg * sizeof(CLR_INT16)); while(arg--) { CLR_INT32 offset; TINYCLR_READ_UNALIGNED_INT16( offset, ip ); if(targets) { *targets++ = (CLR_OFFSET)(base + offset); } } } break; case CLR_OpcodeParam_Var: { FETCH_ARG_UINT16(arg,ip); m_value.SetInteger( (CLR_UINT32)m_ol->m_index ); } break; case CLR_OpcodeParam_ShortI: { FETCH_ARG_INT8(arg,ip); m_value.SetInteger( (CLR_INT32)arg ); } break; case CLR_OpcodeParam_ShortR: { FETCH_ARG_UINT32(arg,ip); m_value.SetFloatFromBits( arg ); } break; case CLR_OpcodeParam_ShortVar: { FETCH_ARG_UINT8(arg,ip); m_value.SetInteger( (CLR_UINT32)arg ); } break; } if(m_token != CLR_EmptyToken) { CLR_RT_Assembly* assm = mc->m_mdInst.m_assm; switch(CLR_TypeFromTk( m_token )) { case TBL_TypeRef: case TBL_TypeDef: { if(m_tdInst.ResolveToken( m_token, assm ) == false) { TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__TYPE); } } break; case TBL_MethodRef: case TBL_MethodDef: { if(m_mdInst.ResolveToken( m_token, assm ) == false) { TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__METHOD); } if(m_ol->m_flowCtrl == CLR_FlowControl_CALL) { m_stackPop += m_mdInst.m_target->numArgs; if(m_ol->m_logicalOpcode == LO_NewObject) { m_stackPop -= 1; } if(m_mdInst.m_target->retVal != DATATYPE_VOID) { m_stackPush += 1; } } } break; case TBL_FieldRef: case TBL_FieldDef: { if(m_fdInst.ResolveToken( m_token, assm ) == false) { TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__FIELD); } } break; case TBL_TypeSpec: { CLR_RT_TypeSpec_Instance sig; CLR_RT_TypeDescriptor desc; if(sig.ResolveToken( m_token, assm ) == false) { TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_TOKEN__TYPE); } TINYCLR_CHECK_HRESULT(desc.InitializeFromTypeSpec( sig )); m_tdInst.InitializeFromIndex( desc.m_reflex.m_data.m_type ); m_tdInstLevels = desc.m_reflex.m_levels; } break; case TBL_Strings: break; default: TINYCLR_SET_AND_LEAVE(CLR_E_JITTER_OPCODE_INVALID_SIGNATURE); } } m_ipLength = (CLR_OFFSET)(ip - mc->m_ipStart - m_ipOffset); TINYCLR_NOCLEANUP(); }
HRESULT MetaData::ByteCode::Parse_ByteCode( const MethodDef& md, COR_ILMETHOD_DECODER& il ) { TINYCLR_HEADER(); const CLR_UINT8* ip = il.Code; const CLR_UINT8* ipStart = ip; const CLR_UINT8* ipEnd = ip + il.GetCodeSize(); //wprintf( L"Method: %s : %d\n", m_name.c_str(), il.GetMaxStack() ); while(ip < ipEnd) { const CLR_UINT8* ipPre = ip; CLR_OPCODE op = CLR_ReadNextOpcode( ip ); const CLR_RT_OpcodeLookup& ol = c_CLR_RT_OpcodeLookup[op]; //printf( " %08X %s\n", ip - ipStart, opcodeName[op] ); if(ol.m_flags & CLR_RT_OpcodeLookup::COND_OVERFLOW) { std::wstring str; if(SUCCEEDED(ErrorReporting::ConstructErrorOrigin( str, md.m_method.m_holder->m_pSymReader, md.m_md, (ULONG32)(ipPre - ipStart) ))) { ErrorReporting::Print( str.c_str(), NULL, FALSE, 0, L"opcode '%S' -- overflow will not throw exception", ol.m_name ); } } if(op < CEE_COUNT && ol.m_logicalOpcode != LO_Unsupported) { const CLR_UINT8* ipEnd = CLR_SkipBodyOfOpcode( ip, op ); LogicalOpcodeDesc& ref = *(m_opcodes.insert( m_opcodes.end(), LogicalOpcodeDesc( ol, op, ipPre, ipEnd ) )); switch(ol.m_opParam) { case CLR_OpcodeParam_Field: { FETCH_ARG_UINT32(arg,ip); ref.m_token = (mdToken)arg; } break; case CLR_OpcodeParam_Method: { FETCH_ARG_UINT32(arg,ip); ref.m_token = (mdToken)arg; } break; case CLR_OpcodeParam_Type: { FETCH_ARG_UINT32(arg,ip); ref.m_token = (mdToken)arg; } break; case CLR_OpcodeParam_String: { FETCH_ARG_UINT32(arg,ip); ref.m_token = (mdToken)arg; } break; case CLR_OpcodeParam_Tok: { FETCH_ARG_UINT32(arg,ip); ref.m_token = (mdToken)arg; } break; case CLR_OpcodeParam_Sig: TINYCLR_SET_AND_LEAVE(CLR_E_UNSUPPORTED_INSTRUCTION); case CLR_OpcodeParam_BrTarget: { FETCH_ARG_INT32(arg,ip); ref.m_targets.resize( 1 ); ref.m_targets[0] = ref.m_ipLength + arg; } break; case CLR_OpcodeParam_ShortBrTarget: { FETCH_ARG_INT8(arg,ip); ref.m_targets.resize( 1 ); ref.m_targets[0] = ref.m_ipLength + arg; } break; case CLR_OpcodeParam_I: { FETCH_ARG_INT32(arg,ip); ref.m_arg_I4 = arg; } break; case CLR_OpcodeParam_I8: { FETCH_ARG_INT64(arg,ip); ref.m_arg_I8 = arg; } break; case CLR_OpcodeParam_None: if(ol.m_flags & CLR_RT_OpcodeLookup::ATTRIB_HAS_INDEX) { ref.m_index = ol.m_index; } if(ol.m_flags & CLR_RT_OpcodeLookup::ATTRIB_HAS_I4) { ref.m_arg_I4 = ol.m_index; } break; case CLR_OpcodeParam_R: { FETCH_ARG_UINT64(arg,ip); ref.m_arg_R8 = arg; } break; case CLR_OpcodeParam_Switch: { FETCH_ARG_UINT32(arg,ip); ref.m_targets.resize( arg ); for(CLR_UINT32 i=0; i<arg; i++) { CLR_INT32& val = ref.m_targets[i]; memcpy( &val, ip, sizeof(CLR_INT32) ); ip += sizeof(CLR_INT32); val = (CLR_INT32)ref.m_ipLength + val; } } break; case CLR_OpcodeParam_Var: { FETCH_ARG_UINT16(arg,ip); ref.m_index = arg; } break; case CLR_OpcodeParam_ShortI: { FETCH_ARG_INT8(arg,ip); ref.m_arg_I4 = arg; } break; case CLR_OpcodeParam_ShortR: { FETCH_ARG_UINT32(arg,ip); ref.m_arg_R4 = arg; } break; case CLR_OpcodeParam_ShortVar: { FETCH_ARG_UINT8(arg,ip); ref.m_index = arg; } break; } } else { wprintf( L"Method: %s\n", m_name.c_str() ); wprintf( L" %08X %S -- Not supported\n", ipPre - ipStart, op < CEE_COUNT ? c_CLR_RT_OpcodeLookup[op].m_name : "<invalid>" ); TINYCLR_SET_AND_LEAVE(CLR_E_FAIL); } } TINYCLR_NOCLEANUP(); }