2 * PLEASE NOTE: This is a research prototype.
5 * interp.c: Interpreter for CIL byte codes
8 * Paolo Molaro (lupus@ximian.com)
9 * Miguel de Icaza (miguel@ximian.com)
11 * (C) 2001 Ximian, Inc.
13 #define _ISOC99_SOURCE
27 # define alloca __builtin_alloca
32 /* trim excessive headers */
33 #include <mono/metadata/image.h>
34 #include <mono/metadata/assembly.h>
35 #include <mono/metadata/cil-coff.h>
36 #include <mono/metadata/endian.h>
37 #include <mono/metadata/tabledefs.h>
38 #include <mono/metadata/blob.h>
39 #include <mono/metadata/tokentype.h>
40 #include <mono/cli/cli.h>
41 #include <mono/cli/types.h>
44 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
48 #include "mono/cil/opcode.def"
53 static int debug_indent_level = 0;
55 #define GET_NATI(sp) ((guint32)(sp).data.i)
56 #define CSIZE(x) (sizeof (x) / 4)
58 static void ves_exec_method (MonoMethod *mh, stackval *args);
60 typedef void (*ICallMethod) (MonoMethod *mh, stackval *args);
64 ves_real_abort (int line, MonoMethod *mh,
65 const unsigned char *ip, stackval *stack, stackval *sp)
67 MonoMethodNormal *mm = (MonoMethodNormal *)mh;
68 fprintf (stderr, "Execution aborted in method: %s\n", mh->name);
69 fprintf (stderr, "Line=%d IP=0x%04x, Aborted execution\n", line,
70 ip-(unsigned char *)mm->header->code);
71 g_print ("0x%04x %02x\n",
72 ip-(unsigned char*)mm->header->code, *ip);
74 printf ("\t[%d] %d 0x%08x %0.5f\n", sp-stack, sp[-1].type, sp[-1].data.i, sp[-1].data.f);
77 #define ves_abort() ves_real_abort(__LINE__, mh, ip, stack, sp)
81 * @klass: klass that needs to be initialized
83 * This routine calls the class constructor for @class if it needs it.
86 init_class (MonoClass *klass)
88 guint32 cols [MONO_METHOD_SIZE];
96 init_class (klass->parent);
98 m = &klass->image->metadata;
99 t = &m->tables [MONO_TABLE_METHOD];
101 for (i = klass->method.first; i < klass->method.last; ++i) {
102 mono_metadata_decode_row (t, i, cols, MONO_METHOD_SIZE);
104 if (strcmp (".cctor", mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0) {
105 MonoMethod *cctor = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (i + 1));
106 ves_exec_method (cctor, NULL);
107 mono_free_method (cctor);
112 /* No class constructor found */
118 * @image: image where the object is being referenced
119 * @token: method token to invoke
121 * This routine creates a new object based on the class where the
122 * constructor lives.x
125 newobj (MonoImage *image, guint32 token)
127 MonoMetadata *m = &image->metadata;
128 MonoObject *result = NULL;
130 switch (mono_metadata_token_code (token)){
131 case MONO_TOKEN_METHOD_DEF: {
132 guint32 idx = mono_metadata_typedef_from_method (m, token);
133 result = mono_object_new (image, MONO_TOKEN_TYPE_DEF | idx);
136 case MONO_TOKEN_MEMBER_REF: {
137 guint32 member_cols [MONO_MEMBERREF_SIZE];
138 guint32 mpr_token, table, idx;
140 mono_metadata_decode_row (
141 &m->tables [MONO_TABLE_MEMBERREF],
142 mono_metadata_token_index (token) - 1,
143 member_cols, CSIZE (member_cols));
144 mpr_token = member_cols [MONO_MEMBERREF_CLASS];
145 table = mpr_token & 7;
146 idx = mpr_token >> 3;
148 if (strcmp (mono_metadata_string_heap (m, member_cols[1]), ".ctor"))
149 g_error ("Unhandled: call to non constructor");
152 case 0: /* TypeDef */
153 result = mono_object_new (image, MONO_TOKEN_TYPE_DEF | idx);
155 case 1: /* TypeRef */
156 result = mono_object_new (image, MONO_TOKEN_TYPE_REF | idx);
158 case 2: /* ModuleRef */
159 g_error ("Unhandled: ModuleRef");
161 case 3: /* MethodDef */
162 g_error ("Unhandled: MethodDef");
164 case 4: /* TypeSpec */
165 result = mono_object_new (image, MONO_TOKEN_TYPE_SPEC | idx);
172 init_class (result->klass);
177 get_virtual_method (MonoImage *image, guint32 token, stackval *args)
179 switch (mono_metadata_token_table (token)) {
180 case MONO_TABLE_METHOD:
181 case MONO_TABLE_MEMBERREF:
182 return mono_get_method (image, token);
184 g_error ("got virtual method: 0x%x\n", token);
189 stackval_from_data (MonoType *type, const char *data, guint offset)
192 switch (type->type) {
194 result.type = VAL_I32;
195 result.data.i = *(gint8*)(data + offset);
198 case MONO_TYPE_BOOLEAN:
199 result.type = VAL_I32;
200 result.data.i = *(guint8*)(data + offset);
203 result.type = VAL_I32;
204 result.data.i = *(gint16*)(data + offset);
208 result.type = VAL_I32;
209 result.data.i = *(guint16*)(data + offset);
212 result.type = VAL_I32;
213 result.data.i = *(gint32*)(data + offset);
216 result.type = VAL_I32;
217 result.data.i = *(guint32*)(data + offset);
220 result.type = VAL_DOUBLE;
221 result.data.f = *(float*)(data + offset);
224 result.type = VAL_DOUBLE;
225 result.data.f = *(double*)(data + offset);
227 case MONO_TYPE_STRING:
228 case MONO_TYPE_SZARRAY:
229 case MONO_TYPE_CLASS:
230 case MONO_TYPE_OBJECT:
231 case MONO_TYPE_ARRAY:
232 result.type = VAL_OBJ;
233 result.data.p = *(gpointer*)(data + offset);
236 g_warning ("got type %x", type->type);
237 g_assert_not_reached ();
243 stackval_to_data (MonoType *type, stackval *val, char *data, guint offset)
245 switch (type->type) {
248 *(guint8*)(data + offset) = val->data.i;
250 case MONO_TYPE_BOOLEAN:
251 *(guint8*)(data + offset) = (val->data.i != 0);
255 *(guint16*)(data + offset) = val->data.i;
259 *(gint32*)(data + offset) = val->data.i;
262 *(float*)(data + offset) = val->data.f;
265 *(double*)(data + offset) = val->data.f;
267 case MONO_TYPE_STRING:
268 case MONO_TYPE_SZARRAY:
269 case MONO_TYPE_CLASS:
270 case MONO_TYPE_OBJECT:
271 case MONO_TYPE_ARRAY:
272 *(gpointer*)(data + offset) = val->data.p;
275 g_warning ("got type %x", type->type);
276 g_assert_not_reached ();
281 mono_get_ansi_string (MonoObject *o)
283 MonoStringObject *s = (MonoStringObject *)o;
287 g_assert (o != NULL);
290 return g_strdup ("");
292 vector = s->c_str->vector;
294 g_assert (vector != NULL);
296 as = g_malloc (s->length + 1);
298 /* fixme: replace with a real unicode/ansi conversion */
299 for (i = 0; i < s->length; i++) {
300 as [i] = vector [i*2];
309 ves_icall_array_Set (MonoMethod *mh, stackval *sp)
317 g_assert (sp [0].type == VAL_OBJ);
320 ao = (MonoArrayObject *)o;
321 ac = (MonoArrayClass *)o->klass;
323 g_assert (ac->rank >= 1);
325 pos = sp [1].data.i - ao->bounds [0].lower_bound;
326 for (i = 1; i < ac->rank; i++) {
327 if ((t = sp [i + 1].data.i - ao->bounds [i].lower_bound) >= ao->bounds [i].length) {
328 g_warning ("wrong array index");
329 g_assert_not_reached ();
331 pos = pos*ao->bounds [i].length + sp [i + 1].data.i - ao->bounds [i].lower_bound;
334 ea = ao->vector + (pos * ac->esize);
335 memcpy (ea, &sp [ac->rank + 1].data.p, ac->esize);
339 ves_icall_array_Get (MonoMethod *mh, stackval *sp)
347 g_assert (sp [0].type == VAL_OBJ);
350 ao = (MonoArrayObject *)o;
351 ac = (MonoArrayClass *)o->klass;
353 g_assert (ac->rank >= 1);
355 pos = sp [1].data.i - ao->bounds [0].lower_bound;
356 for (i = 1; i < ac->rank; i++)
357 pos = pos*ao->bounds [i].length + sp [i + 1].data.i - ao->bounds [i].lower_bound;
359 ea = ao->vector + (pos * ac->esize);
361 sp [0].type = VAL_I32; /* fixme: not really true */
362 memcpy (&sp [0].data.p, ea, ac->esize);
366 ves_icall_System_Array_GetValue (MonoMethod *mh, stackval *sp)
368 MonoArrayObject *ao, *io;
369 MonoArrayClass *ac, *ic;
373 g_assert (sp [0].type == VAL_OBJ);
374 g_assert (sp [1].type == VAL_OBJ); /* expect an array of integers */
377 ic = (MonoArrayClass *)io->obj.klass;
379 ao = (MonoArrayObject *)sp [0].data.p;
380 ac = (MonoArrayClass *)ao->obj.klass;
382 g_assert (ic->rank == 1);
383 g_assert (io->bounds [0].length == ac->rank);
385 ind = (guint32 *)io->vector;
387 pos = ind [0] - ao->bounds [0].lower_bound;
388 for (i = 1; i < ac->rank; i++)
389 pos = pos*ao->bounds [i].length + ind [i] -
390 ao->bounds [i].lower_bound;
392 ea = ao->vector + (pos * ac->esize);
394 sp [0].type = VAL_OBJ;
396 if (ac->class.evaltype)
397 sp [0].data.p = mono_value_box (ac->class.image,
398 ac->etype_token, ea);
404 ves_icall_System_Array_SetValue (MonoMethod *mh, stackval *sp)
406 MonoArrayObject *ao, *io, *vo;
407 MonoArrayClass *ac, *ic, *vc;
411 g_assert (sp [0].type == VAL_OBJ);
412 g_assert (sp [1].type == VAL_OBJ); /* the value object */
413 g_assert (sp [2].type == VAL_OBJ); /* expect an array of integers */
416 vc = (MonoArrayClass *)vo->obj.klass;
419 ic = (MonoArrayClass *)io->obj.klass;
421 ao = (MonoArrayObject *)sp [0].data.p;
422 ac = (MonoArrayClass *)ao->obj.klass;
424 g_assert (ic->rank == 1);
425 g_assert (io->bounds [0].length == ac->rank);
427 g_assert (ac->etype_token == vc->class.type_token);
429 ind = (guint32 *)io->vector;
431 pos = ind [0] - ao->bounds [0].lower_bound;
432 for (i = 1; i < ac->rank; i++)
433 pos = pos*ao->bounds [i].length + ind [i] -
434 ao->bounds [i].lower_bound;
436 ea = ao->vector + (pos * ac->esize);
438 if (ac->class.evaltype) {
439 g_assert (vc->class.valuetype);
441 memcpy (ea, (char *)vo + sizeof (MonoObject), ac->esize);
447 ves_icall_array_ctor (MonoMethod *mh, stackval *sp)
454 g_assert (sp [0].type == VAL_OBJ);
457 ao = (MonoArrayObject *)o;
458 ac = (MonoArrayClass *)o->klass;
460 g_assert (ac->rank >= 1);
463 for (i = 1; i < ac->rank; i++)
464 len *= sp [i + 1].data.i;
466 ao->vector = g_malloc0 (len * ac->esize);
467 ao->bounds = g_malloc0 (ac->rank * sizeof (MonoArrayBounds));
469 for (i = 0; i < ac->rank; i++)
470 ao->bounds [i].length = sp [i + 1].data.i;
474 ves_icall_array_bound_ctor (MonoMethod *mh, stackval *sp)
479 g_assert (sp [0].type == VAL_OBJ);
482 ac = (MonoArrayClass *)o->klass;
484 g_warning ("experimental implementation");
485 g_assert_not_reached ();
489 ves_icall_System_Array_GetRank (MonoMethod *mh, stackval *sp)
493 g_assert (sp [0].type == VAL_OBJ);
497 sp [0].data.i = ((MonoArrayClass *)o->klass)->rank;
498 sp [0].type = VAL_I32;
502 ves_icall_System_Array_GetLength (MonoMethod *mh, stackval *sp)
506 g_assert (sp [0].type == VAL_OBJ);
510 sp [0].data.i = ((MonoArrayObject *)o)->bounds [sp [1].data.i].length;
511 sp [0].type = VAL_I32;
515 ves_icall_System_Array_GetLowerBound (MonoMethod *mh, stackval *sp)
519 g_assert (sp [0].type == VAL_OBJ);
523 sp [0].data.i = ((MonoArrayObject *)o)->bounds [sp [1].data.i].lower_bound;
524 sp [0].type = VAL_I32;
528 mono_lookup_internal_call (const char *name)
530 static GHashTable *icall_hash = NULL;
534 icall_hash = g_hash_table_new (g_str_hash , g_str_equal);
536 g_hash_table_insert (icall_hash, "__array_Set",
537 &ves_icall_array_Set);
538 g_hash_table_insert (icall_hash, "__array_Get",
539 &ves_icall_array_Get);
540 g_hash_table_insert (icall_hash, "__array_ctor",
541 &ves_icall_array_ctor);
542 g_hash_table_insert (icall_hash, "__array_bound_ctor",
543 &ves_icall_array_bound_ctor);
544 g_hash_table_insert (icall_hash, "System.Array::GetValue",
545 &ves_icall_System_Array_GetValue);
546 g_hash_table_insert (icall_hash, "System.Array::SetValue",
547 &ves_icall_System_Array_SetValue);
548 g_hash_table_insert (icall_hash, "System.Array::GetRank",
549 &ves_icall_System_Array_GetRank);
550 g_hash_table_insert (icall_hash, "System.Array::GetLength",
551 &ves_icall_System_Array_GetLength);
552 g_hash_table_insert (icall_hash, "System.Array::GetLowerBound",
553 &ves_icall_System_Array_GetLowerBound);
556 if (!(res = g_hash_table_lookup (icall_hash, name))) {
557 g_warning ("cant resolve internal call to \"%s\"", name);
558 g_assert_not_reached ();
565 ves_pinvoke_method (MonoMethod *mh, stackval *sp)
567 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)mh;
571 int i, acount, rsize, align;
573 GSList *t, *l = NULL;
575 acount = mh->signature->param_count;
577 values = alloca (sizeof (gpointer) * acount);
579 /* fixme: only works on little endian mashines */
581 for (i = 0; i < acount; i++) {
583 switch (mh->signature->params [i]->type->type) {
587 case MONO_TYPE_BOOLEAN:
593 values[i] = &sp [i].data.i;
596 tmp_float = alloca (sizeof (float));
597 *tmp_float = sp [i].data.f;
598 values[i] = tmp_float;
601 values[i] = &sp [i].data.f;
603 case MONO_TYPE_STRING:
604 g_assert (sp [i].type == VAL_OBJ);
606 if (mh->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI && sp [i].data.p) {
607 tmp_string = alloca (sizeof (char *));
608 *tmp_string = mono_get_ansi_string (sp [i].data.p);
609 l = g_slist_prepend (l, *tmp_string);
610 values[i] = tmp_string;
613 * fixme: may we pass the object - I assume
616 values[i] = &sp [i].data.p;
621 g_warning ("not implemented %x",
622 mh->signature->params [i]->type->type);
623 g_assert_not_reached ();
628 if ((rsize = mono_type_size (mh->signature->ret->type, &align)))
629 res = alloca (rsize);
631 ffi_call (piinfo->cif, mh->addr, res, values);
641 if (mh->signature->ret->type)
642 *sp = stackval_from_data (mh->signature->ret->type, res, 0);
645 #define DEBUG_INTERP 1
647 #define OPDEF(a,b,c,d,e,f,g,h,i,j) b,
648 static char *opcode_names[] = {
649 #include "mono/cil/opcode.def"
658 for (h = 0; h < debug_indent_level; h++)
663 dump_stack (stackval *stack, stackval *sp)
675 case VAL_I32: g_print ("[%d] ", s->data.i); break;
676 case VAL_I64: g_print ("[%lld] ", s->data.l); break;
677 case VAL_DOUBLE: g_print ("[%0.5f] ", s->data.f); break;
678 default: g_print ("[%p] ", s->data.p); break;
686 #define DEFAULT_LOCALS_SIZE 64
689 * Need to optimize ALU ops when natural int == int32
691 * Need to design how exceptions are supposed to work...
693 * IDEA: if we maintain a stack of ip, sp to be checked
694 * in the return opcode, we could inline simple methods that don't
695 * use the stack or local variables....
697 * The {,.S} versions of many opcodes can/should be merged to reduce code
700 * -fomit-frame-pointer gives about 2% speedup.
703 ves_exec_method (MonoMethod *mh, stackval *args)
705 MonoMethodNormal *mm = (MonoMethodNormal *)mh;
707 register const unsigned char *ip;
708 register stackval *sp;
709 char locals_store [DEFAULT_LOCALS_SIZE];
710 char *locals = locals_store;
713 if (mh->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
714 ICallMethod icall = mh->addr;
720 if (mh->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
721 ves_pinvoke_method (mh, args);
725 ip = mm->header->code;
728 debug_indent_level++;
730 g_print ("Entering %s\n", mh->name);
734 * with alloca we get the expected huge performance gain
735 * stackval *stack = g_new0(stackval, mh->max_stack);
737 /* We allocate one more stack val and increase stack temporarily to handle
738 * passing this to instance methods: this needs to be removed when we'll
739 * use a different argument passing mechanism.
742 stack = alloca (sizeof (stackval) * (mm->header->max_stack + 1));
746 if (mm->header->num_locals && mm->header->locals_offsets [0] > DEFAULT_LOCALS_SIZE) {
747 locals = alloca (mm->header->locals_offsets [0]);
751 * using while (ip < end) may result in a 15% performance drop,
752 * but it may be useful for debug
755 /*g_assert (sp >= stack);*/
757 dump_stack (stack, sp);
760 g_print ("0x%04x: %s\n",
761 ip-(unsigned char*)mm->header->code,
762 *ip == 0xfe ? opcode_names [256 + ip [1]] : opcode_names [*ip]);
771 G_BREAKPOINT (); /* this is not portable... */
777 *sp = args [(*ip)-CEE_LDARG_0];
785 int n = (*ip)-CEE_LDLOC_0;
787 *sp = stackval_from_data (mm->header->locals [n], locals,
788 n ? mm->header->locals_offsets [n]: 0);
796 int n = (*ip)-CEE_STLOC_0;
799 stackval_to_data (mm->header->locals [n], sp, locals,
800 n ? mm->header->locals_offsets [n]: 0);
812 sp->data.p = &(args [*ip]);
816 CASE (CEE_STARG_S) ves_abort(); BREAK;
819 *sp = stackval_from_data (mm->header->locals [*ip], locals,
820 *ip ? mm->header->locals_offsets [*ip]: 0);
827 sp->data.p = locals + (*ip ? mm->header->locals_offsets [*ip]: 0);
834 stackval_to_data (mm->header->locals [*ip], sp, locals,
835 *ip ? mm->header->locals_offsets [*ip]: 0);
860 sp->data.i = (*ip) - CEE_LDC_I4_0;
867 sp->data.i = *ip; /* FIXME: signed? */
874 sp->data.i = read32 (ip);
881 sp->data.i = read64 (ip);
887 sp->type = VAL_DOUBLE;
888 /* FIXME: ENOENDIAN */
889 sp->data.f = *(float*)(ip);
890 ip += sizeof (float);
895 sp->type = VAL_DOUBLE;
896 /* FIXME: ENOENDIAN */
897 sp->data.f = *(double*) (ip);
898 ip += sizeof (double);
901 CASE (CEE_UNUSED99) ves_abort (); BREAK;
911 CASE (CEE_JMP) ves_abort(); BREAK;
912 CASE (CEE_CALLVIRT) /* Fall through */
916 int virtual = *ip == CEE_CALLVIRT;
922 cmh = get_virtual_method (mh->image, token, sp);
924 cmh = mono_get_method (mh->image, token);
925 g_assert (cmh->signature->call_convention == MONO_CALL_DEFAULT);
927 /* decrement by the actual number of args */
928 sp -= cmh->signature->param_count;
929 if (cmh->signature->hasthis) {
930 g_assert (sp >= stack);
932 g_assert (sp->type == VAL_OBJ);
935 /* we need to truncate according to the type of args ... */
936 ves_exec_method (cmh, sp);
938 /* need to handle typedbyref ... */
939 if (cmh->signature->ret->type)
943 CASE (CEE_CALLI) ves_abort(); BREAK;
945 if (mh->signature->ret->type) {
950 g_warning ("more values on stack: %d", sp-stack);
952 /* g_free (stack); */
954 debug_indent_level--;
959 ip += (signed char) *ip;
962 CASE (CEE_BRFALSE_S) {
967 case VAL_I32: result = sp->data.i == 0; break;
968 case VAL_I64: result = sp->data.l == 0; break;
969 case VAL_DOUBLE: result = sp->data.f ? 0: 1; break;
970 default: result = sp->data.p == NULL; break;
973 ip += (signed char)*ip;
977 CASE (CEE_BRTRUE_S) {
982 case VAL_I32: result = sp->data.i != 0; break;
983 case VAL_I64: result = sp->data.l != 0; break;
984 case VAL_DOUBLE: result = sp->data.f ? 1 : 0; break;
985 default: result = sp->data.p != NULL; break;
988 ip += (signed char)*ip;
996 if (sp->type == VAL_I32)
997 result = sp [0].data.i == GET_NATI (sp [1]);
998 else if (sp->type == VAL_I64)
999 result = sp [0].data.l == sp [1].data.l;
1000 else if (sp->type == VAL_DOUBLE)
1001 result = sp [0].data.f == sp [1].data.f;
1003 result = GET_NATI (sp [0]) == GET_NATI (sp [1]);
1005 ip += (signed char)*ip;
1013 if (sp->type == VAL_I32)
1014 result = sp [0].data.i >= GET_NATI (sp [1]);
1015 else if (sp->type == VAL_I64)
1016 result = sp [0].data.l >= sp [1].data.l;
1017 else if (sp->type == VAL_DOUBLE)
1018 result = sp [0].data.f >= sp [1].data.f;
1020 result = GET_NATI (sp [0]) >= GET_NATI (sp [1]);
1022 ip += (signed char)*ip;
1030 if (sp->type == VAL_I32)
1031 result = sp [0].data.i > GET_NATI (sp [1]);
1032 else if (sp->type == VAL_I64)
1033 result = sp [0].data.l > sp [1].data.l;
1034 else if (sp->type == VAL_DOUBLE)
1035 result = sp [0].data.f > sp [1].data.f;
1037 result = GET_NATI (sp [0]) > GET_NATI (sp [1]);
1039 ip += (signed char)*ip;
1047 if (sp->type == VAL_I32)
1048 result = sp[0].data.i < GET_NATI(sp[1]);
1049 else if (sp->type == VAL_I64)
1050 result = sp[0].data.l < sp[1].data.l;
1051 else if (sp->type == VAL_DOUBLE)
1052 result = sp[0].data.f < sp[1].data.f;
1054 result = GET_NATI(sp[0]) < GET_NATI(sp[1]);
1056 ip += (signed char)*ip;
1065 if (sp->type == VAL_I32)
1066 result = sp [0].data.i <= GET_NATI (sp [1]);
1067 else if (sp->type == VAL_I64)
1068 result = sp [0].data.l <= sp [1].data.l;
1069 else if (sp->type == VAL_DOUBLE)
1070 result = sp [0].data.f <= sp [1].data.f;
1073 * FIXME: here and in other places GET_NATI on the left side
1074 * _will_ be wrong when we change the macro to work on 64 buts
1077 result = GET_NATI (sp [0]) <= GET_NATI (sp [1]);
1080 ip += (signed char)*ip;
1084 CASE (CEE_BNE_UN_S) {
1088 if (sp->type == VAL_I32)
1089 result = (guint32)sp [0].data.i != (guint32)GET_NATI (sp [1]);
1090 else if (sp->type == VAL_I64)
1091 result = (guint64)sp [0].data.l != (guint64)sp [1].data.l;
1092 else if (sp->type == VAL_DOUBLE)
1093 result = isunordered (sp [0].data.f, sp [1].data.f) ||
1094 (sp [0].data.f != sp [1].data.f);
1096 result = GET_NATI (sp [0]) != GET_NATI (sp [1]);
1098 ip += (signed char)*ip;
1102 CASE (CEE_BGE_UN_S) {
1106 if (sp->type == VAL_I32)
1107 result = (guint32)sp [0].data.i >= (guint32)GET_NATI (sp [1]);
1108 else if (sp->type == VAL_I64)
1109 result = (guint64)sp [0].data.l >= (guint64)sp [1].data.l;
1110 else if (sp->type == VAL_DOUBLE)
1111 result = !isless (sp [0].data.f,sp [1].data.f);
1113 result = GET_NATI (sp [0]) >= GET_NATI (sp [1]);
1115 ip += (signed char)*ip;
1119 CASE (CEE_BGT_UN_S) {
1123 if (sp->type == VAL_I32)
1124 result = (guint32)sp [0].data.i > (guint32)GET_NATI (sp [1]);
1125 else if (sp->type == VAL_I64)
1126 result = (guint64)sp [0].data.l > (guint64)sp [1].data.l;
1127 else if (sp->type == VAL_DOUBLE)
1128 result = isgreater (sp [0].data.f, sp [1].data.f);
1130 result = GET_NATI (sp [0]) > GET_NATI (sp [1]);
1132 ip += (signed char)*ip;
1136 CASE (CEE_BLE_UN_S) {
1140 if (sp->type == VAL_I32)
1141 result = (guint32)sp [0].data.i <= (guint32)GET_NATI (sp [1]);
1142 else if (sp->type == VAL_I64)
1143 result = (guint64)sp [0].data.l <= (guint64)sp [1].data.l;
1144 else if (sp->type == VAL_DOUBLE)
1145 result = islessequal (sp [0].data.f, sp [1].data.f);
1147 result = GET_NATI (sp [0]) <= GET_NATI (sp [1]);
1149 ip += (signed char)*ip;
1153 CASE (CEE_BLT_UN_S) {
1157 if (sp->type == VAL_I32)
1158 result = (guint32)sp[0].data.i < (guint32)GET_NATI(sp[1]);
1159 else if (sp->type == VAL_I64)
1160 result = (guint64)sp[0].data.l < (guint64)sp[1].data.l;
1161 else if (sp->type == VAL_DOUBLE)
1162 result = isunordered (sp [0].data.f, sp [1].data.f) ||
1163 (sp [0].data.f < sp [1].data.f);
1165 result = GET_NATI(sp[0]) < GET_NATI(sp[1]);
1167 ip += (signed char)*ip;
1171 CASE (CEE_BR) ves_abort(); BREAK;
1172 CASE (CEE_BRFALSE) ves_abort(); BREAK;
1173 CASE (CEE_BRTRUE) ves_abort(); BREAK;
1174 CASE (CEE_BEQ) ves_abort(); BREAK;
1175 CASE (CEE_BGE) ves_abort(); BREAK;
1176 CASE (CEE_BGT) ves_abort(); BREAK;
1177 CASE (CEE_BLE) ves_abort(); BREAK;
1178 CASE (CEE_BLT) ves_abort(); BREAK;
1179 CASE (CEE_BNE_UN) ves_abort(); BREAK;
1180 CASE (CEE_BGE_UN) ves_abort(); BREAK;
1181 CASE (CEE_BGT_UN) ves_abort(); BREAK;
1182 CASE (CEE_BLE_UN) ves_abort(); BREAK;
1183 CASE (CEE_BLT_UN) ves_abort(); BREAK;
1186 const unsigned char *st;
1190 st = ip + sizeof (gint32) * n;
1192 if ((guint32)sp->data.i < n) {
1194 ip += sizeof (gint32) * (guint32)sp->data.i;
1195 offset = read32 (ip);
1204 sp[-1].type = VAL_I32;
1205 sp[-1].data.i = *(gint8*)sp[-1].data.p;
1209 sp[-1].type = VAL_I32;
1210 sp[-1].data.i = *(guint8*)sp[-1].data.p;
1214 sp[-1].type = VAL_I32;
1215 sp[-1].data.i = *(gint16*)sp[-1].data.p;
1219 sp[-1].type = VAL_I32;
1220 sp[-1].data.i = *(guint16*)sp[-1].data.p;
1222 CASE (CEE_LDIND_I4) /* Fall through */
1225 sp[-1].type = VAL_I32;
1226 sp[-1].data.i = *(gint32*)sp[-1].data.p;
1230 sp[-1].type = VAL_I64;
1231 sp[-1].data.l = *(gint64*)sp[-1].data.p;
1235 sp[-1].type = VAL_NATI;
1236 sp[-1].data.p = *(gpointer*)sp[-1].data.p;
1240 sp[-1].type = VAL_DOUBLE;
1241 sp[-1].data.i = *(gfloat*)sp[-1].data.p;
1245 sp[-1].type = VAL_DOUBLE;
1246 sp[-1].data.i = *(gdouble*)sp[-1].data.p;
1248 CASE (CEE_LDIND_REF)
1250 sp[-1].type = VAL_OBJ;
1251 sp[-1].data.p = *(gpointer*)sp[-1].data.p;
1253 CASE (CEE_STIND_REF)
1256 *(gpointer*)sp->data.p = sp[1].data.p;
1261 *(gint8*)sp->data.p = (gint8)sp[1].data.i;
1266 *(gint16*)sp->data.p = (gint16)sp[1].data.i;
1271 *(gint32*)sp->data.p = sp[1].data.i;
1276 *(gint64*)sp->data.p = sp[1].data.l;
1281 *(gfloat*)sp->data.p = (gfloat)sp[1].data.f;
1286 *(gdouble*)sp->data.p = sp[1].data.f;
1291 /* should probably consider the pointers as unsigned */
1292 if (sp->type == VAL_I32)
1293 sp [-1].data.i += GET_NATI (sp [0]);
1294 else if (sp->type == VAL_I64)
1295 sp [-1].data.l += sp [0].data.l;
1296 else if (sp->type == VAL_DOUBLE)
1297 sp [-1].data.f += sp [0].data.f;
1299 (char*)sp [-1].data.p += GET_NATI (sp [0]);
1304 /* should probably consider the pointers as unsigned */
1305 if (sp->type == VAL_I32)
1306 sp [-1].data.i -= GET_NATI (sp [0]);
1307 else if (sp->type == VAL_I64)
1308 sp [-1].data.l -= sp [0].data.l;
1309 else if (sp->type == VAL_DOUBLE)
1310 sp [-1].data.f -= sp [0].data.f;
1312 (char*)sp [-1].data.p -= GET_NATI (sp [0]);
1317 if (sp->type == VAL_I32)
1318 sp [-1].data.i *= GET_NATI (sp [0]);
1319 else if (sp->type == VAL_I64)
1320 sp [-1].data.l *= sp [0].data.l;
1321 else if (sp->type == VAL_DOUBLE)
1322 sp [-1].data.f *= sp [0].data.f;
1327 if (sp->type == VAL_I32)
1328 sp [-1].data.i /= GET_NATI (sp [0]);
1329 else if (sp->type == VAL_I64)
1330 sp [-1].data.l /= sp [0].data.l;
1331 else if (sp->type == VAL_DOUBLE)
1332 sp [-1].data.f /= sp [0].data.f;
1337 if (sp->type == VAL_I32)
1338 (guint32)sp [-1].data.i /= (guint32)GET_NATI (sp [0]);
1339 else if (sp->type == VAL_I64)
1340 (guint64)sp [-1].data.l /= (guint64)sp [0].data.l;
1341 else if (sp->type == VAL_NATI)
1342 (gulong)sp [-1].data.p /= (gulong)sp [0].data.p;
1347 if (sp->type == VAL_I32)
1348 sp [-1].data.i %= GET_NATI (sp [0]);
1349 else if (sp->type == VAL_I64)
1350 sp [-1].data.l %= sp [0].data.l;
1351 else if (sp->type == VAL_DOUBLE)
1352 /* FIXME: what do we actually fo here? */
1355 GET_NATI (sp [-1]) %= GET_NATI (sp [0]);
1357 CASE (CEE_REM_UN) ves_abort(); BREAK;
1361 if (sp->type == VAL_I32)
1362 sp [-1].data.i &= GET_NATI (sp [0]);
1363 else if (sp->type == VAL_I64)
1364 sp [-1].data.l &= sp [0].data.l;
1366 GET_NATI (sp [-1]) &= GET_NATI (sp [0]);
1371 if (sp->type == VAL_I32)
1372 sp [-1].data.i |= GET_NATI (sp [0]);
1373 else if (sp->type == VAL_I64)
1374 sp [-1].data.l |= sp [0].data.l;
1376 GET_NATI (sp [-1]) |= GET_NATI (sp [0]);
1381 if (sp->type == VAL_I32)
1382 sp [-1].data.i ^= GET_NATI (sp [0]);
1383 else if (sp->type == VAL_I64)
1384 sp [-1].data.l ^= sp [0].data.l;
1386 GET_NATI (sp [-1]) ^= GET_NATI (sp [0]);
1391 if (sp->type == VAL_I32)
1392 sp [-1].data.i <<= GET_NATI (sp [0]);
1393 else if (sp->type == VAL_I64)
1394 sp [-1].data.l <<= GET_NATI (sp [0]);
1396 GET_NATI (sp [-1]) <<= GET_NATI (sp [0]);
1401 if (sp->type == VAL_I32)
1402 sp [-1].data.i >>= GET_NATI (sp [0]);
1403 else if (sp->type == VAL_I64)
1404 sp [-1].data.l >>= GET_NATI (sp [0]);
1406 GET_NATI (sp [-1]) >>= GET_NATI (sp [0]);
1408 CASE (CEE_SHR_UN) ves_abort(); BREAK;
1411 if (sp->type == VAL_I32)
1412 sp->data.i = - sp->data.i;
1413 else if (sp->type == VAL_I64)
1414 sp->data.l = - sp->data.l;
1415 else if (sp->type == VAL_DOUBLE)
1416 sp->data.f = - sp->data.f;
1417 else if (sp->type == VAL_NATI)
1418 sp->data.p = (gpointer)(- (m_i)sp->data.p);
1422 if (sp->type == VAL_I32)
1423 sp->data.i = ~ sp->data.i;
1424 else if (sp->type == VAL_I64)
1425 sp->data.l = ~ sp->data.l;
1426 else if (sp->type == VAL_NATI)
1427 sp->data.p = (gpointer)(~ (m_i)sp->data.p);
1429 CASE (CEE_CONV_I1) ves_abort(); BREAK;
1430 CASE (CEE_CONV_I2) ves_abort(); BREAK;
1431 CASE (CEE_CONV_I4) {
1433 /* FIXME: handle other cases. what about sign? */
1435 switch (sp [-1].type) {
1437 sp [-1].data.i = (gint32)sp [-1].data.f;
1438 sp [-1].type = VAL_I32;
1447 CASE (CEE_CONV_I8) ves_abort(); BREAK;
1448 CASE (CEE_CONV_R4) ves_abort(); BREAK;
1451 /* FIXME: handle other cases. what about sign? */
1452 if (sp [-1].type == VAL_I32) {
1453 sp [-1].data.f = (double)sp [-1].data.i;
1454 sp [-1].type = VAL_DOUBLE;
1461 /* FIXME: handle other cases. what about sign? */
1462 if (sp [-1].type == VAL_DOUBLE) {
1463 sp [-1].data.i = (guint32)sp [-1].data.f;
1464 sp [-1].type = VAL_I32;
1471 /* FIXME: handle other cases */
1472 if (sp [-1].type == VAL_I32) {
1473 /* defined as NOP */
1478 CASE (CEE_CONV_U8) ves_abort(); BREAK;
1479 CASE (CEE_CPOBJ) ves_abort(); BREAK;
1480 CASE (CEE_LDOBJ) ves_abort(); BREAK;
1482 guint32 ctor, ttoken;
1483 MonoMetadata *m = &mh->image->metadata;
1493 index = mono_metadata_token_index (read32 (ip));
1496 name = mono_metadata_user_string (m, index);
1497 len = mono_metadata_decode_blob_size (name, &name);
1499 * terminate with 0, maybe we should use another
1500 * constructor and pass the len
1502 data = g_malloc (len + 2);
1503 memcpy (data, name, len + 2);
1504 data [len/2 + 1] = 0;
1506 ctor = mono_get_string_class_info (&ttoken, &cl);
1507 o = mono_object_new (cl, ttoken);
1509 g_assert (o != NULL);
1511 cmh = mono_get_method (cl, ctor);
1516 sp[1].type = VAL_TP;
1517 sp[1].data.p = data;
1519 g_assert (cmh->signature->call_convention == MONO_CALL_DEFAULT);
1520 ves_exec_method (cmh, sp);
1536 token = read32 (ip);
1537 o = newobj (mh->image, token);
1540 /* call the contructor */
1541 cmh = mono_get_method (mh->image, token);
1544 * decrement by the actual number of args
1545 * need to pass object as first arg: we may overflow the stack here
1546 * until we use a different argument passing mechanism.
1547 * we shift the args to make room for the object reference
1549 for (pc = 0; pc < cmh->signature->param_count; ++pc)
1550 sp [-pc] = sp [-pc-1];
1551 sp -= cmh->signature->param_count + 1;
1555 g_assert (cmh->signature->call_convention == MONO_CALL_DEFAULT);
1558 * we need to truncate according to the type of args ...
1560 ves_exec_method (cmh, sp);
1562 * a constructor returns void, but we need to return the object we created
1570 CASE (CEE_CASTCLASS) ves_abort(); BREAK;
1571 CASE (CEE_ISINST) ves_abort(); BREAK;
1572 CASE (CEE_CONV_R_UN) ves_abort(); BREAK;
1573 CASE (CEE_UNUSED58) ves_abort(); BREAK;
1574 CASE (CEE_UNUSED1) ves_abort(); BREAK;
1581 token = read32 (ip);
1583 c = mono_class_get (mh->image, token);
1587 g_assert (o->klass->type_token == c->type_token);
1589 sp [-1].type = VAL_MP;
1590 sp [-1].data.p = (char *)o + sizeof (MonoObject);
1595 CASE (CEE_THROW) ves_abort(); BREAK;
1598 MonoClassField *field;
1602 token = read32 (ip);
1605 g_assert (sp [-1].type == VAL_OBJ);
1606 obj = sp [-1].data.p;
1607 field = mono_class_get_field (obj->klass, token);
1609 sp [-1] = stackval_from_data (field->type->type, (char*)obj, field->offset);
1612 CASE (CEE_LDFLDA) ves_abort(); BREAK;
1615 MonoClassField *field;
1619 token = read32 (ip);
1622 printf ("FIELD %08x\n",token);
1625 g_assert (sp [0].type == VAL_OBJ);
1626 obj = sp [0].data.p;
1627 field = mono_class_get_field (obj->klass, token);
1629 stackval_to_data (field->type->type, &sp [1], (char*)obj, field->offset);
1634 MonoClassField *field;
1638 token = read32 (ip);
1641 /* need to handle fieldrefs */
1642 klass = mono_class_get (mh->image,
1643 MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&mh->image->metadata, token & 0xffffff));
1644 field = mono_class_get_field (klass, token);
1646 *sp = stackval_from_data (field->type->type, (char*)klass, field->offset);
1650 CASE (CEE_LDSFLDA) ves_abort(); BREAK;
1653 MonoClassField *field;
1657 token = read32 (ip);
1661 /* need to handle fieldrefs */
1662 klass = mono_class_get (mh->image,
1663 MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (&mh->image->metadata, token & 0xffffff));
1664 field = mono_class_get_field (klass, token);
1666 stackval_to_data (field->type->type, sp, (char*)klass, field->offset);
1669 CASE (CEE_STOBJ) ves_abort(); BREAK;
1670 CASE (CEE_CONV_OVF_I1_UN) ves_abort(); BREAK;
1671 CASE (CEE_CONV_OVF_I2_UN) ves_abort(); BREAK;
1672 CASE (CEE_CONV_OVF_I4_UN) ves_abort(); BREAK;
1673 CASE (CEE_CONV_OVF_I8_UN) ves_abort(); BREAK;
1674 CASE (CEE_CONV_OVF_U1_UN) ves_abort(); BREAK;
1675 CASE (CEE_CONV_OVF_U2_UN) ves_abort(); BREAK;
1676 CASE (CEE_CONV_OVF_U4_UN) ves_abort(); BREAK;
1677 CASE (CEE_CONV_OVF_U8_UN) ves_abort(); BREAK;
1678 CASE (CEE_CONV_OVF_I_UN) ves_abort(); BREAK;
1679 CASE (CEE_CONV_OVF_U_UN) ves_abort(); BREAK;
1684 token = read32 (ip);
1686 sp [-1].type = VAL_OBJ;
1687 sp [-1].data.p = mono_value_box (mh->image, token,
1699 token = read32 (ip);
1700 o = mono_new_szarray (mh->image, token, sp [-1].data.i);
1703 sp [-1].type = VAL_OBJ;
1713 g_assert (sp [-1].type == VAL_OBJ);
1716 g_assert (o != NULL);
1718 g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
1720 sp [-1].type = VAL_I32;
1721 sp [-1].data.i = o->bounds [0].length;
1725 CASE (CEE_LDELEMA) ves_abort(); BREAK;
1726 CASE (CEE_LDELEM_I1) /* fall through */
1727 CASE (CEE_LDELEM_U1) /* fall through */
1728 CASE (CEE_LDELEM_I2) /* fall through */
1729 CASE (CEE_LDELEM_U2) /* fall through */
1730 CASE (CEE_LDELEM_I4) /* fall through */
1731 CASE (CEE_LDELEM_U4) /* fall through */
1732 CASE (CEE_LDELEM_I) /* fall through */
1733 CASE (CEE_LDELEM_R4) /* fall through */
1734 CASE (CEE_LDELEM_R8) /* fall through */
1735 CASE (CEE_LDELEM_REF) {
1740 g_assert (sp [0].type == VAL_OBJ);
1743 g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
1745 g_assert (sp [1].data.i >= 0);
1746 g_assert (sp [1].data.i < o->bounds [0].length);
1750 sp [0].data.i = ((gint8 *)o->vector)[sp [1].data.i];
1751 sp [0].type = VAL_I32;
1754 sp [0].data.i = ((guint8 *)o->vector)[sp [1].data.i];
1755 sp [0].type = VAL_I32;
1758 sp [0].data.i = ((gint16 *)o->vector)[sp [1].data.i];
1759 sp [0].type = VAL_I32;
1762 sp [0].data.i = ((guint16 *)o->vector)[sp [1].data.i];
1763 sp [0].type = VAL_I32;
1766 sp [0].data.i = ((gint32 *)o->vector)[sp [1].data.i];
1767 sp [0].type = VAL_NATI;
1770 sp [0].data.i = ((gint32 *)o->vector)[sp [1].data.i];
1771 sp [0].type = VAL_I32;
1774 sp [0].data.i = ((guint32 *)o->vector)[sp [1].data.i];
1775 sp [0].type = VAL_I32;
1778 sp [0].data.f = ((float *)o->vector)[sp [1].data.i];
1779 sp [0].type = VAL_DOUBLE;
1782 sp [0].data.i = ((double *)o->vector)[sp [1].data.i];
1783 sp [0].type = VAL_DOUBLE;
1785 case CEE_LDELEM_REF:
1786 sp [0].data.p = ((gpointer *)o->vector)[sp [1].data.i];
1787 sp [0].type = VAL_OBJ;
1798 CASE (CEE_LDELEM_I8) ves_abort(); BREAK;
1799 CASE (CEE_STELEM_I) /* fall through */
1800 CASE (CEE_STELEM_I1) /* fall through */
1801 CASE (CEE_STELEM_I2) /* fall through */
1802 CASE (CEE_STELEM_I4) /* fall through */
1803 CASE (CEE_STELEM_R4) /* fall through */
1804 CASE (CEE_STELEM_R8) /* fall through */
1805 CASE (CEE_STELEM_REF) {
1812 g_assert (sp [0].type == VAL_OBJ);
1815 g_assert (MONO_CLASS_IS_ARRAY (o->obj.klass));
1816 ac = (MonoArrayClass *)o->obj.klass;
1818 g_assert (sp [1].data.i >= 0);
1819 g_assert (sp [1].data.i < o->bounds [0].length);
1823 ((gint32 *)o->vector)[sp [1].data.i] =
1827 ((gint8 *)o->vector)[sp [1].data.i] =
1831 ((gint16 *)o->vector)[sp [1].data.i] =
1835 ((gint32 *)o->vector)[sp [1].data.i] =
1839 ((float *)o->vector)[sp [1].data.i] =
1843 ((double *)o->vector)[sp [1].data.i] =
1846 case CEE_STELEM_REF:
1847 g_assert (sp [2].type == VAL_OBJ);
1851 //fixme: what about type conversions ?
1852 g_assert (v->klass->type_token == ac->etype_token);
1854 ((gpointer *)o->vector)[sp [1].data.i] =
1865 CASE (CEE_STELEM_I8) ves_abort(); BREAK;
1881 CASE (CEE_UNUSED17) ves_abort(); BREAK;
1882 CASE (CEE_CONV_OVF_I1) ves_abort(); BREAK;
1883 CASE (CEE_CONV_OVF_U1) ves_abort(); BREAK;
1884 CASE (CEE_CONV_OVF_I2) ves_abort(); BREAK;
1885 CASE (CEE_CONV_OVF_U2) ves_abort(); BREAK;
1886 CASE (CEE_CONV_OVF_I4) ves_abort(); BREAK;
1887 CASE (CEE_CONV_OVF_U4)
1889 /* FIXME: handle other cases */
1890 if (sp [-1].type == VAL_I32) {
1891 /* defined as NOP */
1896 CASE (CEE_CONV_OVF_I8) ves_abort(); BREAK;
1897 CASE (CEE_CONV_OVF_U8) ves_abort(); BREAK;
1904 CASE (CEE_UNUSED23) ves_abort(); BREAK;
1905 CASE (CEE_REFANYVAL) ves_abort(); BREAK;
1906 CASE (CEE_CKFINITE) ves_abort(); BREAK;
1907 CASE (CEE_UNUSED24) ves_abort(); BREAK;
1908 CASE (CEE_UNUSED25) ves_abort(); BREAK;
1909 CASE (CEE_MKREFANY) ves_abort(); BREAK;
1918 CASE (CEE_UNUSED67) ves_abort(); BREAK;
1919 CASE (CEE_LDTOKEN) ves_abort(); BREAK;
1920 CASE (CEE_CONV_U2) ves_abort(); BREAK;
1921 CASE (CEE_CONV_U1) ves_abort(); BREAK;
1922 CASE (CEE_CONV_I) ves_abort(); BREAK;
1923 CASE (CEE_CONV_OVF_I) ves_abort(); BREAK;
1924 CASE (CEE_CONV_OVF_U) ves_abort(); BREAK;
1925 CASE (CEE_ADD_OVF) ves_abort(); BREAK;
1926 CASE (CEE_ADD_OVF_UN) ves_abort(); BREAK;
1927 CASE (CEE_MUL_OVF) ves_abort(); BREAK;
1928 CASE (CEE_MUL_OVF_UN) ves_abort(); BREAK;
1929 CASE (CEE_SUB_OVF) ves_abort(); BREAK;
1930 CASE (CEE_SUB_OVF_UN) ves_abort(); BREAK;
1931 CASE (CEE_ENDFINALLY) ves_abort(); BREAK;
1932 CASE (CEE_LEAVE) ves_abort(); BREAK;
1933 CASE (CEE_LEAVE_S) ves_abort(); BREAK;
1934 CASE (CEE_STIND_I) ves_abort(); BREAK;
1957 CASE (CEE_UNUSED48) ves_abort(); BREAK;
1958 CASE (CEE_PREFIX7) ves_abort(); BREAK;
1959 CASE (CEE_PREFIX6) ves_abort(); BREAK;
1960 CASE (CEE_PREFIX5) ves_abort(); BREAK;
1961 CASE (CEE_PREFIX4) ves_abort(); BREAK;
1962 CASE (CEE_PREFIX3) ves_abort(); BREAK;
1963 CASE (CEE_PREFIX2) ves_abort(); BREAK;
1964 CASE (CEE_PREFIXREF) ves_abort(); BREAK;
1968 case CEE_ARGLIST: ves_abort(); break;
1969 case CEE_CEQ: ves_abort(); break;
1970 case CEE_CGT: ves_abort(); break;
1971 case CEE_CGT_UN: ves_abort(); break;
1972 case CEE_CLT: ves_abort(); break;
1973 case CEE_CLT_UN: ves_abort(); break;
1974 case CEE_LDFTN: ves_abort(); break;
1975 case CEE_LDVIRTFTN: ves_abort(); break;
1976 case CEE_UNUSED56: ves_abort(); break;
1977 case CEE_LDARG: ves_abort(); break;
1978 case CEE_LDARGA: ves_abort(); break;
1979 case CEE_STARG: ves_abort(); break;
1980 case CEE_LDLOC: ves_abort(); break;
1981 case CEE_LDLOCA: ves_abort(); break;
1982 case CEE_STLOC: ves_abort(); break;
1983 case CEE_LOCALLOC: ves_abort(); break;
1984 case CEE_UNUSED57: ves_abort(); break;
1985 case CEE_ENDFILTER: ves_abort(); break;
1986 case CEE_UNALIGNED_: ves_abort(); break;
1987 case CEE_VOLATILE_: ves_abort(); break;
1988 case CEE_TAIL_: ves_abort(); break;
1989 case CEE_INITOBJ: ves_abort(); break;
1990 case CEE_UNUSED68: ves_abort(); break;
1991 case CEE_CPBLK: ves_abort(); break;
1992 case CEE_INITBLK: ves_abort(); break;
1993 case CEE_UNUSED69: ves_abort(); break;
1994 case CEE_RETHROW: ves_abort(); break;
1995 case CEE_UNUSED: ves_abort(); break;
1996 case CEE_SIZEOF: ves_abort(); break;
1997 case CEE_REFANYTYPE: ves_abort(); break;
2004 g_error ("Unimplemented opcode: 0xFE %02x at 0x%x\n", *ip, ip-(unsigned char*)mm->header->code);
2011 g_assert_not_reached ();
2015 ves_exec (MonoAssembly *assembly)
2017 MonoImage *image = assembly->image;
2018 MonoCLIImageInfo *iinfo;
2022 iinfo = image->image_info;
2024 /* we need to exec the class and object constructors... */
2025 mh = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point);
2026 ves_exec_method (mh, &result);
2027 fprintf (stderr, "result: %d\n", result.data.i);
2028 mono_free_method (mh);
2030 return result.data.i;
2036 fprintf (stderr, "Usage is: mono-int executable args...");
2041 main (int argc, char *argv [])
2043 MonoAssembly *assembly;
2052 assembly = mono_assembly_open (file, NULL, NULL);
2054 fprintf (stderr, "Can not open image %s\n", file);
2057 retval = ves_exec (assembly);
2058 mono_assembly_close (assembly);