2001-12-16 Dietmar Maurer <dietmar@ximian.com>
authorDietmar Maurer <dietmar@mono-cvs.ximian.com>
Mon, 17 Dec 2001 06:50:02 +0000 (06:50 -0000)
committerDietmar Maurer <dietmar@mono-cvs.ximian.com>
Mon, 17 Dec 2001 06:50:02 +0000 (06:50 -0000)
* emit-x86.c (arch_handle_exception): new code to handle
exceptions inside unmanaged code.

* x86.brg: impl. SAVE_LMF, RESTORE_LMF, pass implizit valuetype
address as first argument.

* x86.brg: pass exceptions on the stack

* jit.h (ISSTRUCT): new macro to check for real value types
(return false for enum types).

* unicode.c (_wapi_unicode_to_utf8): byteswap UTF16 strings before
passing them to iconv

* file-io.c: raise exceptions if handle is invalid.

svn path=/trunk/mono/; revision=1603

mono/arch/x86/x86-codegen.h
mono/io-layer/ChangeLog
mono/io-layer/io.c
mono/io-layer/unicode.c
mono/jit/ChangeLog
mono/jit/emit-x86.c
mono/jit/jit.c
mono/jit/jit.h
mono/jit/x86.brg
mono/metadata/ChangeLog
mono/metadata/file-io.c

index 08421ea6f7cf901d394d891cbea700200d2a0c72..c1cced3d0186a5a7915c29ed0547c1d89fa42415 100644 (file)
@@ -1,7 +1,7 @@
 /* Copyright (C)  2000 Intel Corporation.  All rights reserved.
    Copyright (C)  2001 Ximian, Inc. 
 //
-// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.18 2001/12/13 11:03:21 lupus Exp $
+// $Header: /home/miguel/third-conversion/public/mono/mono/arch/x86/x86-codegen.h,v 1.19 2001/12/17 06:50:02 dietmar Exp $
 */
 
 #ifndef X86_H
@@ -1089,6 +1089,12 @@ typedef union {
                x86_membase_emit ((inst), 6, (basereg), (disp));        \
        } while (0)
 
+#define x86_push_memindex(inst,basereg,disp,indexreg,shift)    \
+       do {    \
+               *(inst)++ = (unsigned char)0xff;        \
+               x86_memindex_emit ((inst), 6, (basereg), (disp), (indexreg), (shift));  \
+       } while (0)
+
 #define x86_push_imm(inst,imm) \
        do {    \
                *(inst)++ = (unsigned char)0x68;        \
index 3a14ea30ac4de8f190501cd39f5a97798bffb78b..3c4b641f0b92383d6e11641b2c83807858ced1ea 100644 (file)
@@ -1,3 +1,8 @@
+2001-12-17  Dietmar Maurer  <dietmar@ximian.com>
+
+       * unicode.c (_wapi_unicode_to_utf8): byteswap UTF16 strings before
+       passing them to iconv
+
 2001-12-11  Dick Porter  <dick@ximian.com>
 
        * io.c: Implement DeleteFile(), GetFileTime(), SetFileTime() and
index ec6992318a08df8b6f07c3ef53fbd03fc6e73ad9..d54be9fdc401dfbb30ebfebf848ed5b8edc2ed03 100644 (file)
@@ -709,8 +709,8 @@ WapiHandle *CreateFile(const guchar *name, guint32 fileaccess,
 
                return(INVALID_HANDLE_VALUE);
        }
-
        filename=_wapi_unicode_to_utf8(name);
+
 #ifdef ACTUALLY_DO_UNICODE
        if(filename==NULL) {
 #ifdef DEBUG
index 80176549b4a3c0eec3bbc023caac34e07e3edb37..21d9539b3eeb8a91aee31794db7e413b2bd3ad50 100644 (file)
@@ -72,18 +72,27 @@ guchar *_wapi_unicode_to_utf8(const guchar *uni)
        guint outbytes_remaining;
        size_t err;
        guint outbuf_size;
-       gint len;
+       gint i, len;
        gboolean have_error = FALSE;
        iconv_t converter;
   
        converter=unicode_reset();
-       
+
        g_return_val_if_fail(uni != NULL, NULL);
        g_return_val_if_fail(converter != (iconv_t) -1, NULL);
      
        len = unicode_len(uni);
+     
+
        str = g_memdup(uni, (guint32)len+2); /* don't forget the double NULL */
 
+       /* fixme: ugly - iconv expects big endian encoding 
+          UTF-16le does not work on older libc */
+       for (i = 0; i < len; i += 2) {
+               str [i] = uni [i + 1];
+               str [i + 1] = uni [i];
+       }
+
        p = str;
        inbytes_remaining = len;
        outbuf_size = len + 1; /* + 1 for nul in case len == 1 */
@@ -97,6 +106,7 @@ again:
        if(err == (size_t)-1) {
                switch(errno) {
                case EINVAL:
+                       have_error = TRUE;
                        /* Incomplete text, do not report an error */
                        break;
                case E2BIG: {
index 42ec63991609da10dfc0a92e446cb29e276050a8..197818e06dcbb4abadfe4c2a05c4e30160351519 100644 (file)
@@ -1,3 +1,18 @@
+2001-12-16  Dietmar Maurer  <dietmar@ximian.com>
+
+       * emit-x86.c (arch_handle_exception): new code to handle
+       exceptions inside unmanaged code.
+
+       * x86.brg: impl. SAVE_LMF, RESTORE_LMF, pass implizit valuetype
+       address as first argument.
+
+2001-12-15  Dietmar Maurer  <dietmar@ximian.com>
+
+       * x86.brg: pass exceptions on the stack
+
+       * jit.h (ISSTRUCT): new macro to check for real value types
+       (return false for enum types). 
+
 2001-12-11  Dietmar Maurer  <dietmar@ximian.com>
 
        * x86.brg: use position indepentent code if possible. 
index 9f53890deefb68fe1bf8fd615e50fd88081c5ed8..3b47b372241eec45ddb8a566174097c59cfaac46 100644 (file)
@@ -35,7 +35,7 @@ enter_method (MonoMethod *method, gpointer ebp)
 
        ebp += 8;
 
-       if (method->signature->ret->type == MONO_TYPE_VALUETYPE) {
+       if (ISSTRUCT (method->signature->ret)) {
                int size, align;
                
                g_assert (!method->signature->ret->byref);
@@ -908,9 +908,12 @@ arch_compile_method (MonoMethod *method)
 
                mono_compute_branches (cfg);
                
-               if (mono_jit_dump_asm)
-                       mono_disassemble_code (cfg->start, cfg->code - cfg->start);
-
+               if (mono_jit_dump_asm) {
+                       char *id = g_strdup_printf ("%s_%s__%s", method->klass->name_space,
+                                                   method->klass->name, method->name);
+                       mono_disassemble_code (cfg->start, cfg->code - cfg->start, id);
+                       g_free (id);
+               }
                if (mono_debug_handle)
                        mono_debug_add_method (mono_debug_handle, cfg);
 
@@ -1129,27 +1132,100 @@ arch_handle_exception (struct sigcontext *ctx, gpointer obj)
                }
 
                ctx->esp = ctx->ebp;
-
-               next_bp = *((int *)ctx->ebp);
-               next_ip = *((int *)ctx->ebp + 1);
+               ctx->eip = *((int *)ctx->ebp + 1);
+               ctx->ebp = *((int *)ctx->ebp);
                
-               if (next_bp < (unsigned)mono_end_of_stack) {
-
-                       ctx->eip = next_ip;
-                       ctx->ebp = next_bp;
+               if (next_bp < (unsigned)mono_end_of_stack)
                        arch_handle_exception (ctx, obj);
-
-               } else {
+               else
                        mono_jit_abort (obj);
-               }
 
        } else {
-               /* fixme: implement exceptions inside unmanaged code */
-               mono_jit_abort (obj);
+               gpointer *lmf_addr = TlsGetValue (lmf_thread_id);
+               MonoLMF *lmf;
+               MonoMethod *m;
+
+               g_assert (lmf_addr);
+               lmf = *((MonoLMF **)lmf_addr);
+
+               if (!lmf)
+                       mono_jit_abort (obj);
+
+               m = lmf->method;
+
+               *lmf_addr = lmf->previous_lmf;
+
+               ctx->esi = lmf->esi;
+               ctx->edi = lmf->edi;
+               ctx->ebx = lmf->ebx;
+               ctx->ebp = lmf->ebp;
+               ctx->eip = lmf->eip;
+               ctx->esp = lmf;
+
+               /*
+               g_warning ("Exception inside unmanaged code. %s.%s::%s %p", m->klass->name_space,
+                          m->klass->name, m->name, lmf->previous_lmf);
+               */
+
+               if (ctx->eip < (unsigned)mono_end_of_stack)
+                       arch_handle_exception (ctx, obj);
+               else
+                       mono_jit_abort (obj);
        }
 
        g_assert_not_reached ();
 }
 
+static void
+throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsigned long ebx,
+                unsigned long esi, unsigned long edi, unsigned long ebp, MonoObject *exc,
+                unsigned long eip,  unsigned long esp)
+{
+       struct sigcontext ctx;
+       
+       ctx.esp = esp;
+       ctx.eip = eip;
+       ctx.ebp = ebp;
+       ctx.edi = edi;
+       ctx.esi = esi;
+       ctx.ebx = ebx;
+       ctx.edx = edx;
+       ctx.ecx = ecx;
+       ctx.eax = eax;
+       
+       arch_handle_exception (&ctx, exc);
+
+       g_assert_not_reached ();
+}
+
+gpointer 
+arch_get_throw_exception (void)
+{
+       static guint8 *start = NULL;
+       guint8 *code;
+
+       if (start)
+               return start;
+
+       code = start = g_malloc (1024);
+
+       x86_push_reg (code, X86_ESP);
+       x86_push_membase (code, X86_ESP, 4); /* IP */
+       x86_push_membase (code, X86_ESP, 12); /* exception */
+       x86_push_reg (code, X86_EBP);
+       x86_push_reg (code, X86_EDI);
+       x86_push_reg (code, X86_ESI);
+       x86_push_reg (code, X86_EBX);
+       x86_push_reg (code, X86_EDX);
+       x86_push_reg (code, X86_ECX);
+       x86_push_reg (code, X86_EAX);
+       x86_call_code (code, throw_exception);
+       /* we should never reach this breakpoint */
+       x86_breakpoint (code);
+
+       return start;
+}
+
+
 
 
index 09877670454428c201c6057e3becbfbb257951b5..0e481127a5f185794ac8c6ec8f0e4eaf14179f0d 100644 (file)
@@ -23,6 +23,7 @@
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/tokentype.h>
 #include <mono/arch/x86/x86-codegen.h>
+#include <mono/io-layer/io-layer.h>
 
 #include "jit.h"
 #include "regset.h"
@@ -172,6 +173,9 @@ gpointer mono_end_of_stack = NULL;
 
 MonoJitInfoTable *mono_jit_info_table = NULL;
 
+/* last managed frame (used by pinvoke) */ 
+guint32 lmf_thread_id = 0;
+
 /* 
  * We sometimes need static data, for example the forest generator need it to
  * store constants or class data.
@@ -685,7 +689,7 @@ mono_print_forest (GPtrArray *forest)
  * Disassemble to code to stdout.
  */
 void
-mono_disassemble_code (guint8 *code, int size)
+mono_disassemble_code (guint8 *code, int size, char *id)
 {
        int i;
        FILE *ofd;
@@ -693,6 +697,8 @@ mono_disassemble_code (guint8 *code, int size)
        if (!(ofd = fopen ("/tmp/test.s", "w")))
                g_assert_not_reached ();
 
+       fprintf (ofd, "%s:\n", id);
+
        for (i = 0; i < size; ++i) 
                fprintf (ofd, ".byte %d\n", (unsigned int) code [i]);
 
@@ -843,7 +849,7 @@ ctree_create_store (MonoFlowGraph *cfg, MonoType *type, MBTree *addr,
 
        t = mono_ctree_new (mp, stind, addr, s);
 
-       if (!type->byref && type->type == MONO_TYPE_VALUETYPE)  
+       if (ISSTRUCT (type))
                t->data.i = mono_class_value_size (type->data.klass, NULL);
        
        return t;
@@ -1352,6 +1358,7 @@ mono_analyze_flow (MonoFlowGraph *cfg)
                                
                        case CEE_CEQ:
                        case CEE_CLT:
+                       case CEE_CGT:
                                ip++;
                                break;
                        case CEE_LDARG:
@@ -1586,12 +1593,9 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                }
        }
 
-       if (signature->ret->type == MONO_TYPE_VALUETYPE) {
+       if (ISSTRUCT (signature->ret)) {
                int size, align;
 
-               // fixme: maybe we must add this check to the above if statement
-               g_assert (!signature->ret->byref);
-
                cfg->has_vtarg = 1;
 
                size = mono_type_size (signature->ret, &align);
@@ -2174,9 +2178,14 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        ci =  mono_mempool_alloc0 (mp, sizeof (MethodCallInfo));
                        ci->m = cm;
 
-                       if ((cm->flags &  METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
-                           !(cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
-                               pinvoke = TRUE;
+                       if (cm->flags &  METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+                               if (!(cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+                                       pinvoke = TRUE;
+
+                               t1 = mono_ctree_new_leaf (mp, MB_TERM_SAVE_LMF);
+                               t1->data.m = cm;
+                               ADD_TREE (t1, cli_addr);
+                       }
 
                        if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
                            !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
@@ -2186,7 +2195,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        g_assert (csig->call_convention == MONO_CALL_DEFAULT);
                        g_assert (!virtual || csig->hasthis);
 
-                       /* fixme: we need to unbox the this pointer for value types */
+                       /* fixme: we need to unbox the this pointer for value types ?*/
                        g_assert (!virtual || !cm->klass->valuetype);
 
                        nargs = csig->param_count;
@@ -2219,7 +2228,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        } else
                                this = mono_ctree_new_leaf (mp, MB_TERM_NOP);
 
-                       if (csig->ret->type == MONO_TYPE_VALUETYPE) {
+                       if (ISSTRUCT (csig->ret)) {
                                int size, align;
                                size = mono_type_size (csig->ret, &align);
                                vtype_num = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
@@ -2307,6 +2316,11 @@ mono_analyze_stack (MonoFlowGraph *cfg)
    
                        }
 
+                       if (cm->flags &  METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+                               t1 = mono_ctree_new_leaf (mp, MB_TERM_RESTORE_LMF);
+                               ADD_TREE (t1, cli_addr);
+                       }
+
                        break;
                }
                case CEE_ISINST: {
@@ -2681,7 +2695,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        if (ret->type != MONO_TYPE_VOID) {
                                --sp;
-                               if (!ret->byref && ret->type == MONO_TYPE_VALUETYPE) {
+                               if (ISSTRUCT (ret)) {
                                        int align;
                                        t1 = mono_ctree_new (mp, MB_TERM_RET_OBJ, *sp, NULL);
                                        t1->data.i = mono_class_value_size (ret->data.klass, &align);
@@ -2928,6 +2942,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                                
                        MAKE_CMP (CEQ)
                        MAKE_CMP (CLT)
+                       MAKE_CMP (CGT)
 
                        case CEE_RETHROW: {
                                ++ip;
@@ -3252,8 +3267,12 @@ main (int argc, char *argv [])
 
        mono_jit_info_table = mono_jit_info_table_new ();
 
+       lmf_thread_id = TlsAlloc ();
+       TlsSetValue (lmf_thread_id, NULL);
+
        mono_install_runtime_class_init (runtime_class_init);
        mono_install_runtime_object_init (runtime_object_init);
+       mono_install_handler (arch_get_throw_exception ());
        mono_init ();
 
        /*
index 211280e0aa22d243bbbba0ab8c9efa4921c7f480..b97bec9cd45016b75101e6b178a3a1d565f6e120 100644 (file)
@@ -9,6 +9,8 @@
 #include "regset.h"
 #include "mempool.h"
 
+#define ISSTRUCT(t) (!t->byref && t->type == MONO_TYPE_VALUETYPE && !t->data.klass->enumtype)
+
 typedef struct _MBTree MBTree;
 
 typedef enum {
@@ -25,6 +27,18 @@ typedef enum {
        MONO_TEMPVAR,
 } MonoValueKind;
 
+typedef struct {
+       gpointer    previous_lmf;
+       gpointer    lmf_addr;
+       MonoMethod *method;
+       guint32     eip;
+       guint32     ebp;
+       guint32     esi;
+       guint32     edi;
+       guint32     ebx;
+
+} MonoLMF;
+
 typedef struct {
        MonoValueType type;
        MonoValueKind kind;
@@ -106,6 +120,8 @@ extern gboolean mono_jit_trace_calls;
 extern MonoJitInfoTable *mono_jit_info_table;
 extern gpointer mono_end_of_stack;
 
+extern guint32  lmf_thread_id;
+
 MonoJitInfoTable *
 mono_jit_info_table_new    (void);
 
@@ -121,6 +137,9 @@ mono_jit_info_table_find   (MonoJitInfoTable *table, gpointer addr);
 void
 arch_handle_exception      (struct sigcontext *ctx, gpointer obj);
 
+gpointer 
+arch_get_throw_exception   (void);
+
 void
 mono_jit_abort             (MonoObject *obj);
 
@@ -143,7 +162,7 @@ void
 mono_analyze_stack         (MonoFlowGraph *cfg);
 
 void
-mono_disassemble_code      (guint8 *code, int size);
+mono_disassemble_code      (guint8 *code, int size, char *id);
 
 gpointer 
 arch_compile_method        (MonoMethod *method);
index b171fa744729e76a7e1c378290df562d0d9bec16..28f6f693d8e00feea540446fda83c05b2909d2f0 100644 (file)
@@ -82,8 +82,7 @@ gint64  mono_llrem     (gint64 a, gint64 b);
 guint64 mono_lldiv_un  (guint64 a, guint64 b);
 guint64 mono_llrem_un  (guint64 a, guint64 b);
 
-gpointer 
-get_throw_exception    (void);
+gpointer arch_get_lmf_addr (void);
 
 gpointer
 get_mono_object_isinst (void);
@@ -145,8 +144,8 @@ x86_pop_reg (s->code, X86_EAX);
 #define EMIT_COND_EXCEPTION(cond, exc)                                       \
         do {                                                                 \
                x86_branch8 (s->code, cond, 12, TRUE);                       \
-               x86_mov_reg_imm (s->code, X86_ECX, exc);                     \
-               x86_mov_reg_imm (s->code, X86_EAX, get_throw_exception ());  \
+               x86_push_imm (s->code, exc);                                 \
+               x86_mov_reg_imm (s->code, X86_EAX, arch_get_throw_exception ());  \
                x86_call_reg (s->code, X86_EAX);                             \
        } while (0); 
 
@@ -165,13 +164,13 @@ x86_pop_reg (s->code, X86_EAX);
 %term BREAK SWITCH BR RET_VOID RET RET_OBJ ENDFINALLY
 %term ADD SUB MUL DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT
 %term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN 
-%term CEQ CLT
+%term CEQ CLT CGT
 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U8 CONV_R4 CONV_R8
 %term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWOBJ NEWSTRUCT CPOBJ POP INITOBJ
 %term ISINST CASTCLASS UNBOX
 %term CONV_OVF_I1 CONV_OVF_U1 CONV_OVF_I2 CONV_OVF_U2 CONV_OVF_U4 CONV_OVF_U8 CONV_OVF_I4
 %term CONV_OVF_I2_UN CONV_OVF_I8_UN CONV_OVF_I1_UN 
-%term EXCEPTION THROW RETHROW HANDLER 
+%term EXCEPTION THROW RETHROW HANDLER SAVE_LMF RESTORE_LMF
 %term LDLEN
 
 #
@@ -286,10 +285,8 @@ reg: EXCEPTION {
 stmt: THROW (reg) {
        tree->is_jump = TRUE;
 
-       if (tree->left->reg1 != X86_ECX)
-               x86_mov_reg_reg (s->code, X86_ECX, tree->left->reg1, 4);
-
-       x86_call_code (s->code, get_throw_exception ());
+       x86_push_reg (s->code, tree->left->reg1);
+       x86_call_code (s->code, arch_get_throw_exception ());
 }
 
 stmt: RETHROW {
@@ -297,9 +294,8 @@ stmt: RETHROW {
 
        tree->is_jump = TRUE;
 
-       x86_mov_reg_membase (s->code, X86_ECX, X86_EBP, offset, 4);
-
-       x86_call_code (s->code, get_throw_exception ());
+       x86_push_membase (s->code, X86_EBP, offset);
+       x86_call_code (s->code, arch_get_throw_exception ());
 }
 
 stmt: HANDLER {
@@ -312,6 +308,52 @@ stmt: ENDFINALLY {
        x86_ret (s->code);
 }
 
+stmt: SAVE_LMF {
+       tree->is_jump = TRUE;
+
+
+       /* save all caller saved regs */
+       x86_push_reg (s->code, X86_EBX);
+       x86_push_reg (s->code, X86_EDI);
+       x86_push_reg (s->code, X86_ESI);
+       x86_push_reg (s->code, X86_EBP);
+
+       /* save the IP */
+       x86_push_imm (s->code, s->code);
+
+       /* save method info */
+       x86_push_imm (s->code, tree->data.m);
+       /* get the address of lmf for the current thread */
+       x86_call_code (s->code, arch_get_lmf_addr);
+       /* push lmf */
+       x86_push_reg (s->code, X86_EAX); 
+       /* push *lfm (previous_lmf) */
+       x86_push_membase (s->code, X86_EAX, 0);
+       /* *(lmf) = ESP */
+       x86_mov_membase_reg (s->code, X86_EAX, 0, X86_ESP, 4);
+}
+
+stmt: RESTORE_LMF {
+       /* ebx = previous_lmf */
+       x86_pop_reg (s->code, X86_EBX);
+       /* edi = lmf */
+       x86_pop_reg (s->code, X86_EDI);
+       /* *(lmf) = previous_lmf */
+       x86_mov_membase_reg (s->code, X86_EDI, 0, X86_EBX, 4);
+
+       /* discard method info */
+       x86_pop_reg (s->code, X86_ESI);
+
+       /* discard save IP */
+       x86_pop_reg (s->code, X86_ESI);
+
+       /* restore caller saved regs */
+       x86_pop_reg (s->code, X86_EBP);
+       x86_pop_reg (s->code, X86_ESI);
+       x86_pop_reg (s->code, X86_EDI);
+       x86_pop_reg (s->code, X86_EBX);
+}
+
 stmt: STIND_I4 (addr, reg) {
        PRINT_REG ("STIND_I4", tree->right->reg1);
 
@@ -729,6 +771,12 @@ reg: CEQ (reg, reg) {
        x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
 }
 
+reg: CGT (reg, reg) {
+       x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
+       x86_set_reg (s->code, X86_CC_GT, tree->reg1, TRUE);
+       x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
+}
+
 reg: CLT (reg, reg) {
        x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1, tree->right->reg1);
        x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
@@ -1291,6 +1339,55 @@ stmt: RET_VOID {
        } 
 }
 
+
+stmt: ARG_I4 (LDIND_I4 (addr)) {
+       MBTree *at = tree->left->left;
+
+       switch (at->data.ainfo.amode) {
+
+       case AMImmediate:
+               x86_push_mem (s->code, at->data.ainfo.offset);
+               break;
+
+       case AMBase:
+               x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
+               break;          
+       case AMIndex:
+               x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
+                                  at->data.ainfo.indexreg, at->data.ainfo.shift);
+               break;          
+       case AMBaseIndex:
+               x86_push_memindex (s->code, at->data.ainfo.basereg, 
+                                  at->data.ainfo.offset, at->data.ainfo.indexreg, 
+                                  at->data.ainfo.shift);
+               break;          
+       }
+}
+
+stmt: ARG_I4 (LDIND_U4 (addr)) {
+       MBTree *at = tree->left->left;
+
+       switch (at->data.ainfo.amode) {
+
+       case AMImmediate:
+               x86_push_mem (s->code, at->data.ainfo.offset);
+               break;
+
+       case AMBase:
+               x86_push_membase (s->code, at->data.ainfo.basereg, at->data.ainfo.offset);
+               break;          
+       case AMIndex:
+               x86_push_memindex (s->code, X86_NOBASEREG, at->data.ainfo.offset,
+                                  at->data.ainfo.indexreg, at->data.ainfo.shift);
+               break;          
+       case AMBaseIndex:
+               x86_push_memindex (s->code, at->data.ainfo.basereg, 
+                                  at->data.ainfo.offset, at->data.ainfo.indexreg, 
+                                  at->data.ainfo.shift);
+               break;          
+       }
+}
+
 stmt: ARG_I4 (reg) {
        x86_push_reg (s->code, tree->left->reg1);
        PRINT_REG ("ARG_I4",  tree->left->reg1);
@@ -1342,17 +1439,17 @@ reg: CALL_I4 (this, reg) {
        if (lreg == treg || rreg == treg) 
                g_assert_not_reached ();
 
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
-       if (tree->left->op != MB_TERM_NOP) {
-               g_assert (lreg >= 0);
-               x86_push_reg (s->code, lreg);
-       }
-
        x86_call_reg (s->code, rreg);
 
        if (ci->args_size)
@@ -1371,17 +1468,17 @@ reg: CALL_I4 (this, LDIND_I4 (ADDR_G)) {
        if (lreg == treg) 
                treg = X86_EDX;
        
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
-       if (tree->left->op != MB_TERM_NOP) {
-               g_assert (lreg >= 0);
-               x86_push_reg (s->code, lreg);
-       }
-
        x86_call_mem (s->code, tree->right->left->data.p);
 
        if (ci->args_size)
@@ -1400,17 +1497,17 @@ reg: CALL_I4 (this, INTF_ADDR) {
        if (lreg == treg) 
                treg = X86_EDX;
 
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
-       if (tree->left->op != MB_TERM_NOP) {
-               g_assert (lreg >= 0);
-               x86_push_reg (s->code, lreg);
-       }
-
        x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
        x86_mov_reg_membase (s->code, lreg, lreg, 
                G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
@@ -1433,17 +1530,17 @@ reg: CALL_I4 (this, VFUNC_ADDR) {
        if (lreg == treg) 
                treg = X86_EDX;
 
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
-       if (tree->left->op != MB_TERM_NOP) {
-               g_assert (lreg >= 0);
-               x86_push_reg (s->code, lreg);
-       }
-
        x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
        x86_call_virtual (s->code, lreg, 
                G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
@@ -1500,7 +1597,6 @@ stmt: CALL_VOID (this, INTF_ADDR) {
                x86_push_reg (s->code, treg);
        }
 
-
        x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
        x86_mov_reg_membase (s->code, lreg, lreg, 
                G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
@@ -1576,8 +1672,8 @@ reg: CONV_OVF_I4 (lreg){
        x86_branch8 (s->code, X86_CC_EQ, 17, TRUE);
 
        /* throw exception */
-       x86_mov_reg_imm (s->code, X86_ECX, get_exception_overflow ());
-       x86_mov_reg_imm (s->code, X86_EAX, get_throw_exception ()); 
+       x86_push_imm (s->code, get_exception_overflow ());
+       x86_mov_reg_imm (s->code, X86_EAX, arch_get_throw_exception ()); 
        x86_call_reg (s->code, X86_EAX); 
        
        /* our top bit is set, check that top word is 0xfffffff */
@@ -1635,8 +1731,8 @@ lreg: CONV_U8 (CONST_I4) 1 {
 
 lreg: CONV_OVF_U8 (CONST_I4) {
        if (tree->left->data.i < 0){
-               x86_mov_reg_imm (s->code, X86_ECX, get_exception_overflow ());
-               x86_mov_reg_imm (s->code, X86_EAX, get_throw_exception ()); 
+               x86_push_imm (s->code, get_exception_overflow ());
+               x86_mov_reg_imm (s->code, X86_EAX, arch_get_throw_exception ()); 
                x86_call_reg (s->code, X86_EAX);                            
        } else {
                x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
@@ -1882,22 +1978,55 @@ lreg: CALL_I8 (this, LDIND_I4 (ADDR_G)) {
        if (lreg == treg) 
                treg = X86_EDX;
        
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
+       x86_call_mem (s->code, tree->right->left->data.p);
+
+       if (ci->args_size)
+               x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
+
+       g_assert (tree->reg1 == X86_EAX);
+       g_assert (tree->reg2 == X86_EDX);
+}
+
+lreg: CALL_I8 (this, VFUNC_ADDR) {
+       MethodCallInfo *ci = tree->data.ci;
+       int lreg = tree->left->reg1;
+       int treg = X86_EAX;
+
+       if (lreg == treg) 
+               treg = X86_EDX;
+
        if (tree->left->op != MB_TERM_NOP) {
                g_assert (lreg >= 0);
                x86_push_reg (s->code, lreg);
        }
 
-       x86_call_mem (s->code, tree->right->left->data.p);
+       if (ci->vtype_num) {
+               int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+               x86_lea_membase (s->code, treg, X86_EBP, offset);
+               x86_push_reg (s->code, treg);
+       }
+
+       x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
+       x86_call_virtual (s->code, lreg, 
+               G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
 
        if (ci->args_size)
                x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
 
+       PRINT_REG ("CALL0_I8(VIRTUAL)", tree->reg1);
+       PRINT_REG ("CALL1_I8(VIRTUAL)", tree->reg2);
+
        g_assert (tree->reg1 == X86_EAX);
        g_assert (tree->reg2 == X86_EDX);
 }
@@ -2352,17 +2481,17 @@ freg: CALL_R8 (this, LDIND_I4 (ADDR_G)) {
        if (lreg == treg) 
                treg = X86_EDX;
        
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
-       if (tree->left->op != MB_TERM_NOP) {
-               g_assert (lreg >= 0);
-               x86_push_reg (s->code, lreg);
-       }
-
        x86_call_mem (s->code, tree->right->left->data.p);
 
        if (ci->args_size)
@@ -2377,17 +2506,17 @@ freg: CALL_R8 (this, INTF_ADDR) {
        if (lreg == treg) 
                treg = X86_EDX;
 
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
-       if (tree->left->op != MB_TERM_NOP) {
-               g_assert (lreg >= 0);
-               x86_push_reg (s->code, lreg);
-       }
-
        x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
        x86_mov_reg_membase (s->code, lreg, lreg, 
                G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
@@ -2406,17 +2535,17 @@ freg: CALL_R8 (this, VFUNC_ADDR) {
        if (lreg == treg) 
                treg = X86_EDX;
 
+       if (tree->left->op != MB_TERM_NOP) {
+               g_assert (lreg >= 0);
+               x86_push_reg (s->code, lreg);
+       }
+
        if (ci->vtype_num) {
                int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
                x86_lea_membase (s->code, treg, X86_EBP, offset);
                x86_push_reg (s->code, treg);
        }
 
-       if (tree->left->op != MB_TERM_NOP) {
-               g_assert (lreg >= 0);
-               x86_push_reg (s->code, lreg);
-       }
-
        x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
        x86_call_virtual (s->code, lreg, 
                G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
@@ -2566,56 +2695,23 @@ mono_ctree_new_leaf (MonoMemPool *mp, int op)
        return mono_ctree_new (mp, op, NULL, NULL);
 }
 
-static void
-throw_exception (unsigned long eax, unsigned long ecx, unsigned long edx, unsigned long ebx,
-                unsigned long esi, unsigned long edi, unsigned long ebp, unsigned long eip,
-                unsigned long esp)
-{
-       MonoObject *exc = (gpointer)ecx;
-       struct sigcontext ctx;
-       
-       ctx.esp = esp;
-       ctx.eip = eip;
-       ctx.ebp = ebp;
-       ctx.edi = edi;
-       ctx.esi = esi;
-       ctx.ebx = ebx;
-       ctx.edx = edx;
-       ctx.ecx = ecx;
-       ctx.eax = eax;
-       
-       arch_handle_exception (&ctx, exc);
-
-       g_assert_not_reached ();
-}
-
 gpointer 
-get_throw_exception (void)
+arch_get_lmf_addr (void)
 {
-       static guint8 *start = NULL;
-       guint8 *code;
+       gpointer *lmf;
 
-       if (start)
-               return start;
+       if ((lmf = TlsGetValue (lmf_thread_id)))
+               return lmf;
 
-       code = start = g_malloc (1024);
+       lmf = g_malloc (sizeof (gpointer));
+       *lmf = NULL;
 
-       x86_push_reg (code, X86_ESP);
-       x86_push_membase (code, X86_ESP, 4); /* IP */
-       x86_push_reg (code, X86_EBP);
-       x86_push_reg (code, X86_EDI);
-       x86_push_reg (code, X86_ESI);
-       x86_push_reg (code, X86_EBX);
-       x86_push_reg (code, X86_EDX);
-       x86_push_reg (code, X86_ECX);
-       x86_push_reg (code, X86_EAX);
-       x86_call_code (code, throw_exception);
-       /* we should never reach this breakpoint */
-       x86_breakpoint (code);
+       TlsSetValue (lmf_thread_id, lmf);
 
-       return start;
+       return lmf;
 }
 
+
 #ifdef DEBUG
 void *
 MEMCOPY (void *dest, const void *src, size_t n)
index 40c9c05faff135f201a5e0ec2cc2a2e3d15e37e2..4e00c9c48531a1611fc356131e24b092ab8db536 100644 (file)
@@ -1,3 +1,6 @@
+2001-12-16  Dietmar Maurer  <dietmar@ximian.com>
+
+       * file-io.c: raise exceptions if handle is invalid.
 
 Thu Dec 13 20:27:08 CET 2001 Paolo Molaro <lupus@ximian.com>
 
index 103667e4ffc2cd70f295ed3c22ed6006a0367782..4475d41c94ed163e0ed4212199bd98e1dc0fac0e 100644 (file)
@@ -185,7 +185,11 @@ gint32 ves_icall_System_PAL_OpSys_ReadFile(MonoObject *this, HANDLE handle, Mono
        guint32 bytesread;
        guchar *buf;
        gint32 alen;
-       
+
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        alen=mono_array_length(buffer);
        if(offset+count>alen) {
                return(0);
@@ -205,6 +209,10 @@ gint32 ves_icall_System_PAL_OpSys_WriteFile(MonoObject *this, HANDLE handle,  Mo
        guchar *buf;
        gint32 alen;
        
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        alen=mono_array_length(buffer);
        if(offset+count>alen) {
                return(0);
@@ -227,6 +235,10 @@ gint32 ves_icall_System_PAL_OpSys_SetLengthFile(MonoObject *this, HANDLE handle,
        gboolean ret;
        gint32 lenlo, lenhi, retlo;
        
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        lenlo=length & 0xFFFFFFFF;
        lenhi=length >> 32;
 
@@ -243,16 +255,25 @@ gint32 ves_icall_System_PAL_OpSys_SetLengthFile(MonoObject *this, HANDLE handle,
 HANDLE ves_icall_System_PAL_OpSys_OpenFile(MonoObject *this, MonoString *path, gint32 mode, gint32 access, gint32 share)
 {
        HANDLE handle;
-       
+
        handle=CreateFile(mono_string_chars(path), convert_access(access),
                          convert_share(share), NULL, convert_mode(mode),
                          FILE_ATTRIBUTE_NORMAL, NULL);
        
+       /* fixme: raise mor appropriate exceptions (errno) */
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        return(handle);
 }
 
 void ves_icall_System_PAL_OpSys_CloseFile(MonoObject *this, HANDLE handle)
 {
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        CloseHandle(handle);
 }
 
@@ -262,6 +283,10 @@ gint64 ves_icall_System_PAL_OpSys_SeekFile(MonoObject *this, HANDLE handle,
        gint64 ret;
        gint32 offsetlo, offsethi, retlo;
        
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        offsetlo=offset & 0xFFFFFFFF;
        offsethi=offset >> 32;
 
@@ -288,6 +313,10 @@ gboolean ves_icall_System_PAL_OpSys_GetFileTime(HANDLE handle, gint64 *createtim
        gboolean ret;
        FILETIME cr, ac, wr;
        
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        ret=GetFileTime(handle, &cr, &ac, &wr);
        if(ret==TRUE) {
                /* The FILETIME struct holds two unsigned 32 bit
@@ -310,6 +339,10 @@ gboolean ves_icall_System_PAL_OpSys_SetFileTime(HANDLE handle, gint64 createtime
        gboolean ret;
        FILETIME cr, ac, wr;
        
+       if(handle == INVALID_HANDLE_VALUE) {
+               mono_raise_exception(get_io_exception("Invalid handle"));
+       }
+
        cr.dwLowDateTime= createtime & 0xFFFFFFFF;
        cr.dwHighDateTime= createtime >> 32;