fixed lowering of Conv from I->L (fixed fehler72.c)
[libfirm] / ir / lower / lower_dw.c
index 777e24f..10b1941 100644 (file)
@@ -1,23 +1,33 @@
 /*
- * Project:     libFIRM
- * File name:   ir/lower/lower_dw.c
- * Purpose:     Lower Double word operations, ie Mode L -> I.
- * Author:      Michael Beck
- * Created:     8.10.2004
- * CVS-ID:      $Id$
- * Copyright:   (c) 1998-2006 Universität Karlsruhe
- * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file
+ * @brief   Lower Double word operations, ie 64bit -> 32bit, 32bit -> 16bit etc.
+ * @date    8.10.2004
+ * @author  Michael Beck
+ * @version $Id$
  */
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
-#ifdef HAVE_MALLOC_H
-# include <malloc.h>
-#endif
-#ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-#endif
 #ifdef HAVE_STRING_H
 # include <string.h>
 #endif
@@ -27,6 +37,7 @@
 
 #include <assert.h>
 
+#include "lowering.h"
 #include "irnode_t.h"
 #include "irgraph_t.h"
 #include "irmode_t.h"
@@ -39,7 +50,6 @@
 #include "firmstat.h"
 #include "irgwalk.h"
 #include "ircons.h"
-#include "lower_dw.h"
 #include "irflag.h"
 #include "irtools.h"
 #include "debug.h"
@@ -47,6 +57,7 @@
 #include "pmap.h"
 #include "pdeq.h"
 #include "irdump.h"
+#include "xmalloc.h"
 
 /** A map from mode to a primitive type. */
 static pmap *prim_types;
@@ -413,6 +424,8 @@ static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) {
        dbg_info *dbg;
        int      idx;
        node_entry_t *entry;
+       (void) node;
+       (void) mode;
 
        irn = get_Store_value(node);
        entry = env->entries[get_irn_idx(irn)];
@@ -1207,6 +1220,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) {
        ir_node *sel = get_Cond_selector(node);
        ir_mode *m = get_irn_mode(sel);
        int     idx;
+       (void) mode;
 
        if (m == mode_b) {
                node_entry_t *lentry, *rentry;
@@ -1218,7 +1232,13 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) {
                pn_Cmp   pnc;
                dbg_info *dbg;
 
+               if(!is_Proj(sel))
+                       return;
+
                cmp   = get_Proj_pred(sel);
+               if(!is_Cmp(cmp))
+                       return;
+
                left  = get_Cmp_left(cmp);
                idx   = get_irn_idx(left);
                lentry = env->entries[idx];
@@ -1439,8 +1459,13 @@ static void lower_Conv_to_Ls(ir_node *node, lower_env_t *env) {
                                op = new_rd_Conv(dbg, irg, block, op, dst_mode);
 
                        env->entries[idx]->low_word  = op;
-                       env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op,
-                               new_Const_long(mode_Iu, get_mode_size_bits(dst_mode) - 1), dst_mode);
+
+                       if (mode_is_signed(imode)) {
+                               env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op,
+                                       new_Const_long(mode_Iu, get_mode_size_bits(dst_mode) - 1), dst_mode);
+                       } else {
+                               env->entries[idx]->high_word = new_Const(dst_mode, get_mode_null(dst_mode));
+                       }  /* if */
                }  /* if */
        } else {
                ir_node *irn, *call;
@@ -1489,7 +1514,13 @@ static void lower_Conv_to_Lu(ir_node *node, lower_env_t *env) {
                                op = new_rd_Conv(dbg, irg, block, op, dst_mode);
 
                        env->entries[idx]->low_word  = op;
-                       env->entries[idx]->high_word = new_Const(dst_mode, get_mode_null(dst_mode));
+
+                       if (mode_is_signed(imode)) {
+                               env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op,
+                                       new_Const_long(mode_Iu, get_mode_size_bits(dst_mode) - 1), dst_mode);
+                       } else {
+                               env->entries[idx]->high_word = new_Const(dst_mode, get_mode_null(dst_mode));
+                       }  /* if */
                }  /* if */
        } else {
                ir_node *irn, *call;
@@ -1520,6 +1551,12 @@ static void lower_Conv_from_Ls(ir_node *node, lower_env_t *env) {
 
        assert(idx < env->n_entries);
 
+       if (! env->entries[idx]->low_word) {
+               /* not ready yet, wait */
+               pdeq_putr(env->waitq, node);
+               return;
+       }  /* if */
+
        if (mode_is_int(omode) || mode_is_reference(omode)) {
                op = env->entries[idx]->low_word;
 
@@ -1558,6 +1595,12 @@ static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) {
 
        assert(idx < env->n_entries);
 
+       if (! env->entries[idx]->low_word) {
+               /* not ready yet, wait */
+               pdeq_putr(env->waitq, node);
+               return;
+       }  /* if */
+
        if (mode_is_int(omode) || mode_is_reference(omode)) {
                op = env->entries[idx]->low_word;
 
@@ -1707,6 +1750,7 @@ static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) {
        ir_node   **in;
        int       i, j, n, idx;
        int       need_conv = 0;
+       (void) mode;
 
        /* check if this return must be lowered */
        for (i = 0, n = get_Return_n_ress(node); i < n; ++i) {
@@ -1765,6 +1809,7 @@ static void lower_Start(ir_node *node, ir_mode *mode, lower_env_t *env) {
        long      *new_projs;
        int       i, j, n_params, rem;
        ir_node   *proj, *args;
+       (void) mode;
 
        if (is_lowered_type(tp)) {
                mtp = get_associated_type(tp);
@@ -1852,6 +1897,7 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) {
        int      n_params, n_res, need_lower = 0;
        int      i, j;
        long     *res_numbers = NULL;
+       (void) mode;
 
        if (is_lowered_type(tp)) {
                call_tp = get_associated_type(tp);
@@ -2256,6 +2302,7 @@ static void lower_ops(ir_node *node, void *env)
 static int cmp_op_mode(const void *elt, const void *key, size_t size) {
        const op_mode_entry_t *e1 = elt;
        const op_mode_entry_t *e2 = key;
+       (void) size;
 
        return (e1->op - e2->op) | (e1->imode - e2->imode) | (e1->omode - e2->omode);
 }  /* cmp_op_mode */
@@ -2266,6 +2313,7 @@ static int cmp_op_mode(const void *elt, const void *key, size_t size) {
 static int cmp_conv_tp(const void *elt, const void *key, size_t size) {
        const conv_tp_entry_t *e1 = elt;
        const conv_tp_entry_t *e2 = key;
+       (void) size;
 
        return (e1->imode - e2->imode) | (e1->omode - e2->omode);
 }  /* static int cmp_conv_tp */
@@ -2466,6 +2514,7 @@ ir_entity *def_create_intrinsic_fkt(ir_type *method, const ir_op *op,
        char buf[64];
        ident *id;
        ir_entity *ent;
+       (void) context;
 
        if (imode == omode) {
                snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode));