2008-10-17 Marek Safar <marek.safar@gmail.com>
[mono.git] / mono / mini / mini-alpha.c
index bb58c192f5affbaed6a7a2c325ee11c6e7f1279e..354efe6f8a24160324c88722d36baaf873299a04 100644 (file)
 /*------------------------------------------------------------------*/
 /*                 D e f i n e s                                    */
 /*------------------------------------------------------------------*/
-
-#define NOT_IMPLEMENTED(x) \
-   g_error ("FIXME: %s is not yet implemented.", x);
-
 #define ALPHA_DEBUG(x) \
    if (mini_alpha_verbose_level) \
        g_debug ("ALPHA_DEBUG: %s is called.", x);
@@ -73,6 +69,7 @@
 #include "mini-alpha.h"
 #include "inssel.h"
 #include "cpu-alpha.h"
+#include "jit-icalls.h"
 
 /*========================= End of Includes ========================*/
 
@@ -94,9 +91,11 @@ pthread_key_t lmf_addr_key;
 
 gboolean lmf_addr_key_inited = FALSE;
 
+MonoBreakpointInfo
+mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
+
 /*====================== End of Global Variables ===================*/
 
-static void mono_arch_break(void);
 gpointer mono_arch_get_lmf_addr (void);
 
 typedef enum {
@@ -134,7 +133,7 @@ typedef struct {
    ArgInfo args [1];
 } CallInfo;
 
-static CallInfo* get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke);
+static CallInfo* get_call_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke);
 static unsigned int *emit_call(MonoCompile *cfg, unsigned int *code,
                               guint32 patch_type, gconstpointer data);
 
@@ -195,7 +194,7 @@ add_float (guint32 *gr, guint32 *stack_size, ArgInfo *ainfo,
 }
 
 static void
-add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
+add_valuetype (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
                gboolean is_return,
                guint32 *gr, guint32 *fr, guint32 *stack_size)
 {
@@ -211,7 +210,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
   else if (sig->pinvoke)
     size = mono_type_native_stack_size (&klass->byval_arg, NULL);
   else
-    size = mono_type_stack_size (&klass->byval_arg, NULL);
+    size = mini_type_stack_size (gsctx, &klass->byval_arg, NULL);
 
   if (!sig->pinvoke || (size == 0) || is_return) {
     /* Allways pass in memory */
@@ -394,7 +393,7 @@ mono_arch_create_vars (MonoCompile *cfg)
    
   sig = mono_method_signature (cfg->method);
    
-  cinfo = get_call_info (sig, FALSE);
+  cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
    
   if (cinfo->ret.storage == ArgValuetypeInReg)
     cfg->ret_var_is_local = TRUE;
@@ -439,21 +438,28 @@ mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
 
 /*========================= End of Function ========================*/
 
-static void
-  peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
+// This peephole function is called before "local_regalloc" method
+// TSV_TODO - Check what we need to move here
+void
+mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
 {
-  MonoInst *ins, *last_ins = NULL;
+  CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE_1 pass\n");
+}
+
+// This peephole function is called after "local_regalloc" method
+void
+mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+  MonoInst *ins, *n, *last_ins = NULL;
   ins = bb->code;
    
-  CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE pass\n");
+  CFG_DEBUG(3) g_print ("ALPHA: PEEPHOLE_2 pass\n");
 
-  while (ins) 
-    {  
+  MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
       switch (ins->opcode) 
        {        
        case OP_MOVE:
        case OP_FMOVE:
-       case OP_SETREG:
          /*
           * Removes:
           *
@@ -462,10 +468,7 @@ static void
          if (ins->dreg == ins->sreg1 &&
              ins->dreg != alpha_at) 
            {
-             if (last_ins)
-               last_ins->next = ins->next;
-             
-             ins = ins->next;
+             MONO_DELETE_INS (bb, ins);
              continue;
            }
          
@@ -480,9 +483,7 @@ static void
              last_ins->dreg != alpha_at &&
              ins->dreg == last_ins->sreg1) 
            {
-             last_ins->next = ins->next;
-             
-             ins = ins->next;
+             MONO_DELETE_INS (bb, ins);
              continue;
            }
          
@@ -498,8 +499,7 @@ static void
                }
              else 
                {
-                 last_ins->next = ins->next;
-                 ins = ins->next;
+                 MONO_DELETE_INS (bb, ins);
                  continue;
                }
            }
@@ -525,9 +525,7 @@ static void
             {
               if (ins->dreg == last_ins->sreg1)
                 {
-                  last_ins->next = ins->next;
-
-                  ins = ins->next;
+                 MONO_DELETE_INS (bb, ins);
                   continue;
                 }
               else
@@ -558,9 +556,7 @@ static void
            {
              if (ins->dreg == last_ins->sreg1)
                {
-                 last_ins->next = ins->next;
-
-                 ins = ins->next;
+                 MONO_DELETE_INS (bb, ins);
                  continue;
                }
              else
@@ -589,9 +585,7 @@ static void
            {
              if (ins->dreg == last_ins->dreg)
                {
-                 last_ins->next = ins->next;
-                 
-                 ins = ins->next;
+                 MONO_DELETE_INS (bb, ins);
                  continue;
                }
              else
@@ -613,8 +607,6 @@ static void
   bb->last_ins = last_ins;
 }
 
-
-
 // Convert to opposite branch opcode
 static guint16 cvt_branch_opcode(guint16 opcode)
 {
@@ -946,10 +938,10 @@ static void cvt_cmp_branch(MonoInst *curr, MonoInst *next)
  * Converts complex opcodes into simpler ones so that each IR instruction
  * corresponds to one machine instruction.
  */
-static void
-  mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
+void
+mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
 {   
-   MonoInst *ins, *temp, *last_ins = NULL;
+   MonoInst *ins, *n, *temp, *last_ins = NULL;
    MonoInst *next;
    
    ins = bb->code;
@@ -963,8 +955,7 @@ static void
     * cdq.
     */
    
-   while (ins) 
-     {
+   MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
        switch (ins->opcode) 
         {       
         case OP_DIV_IMM:
@@ -1022,7 +1013,7 @@ static void
               ins->sreg2 = temp->dreg;
                                  
               // We should try to reevaluate new IR opcode
-              continue;
+              //continue;
             }
           
           next = ins->next;
@@ -1041,7 +1032,7 @@ static void
                ins->sreg2 = temp->dreg;
 
                // We should try to reevaluate new IR opcode
-               continue;
+               //continue;
              }
 
            next = ins->next;
@@ -1213,33 +1204,6 @@ static void
    bb->max_vreg = cfg->rs->next_vreg;
 }
 
-/*------------------------------------------------------------------*/
-/*                                                                  */
-/* Name         - mono_arch_local_regalloc.                         */
-/*                                                                  */
-/* Function     - We first scan the list of instructions and we     */
-/*                save the liveness information of each register    */
-/*                (when the register is first used, when its value  */
-/*                is set etc.). We also reverse the list of instr-  */
-/*                uctions (in the InstList list) because assigning  */
-/*                registers backwards allows for more tricks to be  */
-/*                used.                                             */
-/*                                                                  */
-/*------------------------------------------------------------------*/
-
-void
-mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
-{
-  CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_local_regalloc");
-   
-  if (!bb->code)
-    return;
-   
-  mono_arch_lowering_pass (cfg, bb);
-   
-  mono_local_regalloc(cfg, bb);
-}
-
 /*========================= End of Function ========================*/
 
 #define AXP_GENERAL_REGS     6
@@ -1341,7 +1305,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, unsigned int *code)
 
   sig = mono_method_signature (method);
 
-  cinfo = get_call_info (sig, FALSE);
+  cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
 
   if (sig->ret->type != MONO_TYPE_VOID) {
     if ((cinfo->ret.storage == ArgInIReg) &&
@@ -1355,7 +1319,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, unsigned int *code)
   for (i = 0; i < sig->param_count + sig->hasthis; ++i)
     {
       ArgInfo *ainfo = &cinfo->args [i];
-      MonoInst *inst = cfg->varinfo [i];
+      MonoInst *inst = cfg->args [i];
 
       switch(ainfo->storage)
        {
@@ -1500,7 +1464,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
    
    offset = cfg->arch.args_save_area_offset;
 
-   cinfo = get_call_info (sig, FALSE);
+   cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
 
    if (sig->ret->type != MONO_TYPE_VOID)
      {
@@ -1517,7 +1481,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
    for (i = 0; i < sig->param_count + sig->hasthis; ++i)
      {
        ArgInfo *ainfo = &cinfo->args [i];
-       MonoInst *inst = cfg->varinfo [i];
+       MonoInst *inst = cfg->args [i];
        int j;
 
        switch(ainfo->storage)
@@ -1742,7 +1706,7 @@ mono_arch_get_argument_info (MonoMethodSignature *csig,
                              MonoJitArgumentInfo *arg_info)
 {
   int k;
-  CallInfo *cinfo = get_call_info (csig, FALSE);
+  CallInfo *cinfo = get_call_info (NULL, csig, FALSE);
   guint32 args_size = cinfo->stack_usage;
 
   ALPHA_DEBUG("mono_arch_get_argument_info");
@@ -2239,9 +2203,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
    
    CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_output_basic_block");
    
-   if (cfg->opt & MONO_OPT_PEEPHOLE)
-     peephole_pass (cfg, bb);
-    
    CFG_DEBUG(2) g_print ("Basic block %d(%p) starting at offset 0x%x\n",
                         bb->block_num, bb, bb->native_offset);
    
@@ -2251,9 +2212,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
    mono_debug_open_block (cfg, bb, offset);
    
-   ins = bb->code;
-   while (ins)
-     {
+   MONO_BB_FOR_EACH_INS (bb, ins) {
        offset = ((char *)code) - ((char *)cfg->native_code);
          
        max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
@@ -2273,6 +2232,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
          
        switch (ins->opcode)
         {
+        case OP_RELAXED_NOP:
+               break;
         case OP_LSHR:
           // Shift 64 bit value right
           CFG_DEBUG(4) g_print("ALPHA_CHECK: [long_shr] dreg=%d, sreg1=%d, sreg2=%d\n",
@@ -3663,7 +3624,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
           ins->inst_c0 = (char *)code - (char *)cfg->native_code;
           break;
           
-        case CEE_BR:
+        case OP_BR:
           CFG_DEBUG(4) g_print("ALPHA_CHECK: [br] target: %p, next: %p, curr: %p, last: %p [",
                  ins->inst_target_bb, bb->next_bb, ins, bb->last_ins);
           
@@ -3727,7 +3688,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
         case OP_LCALL:
         case OP_VCALL:
         case OP_VOIDCALL:
-        case CEE_CALL:
+        case OP_CALL:
           CFG_DEBUG(4) g_print("ALPHA_CHECK: [fcall/lcall/vcall/voidcall/call] Target: [");
           call = (MonoCallInst*)ins;
           
@@ -3829,7 +3790,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
           }
           break;
 
-        case CEE_ENDFINALLY:
+        case OP_ENDFINALLY:
           {
              // Keep in sync with start_handler
              CFG_DEBUG(4) g_print("ALPHA_CHECK: [endfinally] basereg=%d, offset=%0lx\n",
@@ -3873,14 +3834,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
             alpha_bsr(code, alpha_ra, 0);
           }
           break;
-          
-        case CEE_RET:
-          CFG_DEBUG(4) g_print("ALPHA_CHECK: [ret]\n");
-          
-          alpha_ret(code, alpha_ra, 1);
-          break;
 
-        case CEE_THROW:
+        case OP_THROW:
           CFG_DEBUG(4) g_print("ALPHA_CHECK: [throw] sreg1=%0x\n",
                                ins->sreg1);
           alpha_mov1(code, ins->sreg1, alpha_a0);
@@ -3896,7 +3851,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                              (gpointer)"mono_arch_rethrow_exception");
            break;
 
-        case CEE_JMP:
+        case OP_JMP:
           {
             /*
              * Note: this 'frame destruction' logic is useful for tail calls,
@@ -3943,7 +3898,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
           alpha_mb(code);
           break;
          
-        case CEE_CKFINITE:
+        case OP_CKFINITE:
           // Float register contains a value which we need to check
           {
                double  ni = -1.0 / 0.0;
@@ -4009,9 +3964,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
        
        last_ins = ins;
        last_offset = offset;
-       
-       ins = ins->next;          
-     }
+   }
    
    cfg->code_len = ((char *)code) - ((char *)cfg->native_code);
 }
@@ -4193,7 +4146,7 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain,
  
            if (*ip2 != (t_addr & 0xFFFFFFFF) ||
                *(ip2+1) != ((t_addr>>32) & 0xFFFFFFFF))
-                   NOT_IMPLEMENTED("mono_arch_patch_code: MONO_PATCH_INFO_CLASS_INIT");
+                       NOT_IMPLEMENTED;
            //  amd64_call_code (ip2, 0);
            break;
          }
@@ -4312,7 +4265,7 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst,
        int this_reg, int this_type, int vt_reg)
 {
   MonoCallInst *call = (MonoCallInst*)inst;
-  CallInfo * cinfo = get_call_info (inst->signature, FALSE);
+  CallInfo * cinfo = get_call_info (cfg->generic_sharing_context, inst->signature, FALSE);
 
   CFG_DEBUG(2) ALPHA_DEBUG("mono_arch_emit_this_vret_args");
 
@@ -4438,6 +4391,21 @@ mono_arch_cpu_init (void)
   //printf("amask: %x, implver: %x", amask, implver);
 }
 
+/*
+ * Initialize architecture specific code.
+ */
+void
+mono_arch_init (void)
+{
+}
+
+/*
+ * Cleanup architecture specific code.
+ */
+void
+mono_arch_cleanup (void)
+{
+}
 
 /*
  * get_call_info:
@@ -4450,7 +4418,7 @@ mono_arch_cpu_init (void)
  * For x86 win32, see ???.
  */
 static CallInfo*
-get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke)
+get_call_info (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gboolean is_pinvoke)
 {
    guint32 i, gr, fr, *pgr, *pfr;
    MonoType *ret_type;
@@ -4520,7 +4488,7 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke)
        {
         guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
                        
-        add_valuetype (sig, &cinfo->ret, sig->ret, TRUE,
+        add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE,
                        &tmp_gr, &tmp_fr, &tmp_stacksize);
         
         if (cinfo->ret.storage == ArgOnStack)
@@ -4621,7 +4589,7 @@ get_call_info (MonoMethodSignature *sig, gboolean is_pinvoke)
        case MONO_TYPE_VALUETYPE:
         /* FIXME: */
         /* We allways pass valuetypes on the stack */
-        add_valuetype (sig, ainfo, sig->params [i],
+        add_valuetype (gsctx, sig, ainfo, sig->params [i],
                        FALSE, pgr, pfr, &stack_size);
         break;
        case MONO_TYPE_TYPEDBYREF:
@@ -4779,7 +4747,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb,
    n = sig->param_count + sig->hasthis;
 
    // Collect info about method we age going to call
-   cinfo = get_call_info (sig, sig->pinvoke);
+   cinfo = get_call_info (cfg->generic_sharing_context, sig, sig->pinvoke);
 
    CFG_DEBUG(3) g_print("ALPHA: Will call %s method with %d(%d) params. RetType: %s(0x%X)\n",
                        sig->pinvoke ? "PInvoke" : "Managed",
@@ -4872,7 +4840,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb,
                 size = mono_type_native_stack_size (&in->klass->byval_arg,
                                                     &align);
               else
-                size = mono_type_stack_size (&in->klass->byval_arg, &align);
+                size = mini_type_stack_size (cfg->generic_sharing_context, &in->klass->byval_arg, &align);
 
             if (ainfo->storage == ArgAggregate)
               {
@@ -5075,19 +5043,6 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb,
 
 /*========================= End of Function ========================*/
 
-/*------------------------------------------------------------------*/
-/*                                                                  */
-/* Name         - mono_arch_break                                   */
-/*                                                                  */
-/* Function     - Process a "break" operation for debugging.        */
-/*                                                                  */
-/*------------------------------------------------------------------*/
-
-static void
-mono_arch_break(void) {
-}
-
-
 /*------------------------------------------------------------------*/
 /*                                                                  */
 /* Name         - mono_arch_register_lowlevel_calls                 */
@@ -5101,7 +5056,6 @@ mono_arch_register_lowlevel_calls (void)
 {
    ALPHA_DEBUG("mono_arch_register_lowlevel_calls");
    
-   mono_register_jit_icall (mono_arch_break, "mono_arch_break", NULL, TRUE);
    mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr",
                                                        NULL, TRUE);
 }
@@ -5158,11 +5112,11 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
 
    sig = mono_method_signature (cfg->method);
 
-   cinfo = get_call_info (sig, FALSE);
+   cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
 
    for (i = 0; i < sig->param_count + sig->hasthis; ++i)
      {
-       MonoInst *ins = cfg->varinfo [i];
+       MonoInst *ins = cfg->args [i];
 
        ArgInfo *ainfo = &cinfo->args [i];
 
@@ -5275,11 +5229,6 @@ mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod,
    
    CFG_DEBUG(3) g_print("mono_arch_get_inst_for_method: %s\n", cmethod->name);
    
-   if (cmethod->klass == mono_defaults.thread_class &&
-       strcmp (cmethod->name, "MemoryBarrier") == 0) {
-     MONO_INST_NEW (cfg, ins, OP_MEMORY_BARRIER);
-   }
-   
    return ins;
 }
 
@@ -5306,7 +5255,7 @@ mono_arch_create_class_init_trampoline (MonoVTable *vtable)
 {
    ALPHA_DEBUG("mono_arch_create_class_init_trampoline");
    
-   NOT_IMPLEMENTED("mono_arch_create_class_init_trampoline: check MONO_ARCH_HAVE_CREATE_SPECIFIC_TRAMPOLINE define");
+   NOT_IMPLEMENTED;
    
    return 0;
 }
@@ -5340,7 +5289,7 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
       /* Allocate a new area on the stack and save arguments there */
       sig = mono_method_signature (cfg->method);
 
-      cinfo = get_call_info (sig, FALSE);
+      cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
 
       n = sig->param_count + sig->hasthis;
 
@@ -5352,7 +5301,7 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
       
       for (i = 0; i < n; ++i)
        {
-         inst = cfg->varinfo [i];
+         inst = cfg->args [i];
 
          if (inst->opcode == OP_REGVAR)
            {
@@ -5589,7 +5538,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
    
    sig = mono_method_signature (cfg->method);
    
-   cinfo = get_call_info (sig, FALSE);
+   cinfo = get_call_info (cfg->generic_sharing_context, sig, FALSE);
    
    /* if (cfg->arch.omit_fp) {
       cfg->flags |= MONO_CFG_HAS_SPILLUP;
@@ -5770,7 +5719,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
    // Reserve space for method params
    for (i = 0; i < sig->param_count + sig->hasthis; ++i)
      {
-       inst = cfg->varinfo [i];
+       inst = cfg->args [i];
 
        if (inst->opcode != OP_REGVAR)
         {
@@ -5832,7 +5781,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
               break;
 
             default:
-              NOT_IMPLEMENTED("");
+              NOT_IMPLEMENTED;
             }
 
           if (!inreg && (ainfo->storage != ArgOnStack))
@@ -5964,9 +5913,45 @@ mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs)
   return 0;
 }
 
+gpointer
+mono_arch_get_this_arg_from_call (MonoGenericSharingContext *gsctx, MonoMethodSignature *sig, gssize *regs, guint8 *code)
+{
+  unsigned int *pc = (unsigned int *)code;
+
+  ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_this_arg_from_call] code: %p regs: %p",
+          pc, regs);
+
+        if (MONO_TYPE_ISSTRUCT (sig->ret))
+                return (gpointer)regs [alpha_a1];
+        else
+                return (gpointer)regs [alpha_a0];
+}
+
+gpointer
+mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
+{
+       unsigned int *code, *start;
+        MonoDomain *domain = mono_domain_get ();
+        int i;
+
+       ALPHA_PRINT g_debug("ALPHA_CHECK: [mono_arch_get_delegate_invoke_impl]");
+
+        /* FIXME: Support more cases */
+        if (MONO_TYPE_ISSTRUCT (sig->ret))
+                return NULL;
+
+       return NULL;
+}
 
 guint32
 mono_arch_get_patch_offset (guint8 *code)
 {
   return 3;
 }
+
+gpointer
+mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
+{
+       /* FIXME: implement */
+       g_assert_not_reached ();
+}