fix shift operations
authorMatthias Braun <matze@braunis.de>
Fri, 16 Nov 2007 15:38:21 +0000 (15:38 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 16 Nov 2007 15:38:21 +0000 (15:38 +0000)
[r18412]

ast2firm.c
parser.c
type.c
type.h

index 4a68ed8..a7aacd1 100644 (file)
@@ -1042,6 +1042,42 @@ static ir_node *create_sub(const binary_expression_t *expression)
        return res;
 }
 
+static ir_node *create_shift(const binary_expression_t *expression)
+{
+       dbg_info *dbgi  = get_dbg_info(&expression->expression.source_position);
+       ir_node  *left  = expression_to_firm(expression->left);
+       ir_node  *right = expression_to_firm(expression->right);
+       type_t   *type  = expression->expression.datatype;
+       ir_mode  *mode  = get_ir_mode(type);
+
+       /* firm always wants the shift count to be unsigned */
+       right = create_conv(dbgi, right, mode_Iu);
+
+       ir_node *res;
+
+       switch(expression->type) {
+       case BINEXPR_SHIFTLEFT:
+               res = new_d_Shl(dbgi, left, right, mode);
+               break;
+       case BINEXPR_SHIFTRIGHT: {
+                expression_t *expr_left = expression->left;
+                type_t       *type_left = skip_typeref(expr_left->datatype);
+
+                if(is_type_signed(type_left)) {
+                       res = new_d_Shrs(dbgi, left, right, mode);
+                } else {
+                        res = new_d_Shr(dbgi, left, right, mode);
+                }
+                break;
+       }
+       default:
+               panic("create shift op called for non-shift op");
+       }
+
+       return res;
+}
+
+
 static ir_node *create_divmod(const binary_expression_t *expression)
 {
        dbg_info *dbgi  = get_dbg_info(&expression->expression.source_position);
@@ -1109,9 +1145,8 @@ static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
        case BINEXPR_BITWISE_XOR:
                return create_arithmetic_binop(expression, new_d_Eor);
        case BINEXPR_SHIFTLEFT:
-               return create_arithmetic_binop(expression, new_d_Shl);
        case BINEXPR_SHIFTRIGHT:
-               return create_arithmetic_binop(expression, new_d_Shr);
+               return create_shift(expression);
        case BINEXPR_DIV:
        case BINEXPR_MOD:
                return create_divmod(expression);
index 5c4ecd7..c33c112 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -594,14 +594,27 @@ static expression_t *create_implicit_cast(expression_t *expression,
                return create_cast_expression(expression, dest_type);
        }
        if(dest_type->type == TYPE_POINTER) {
+               pointer_type_t *pointer_type
+                       = (pointer_type_t*) dest_type;
                if(source_type->type == TYPE_POINTER) {
                        if(!pointers_compatible(source_type, dest_type)) {
                                type_error_incompatible("can't implicitely cast types",
                                                expression->source_position,
                                                source_type, dest_type);
+                           return expression;
                        } else {
                                return create_cast_expression(expression, dest_type);
                        }
+               } else if(source_type->type == TYPE_ARRAY) {
+                       array_type_t *array_type = (array_type_t*) source_type;
+                       if(!types_compatible(array_type->element_type,
+                                            pointer_type->points_to)) {
+                               type_error_incompatible("can't implicitely cast types",
+                                               expression->source_position,
+                                               source_type, dest_type);
+                           return expression;
+                       }
+                       return create_cast_expression(expression, dest_type);
                }
        }
 
@@ -2811,6 +2824,34 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
        expression->expression.datatype = arithmetic_type;
 }
 
+static void semantic_shift_op(binary_expression_t *expression)
+{
+       expression_t *left       = expression->left;
+       expression_t *right      = expression->right;
+       type_t       *orig_type_left  = left->datatype;
+       type_t       *orig_type_right = right->datatype;
+
+       if(orig_type_left == NULL || orig_type_right == NULL)
+               return;
+
+       type_t *type_left  = skip_typeref(orig_type_left);
+       type_t *type_right = skip_typeref(orig_type_right);
+
+       if(!is_type_integer(type_left) || !is_type_integer(type_right)) {
+               /* TODO: improve error message */
+               parser_print_error_prefix();
+               fprintf(stderr, "operation needs integer types\n");
+               return;
+       }
+
+       type_left  = promote_integer(type_left);
+       type_right = promote_integer(type_right);
+
+       expression->left  = create_implicit_cast(left, type_left);
+       expression->right = create_implicit_cast(right, type_right);
+       expression->expression.datatype = type_left;
+}
+
 static void semantic_add(binary_expression_t *expression)
 {
        expression_t *left            = expression->left;
@@ -3022,9 +3063,9 @@ CREATE_BINEXPR_PARSER(T_ANDAND, BINEXPR_LOGICAL_AND,  semantic_logical_op, 1)
 CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR, semantic_logical_op, 1)
 /* TODO shift has a bit special semantic */
 CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT,
-                      semantic_binexpr_arithmetic, 1)
+                      semantic_shift_op, 1)
 CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT,
-                      semantic_binexpr_arithmetic, 1)
+                      semantic_shift_op, 1)
 CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN,
                       semantic_arithmetic_assign, 0)
 CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN,
diff --git a/type.c b/type.c
index 76e9241..bcc1b25 100644 (file)
--- a/type.c
+++ b/type.c
@@ -461,11 +461,51 @@ bool is_type_scalar(const type_t *type)
        return is_type_arithmetic(type);
 }
 
+bool is_type_incomplete(const type_t *type)
+{
+       switch(type->type) {
+       case TYPE_COMPOUND_STRUCT:
+       case TYPE_COMPOUND_UNION: {
+               const compound_type_t *compound_type
+                       = (const compound_type_t*) type;
+               declaration_t *declaration = compound_type->declaration;
+               return !declaration->init.is_defined;
+       }
+       case TYPE_FUNCTION:
+               return true;
+
+       case TYPE_ARRAY:
+       case TYPE_ATOMIC:
+       case TYPE_POINTER:
+       case TYPE_ENUM:
+               return false;
+
+       case TYPE_TYPEDEF:
+       case TYPE_TYPEOF:
+       case TYPE_BUILTIN:
+               panic("is_type_incomplete called without typerefs skipped");
+       case TYPE_INVALID:
+               break;
+       }
+
+       panic("invalid type found");
+}
+
+bool types_compatible(const type_t *type1, const type_t *type2)
+{
+       (void) type1;
+       (void) type2;
+       return true;
+}
+
 bool pointers_compatible(const type_t *type1, const type_t *type2)
 {
        assert(type1->type == TYPE_POINTER);
        assert(type2->type == TYPE_POINTER);
-       return true;
+       pointer_type_t *pointer_type1 = (pointer_type_t*) type1;
+       pointer_type_t *pointer_type2 = (pointer_type_t*) type2;
+       return types_compatible(pointer_type1->points_to,
+                               pointer_type2->points_to);
 }
 
 type_t *skip_typeref(type_t *type)
diff --git a/type.h b/type.h
index 2bf5940..0e6521e 100644 (file)
--- a/type.h
+++ b/type.h
@@ -72,6 +72,10 @@ bool is_type_arithmetic(const type_t *type);
  */
 bool is_type_scalar(const type_t *type);
 
+bool is_type_incomplete(const type_t *type);
+
+bool types_compatible(const type_t *type1, const type_t *type2);
+
 bool pointers_compatible(const type_t *type1, const type_t *type2);
 
 type_t *skip_typeref(type_t *type);