support for pointer add/sub, no need for type_environment in ast2firm
authorMatthias Braun <matze@braunis.de>
Wed, 14 Nov 2007 09:47:25 +0000 (09:47 +0000)
committerMatthias Braun <matze@braunis.de>
Wed, 14 Nov 2007 09:47:25 +0000 (09:47 +0000)
[r18388]

Makefile
ast2firm.c
config.h
parser.c
type.c
type.h

index 0c3f793..aeda011 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ CFLAGS += -DHAVE_CONFIG_H
 CFLAGS += -I .
 CFLAGS += -O0 -g3
 CFLAGS += $(FIRM_CFLAGS)
-#CFLAGS += -O3 -march=pentium3 -fomit-frame-pointer -DNDEBUG
+#CFLAGS += -O3 -march=pentium4 -fomit-frame-pointer -DNDEBUG
 
 LFLAGS = $(FIRM_LIBS)
 
index 8fc001f..0f65cea 100644 (file)
@@ -41,13 +41,6 @@ typedef enum declaration_type_t {
        DECLARATION_TYPE_COMPOUND_MEMBER
 } declaration_type_t;
 
-typedef struct type2firm_env_t type2firm_env_t;
-struct type2firm_env_t {
-       int can_cache;       /* nonzero if type can safely be cached because
-                               no typevariables are in the hierarchy */
-};
-
-static ir_type *_get_ir_type(type2firm_env_t *env, type_t *type);
 static ir_type *get_ir_type(type_t *type);
 
 ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos)
@@ -260,10 +253,8 @@ static unsigned count_parameters(const function_type_t *function_type)
 
 
 
-static ir_type *create_atomic_type(type2firm_env_t *env,
-                                   const atomic_type_t *type)
+static ir_type *create_atomic_type(const atomic_type_t *type)
 {
-       (void) env;
        ir_mode *mode   = get_atomic_mode(type);
        ident   *id     = get_mode_ident(mode);
        ir_type *irtype = new_type_primitive(id, mode);
@@ -271,8 +262,7 @@ static ir_type *create_atomic_type(type2firm_env_t *env,
        return irtype;
 }
 
-static ir_type *create_method_type(type2firm_env_t *env,
-                                   const function_type_t *function_type)
+static ir_type *create_method_type(const function_type_t *function_type)
 {
        type_t  *result_type  = function_type->result_type;
 
@@ -282,26 +272,26 @@ static ir_type *create_method_type(type2firm_env_t *env,
        ir_type *irtype       = new_type_method(id, n_parameters, n_results);
 
        if(result_type != type_void) {
-               ir_type *restype = _get_ir_type(env, result_type);
+               ir_type *restype = get_ir_type(result_type);
                set_method_res_type(irtype, 0, restype);
        }
 
        function_parameter_t *parameter = function_type->parameters;
        int                   n         = 0;
        for( ; parameter != NULL; parameter = parameter->next) {
-               ir_type *p_irtype = _get_ir_type(env, parameter->type);
+               ir_type *p_irtype = get_ir_type(parameter->type);
                set_method_param_type(irtype, n, p_irtype);
                ++n;
        }
 
-       if(function_type->variadic) {
+       if(function_type->variadic || function_type->unspecified_parameters) {
                set_method_variadicity(irtype, variadicity_variadic);
        }
 
        return irtype;
 }
 
-static ir_type *create_pointer_type(type2firm_env_t *env, pointer_type_t *type)
+static ir_type *create_pointer_type(pointer_type_t *type)
 {
        type_t  *points_to = type->points_to;
        ir_type *ir_points_to;
@@ -313,16 +303,16 @@ static ir_type *create_pointer_type(type2firm_env_t *env, pointer_type_t *type)
                                            ir_type_void, mode_P_data);
        type->type.firm_type  = ir_type;
 
-       ir_points_to = _get_ir_type(env, points_to);
+       ir_points_to = get_ir_type(points_to);
        set_pointer_points_to_type(ir_type, ir_points_to);
 
        return ir_type;
 }
 
-static ir_type *create_array_type(type2firm_env_t *env, array_type_t *type)
+static ir_type *create_array_type(array_type_t *type)
 {
        type_t  *element_type    = type->element_type;
-       ir_type *ir_element_type = _get_ir_type(env, element_type);
+       ir_type *ir_element_type = get_ir_type(element_type);
 
        /* TODO... */
        int n_elements = 0;
@@ -345,7 +335,7 @@ static ir_type *create_array_type(type2firm_env_t *env, array_type_t *type)
 
 #define INVALID_TYPE ((ir_type_ptr)-1)
 
-static ir_type *create_struct_type(type2firm_env_t *env, compound_type_t *type)
+static ir_type *create_struct_type(compound_type_t *type)
 {
        symbol_t *symbol = type->declaration->symbol;
        ident    *id;
@@ -366,7 +356,7 @@ static ir_type *create_struct_type(type2firm_env_t *env, compound_type_t *type)
                        continue;
 
                ident       *ident         = new_id_from_str(entry->symbol->string);
-               ir_type_ptr  entry_ir_type = _get_ir_type(env, entry->type);
+               ir_type_ptr  entry_ir_type = get_ir_type(entry->type);
 
                int entry_size      = get_type_size_bytes(entry_ir_type);
                int entry_alignment = get_type_alignment_bytes(entry_ir_type);
@@ -397,7 +387,7 @@ static ir_type *create_struct_type(type2firm_env_t *env, compound_type_t *type)
        return ir_type;
 }
 
-static ir_type *create_union_type(type2firm_env_t *env, compound_type_t *type)
+static ir_type *create_union_type(compound_type_t *type)
 {
        declaration_t *declaration = type->declaration;
        symbol_t      *symbol      = declaration->symbol;
@@ -419,7 +409,7 @@ static ir_type *create_union_type(type2firm_env_t *env, compound_type_t *type)
                        continue;
 
                ident       *ident         = new_id_from_str(entry->symbol->string);
-               ir_type_ptr  entry_ir_type = _get_ir_type(env, entry->type);
+               ir_type_ptr  entry_ir_type = get_ir_type(entry->type);
 
                int entry_size      = get_type_size_bytes(entry_ir_type);
                int entry_alignment = get_type_alignment_bytes(entry_ir_type);
@@ -448,7 +438,7 @@ static ir_type *create_union_type(type2firm_env_t *env, compound_type_t *type)
        return ir_type;
 }
 
-static ir_type *_get_ir_type(type2firm_env_t *env, type_t *type)
+static ir_type *get_ir_type(type_t *type)
 {
        assert(type != NULL);
 
@@ -462,22 +452,22 @@ static ir_type *_get_ir_type(type2firm_env_t *env, type_t *type)
        ir_type *firm_type = NULL;
        switch(type->type) {
        case TYPE_ATOMIC:
-               firm_type = create_atomic_type(env, (atomic_type_t*) type);
+               firm_type = create_atomic_type((atomic_type_t*) type);
                break;
        case TYPE_FUNCTION:
-               firm_type = create_method_type(env, (function_type_t*) type);
+               firm_type = create_method_type((function_type_t*) type);
                break;
        case TYPE_POINTER:
-               firm_type = create_pointer_type(env, (pointer_type_t*) type);
+               firm_type = create_pointer_type((pointer_type_t*) type);
                break;
        case TYPE_ARRAY:
-               firm_type = create_array_type(env, (array_type_t*) type);
+               firm_type = create_array_type((array_type_t*) type);
                break;
        case TYPE_COMPOUND_STRUCT:
-               firm_type = create_struct_type(env, (compound_type_t*) type);
+               firm_type = create_struct_type((compound_type_t*) type);
                break;
        case TYPE_COMPOUND_UNION:
-               firm_type = create_union_type(env, (compound_type_t*) type);
+               firm_type = create_union_type((compound_type_t*) type);
                break;
        case TYPE_ENUM:
                firm_type = ir_type_int;
@@ -491,19 +481,8 @@ static ir_type *_get_ir_type(type2firm_env_t *env, type_t *type)
        if(firm_type == NULL)
                panic("unknown type found");
 
-       if(env->can_cache) {
-               type->firm_type = firm_type;
-       }
+       type->firm_type = firm_type;
        return firm_type;
-
-}
-
-static ir_type *get_ir_type(type_t *type)
-{
-       type2firm_env_t env;
-       env.can_cache = 1;
-
-       return _get_ir_type(&env, type);
 }
 
 static inline ir_mode *get_ir_mode(type_t *type)
@@ -655,7 +634,7 @@ static ir_node *call_expression_to_firm(const call_expression_t *call)
 
        ir_type *ir_method_type  = get_ir_type((type_t*) function_type);
        ir_type *new_method_type = NULL;
-       if(function_type->variadic) {
+       if(function_type->variadic || function_type->unspecified_parameters) {
                /* we need to construct a new method type matching the call
                 * arguments... */
                int n_res       = get_method_n_ress(ir_method_type);
@@ -906,14 +885,98 @@ static ir_node *create_arithmetic_binop(const binary_expression_t *expression,
        ir_node  *right = expression_to_firm(expression->right);
        type_t   *type  = expression->expression.datatype;
        ir_mode  *mode  = get_ir_mode(type);
-       /* TODO FIXME Hack for now */
-       right = create_conv(dbgi, right, get_irn_mode(left));
-
        ir_node  *res   = func(dbgi, left, right, mode);
 
        return res;
 }
 
+static ir_node *create_add(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);
+
+       expression_t *expr_left  = expression->left;
+       expression_t *expr_right = expression->right;
+       type_t       *type_left  = skip_typeref(expr_left->datatype);
+       type_t       *type_right = skip_typeref(expr_right->datatype);
+
+       if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+               return new_d_Add(dbgi, left, right, mode);
+       }
+
+       ir_node        *pointer;
+       ir_node        *integer;
+       pointer_type_t *pointer_type;
+       if(type_left->type == TYPE_POINTER) {
+               pointer      = left;
+               integer      = right;
+               pointer_type = (pointer_type_t*) type_left;
+       } else {
+               assert(type_right->type == TYPE_POINTER);
+               pointer      = right;
+               integer      = left;
+               pointer_type = (pointer_type_t*) type_right;
+       }
+
+       type_t   *points_to = pointer_type->points_to;
+       unsigned  elem_size = get_type_size(points_to);
+
+       assert(elem_size >= 1);
+       if(elem_size > 1) {
+               ir_node *cnst = new_Const_long(mode_Iu, elem_size);
+               ir_node *mul  = new_d_Mul(dbgi, integer, cnst, mode_Iu);
+               integer = mul;
+       }
+
+       ir_node *res = new_d_Add(dbgi, pointer, integer, mode);
+
+       return res;
+}
+
+static ir_node *create_sub(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);
+
+       expression_t *expr_left  = expression->left;
+       expression_t *expr_right = expression->right;
+       type_t       *type_left  = skip_typeref(expr_left->datatype);
+       type_t       *type_right = skip_typeref(expr_right->datatype);
+
+       if((is_type_arithmetic(type_left) && is_type_arithmetic(type_right))
+                       || (type_left->type == TYPE_POINTER
+                               && type_right->type == TYPE_POINTER)) {
+               return new_d_Sub(dbgi, left, right, mode);
+       }
+
+       assert(type_right->type == TYPE_POINTER);
+       ir_node        *pointer      = left;
+       ir_node        *integer      = right;
+       pointer_type_t *pointer_type = (pointer_type_t*) type_right;
+
+       type_t   *points_to = pointer_type->points_to;
+       unsigned  elem_size = get_type_size(points_to);
+
+       assert(elem_size >= 1);
+       if(elem_size > 1) {
+               ir_node *cnst = new_Const_long(mode_Iu, elem_size);
+               ir_node *mul  = new_d_Mul(dbgi, integer, cnst, mode_Iu);
+               integer = mul;
+       }
+
+       ir_node *res = new_d_Sub(dbgi, pointer, integer, mode);
+
+       return res;
+}
+
+
+
 static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
 {
        binary_expression_type_t type = expression->type;
@@ -938,9 +1001,9 @@ static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
                return right;
        }
        case BINEXPR_ADD:
-               return create_arithmetic_binop(expression, new_d_Add);
+               return create_add(expression);
        case BINEXPR_SUB:
-               return create_arithmetic_binop(expression, new_d_Sub);
+               return create_sub(expression);
        case BINEXPR_MUL:
                return create_arithmetic_binop(expression, new_d_Mul);
        case BINEXPR_BITWISE_AND:
@@ -1258,7 +1321,9 @@ static void for_statement_to_firm(for_statement_t *statement)
 
        ir_node *jmp = NULL;
        if (get_cur_block() != NULL) {
-               expression_to_firm(statement->initialisation);
+               if(statement->initialisation != NULL) {
+                       expression_to_firm(statement->initialisation);
+               }
                jmp = new_Jmp();
        }
 
index e69de29..aae6e6b 100644 (file)
--- a/config.h
+++ b/config.h
@@ -0,0 +1 @@
+#define INLINE inline
index c5673bd..aafbc36 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -45,6 +45,7 @@ static type_t         *type_const_char  = NULL;
 static type_t         *type_string      = NULL;
 static type_t         *type_void        = NULL;
 static type_t         *type_size_t      = NULL;
+static type_t         *type_ptrdiff_t   = NULL;
 
 static statement_t *parse_compound_statement(void);
 static statement_t *parse_statement(void);
@@ -2598,6 +2599,72 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
        expression->expression.datatype = expression->left->datatype;
 }
 
+static void semantic_add(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;
+       type_t       *type_left       = skip_typeref(orig_type_left);
+       type_t       *type_right      = skip_typeref(orig_type_right);
+
+       /* § 5.6.5 */
+       if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+               semantic_arithmetic(&expression->left, &expression->right);
+               expression->expression.datatype = expression->left->datatype;
+               return;
+       } else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
+               expression->expression.datatype = type_left;
+       } else if(type_right->type == TYPE_POINTER && is_type_integer(type_left)) {
+               expression->expression.datatype = type_right;
+       } else {
+               parser_print_error_prefix();
+               fprintf(stderr, "invalid operands to binary + (");
+               print_type(orig_type_left);
+               fprintf(stderr, ", ");
+               print_type(orig_type_right);
+               fprintf(stderr, ")\n");
+       }
+}
+
+static void semantic_sub(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;
+       type_t       *type_left       = skip_typeref(orig_type_left);
+       type_t       *type_right      = skip_typeref(orig_type_right);
+
+       /* § 5.6.5 */
+       if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
+               semantic_arithmetic(&expression->left, &expression->right);
+               expression->expression.datatype = expression->left->datatype;
+               return;
+       } else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
+               expression->expression.datatype = type_left;
+       } else if(type_left->type == TYPE_POINTER &&
+                       type_right->type == TYPE_POINTER) {
+               if(!pointers_compatible(type_left, type_right)) {
+                       parser_print_error_prefix();
+                       fprintf(stderr, "pointers to incompatible objects to binary - (");
+                       print_type(orig_type_left);
+                       fprintf(stderr, ", ");
+                       print_type(orig_type_right);
+                       fprintf(stderr, ")\n");
+               } else {
+                       expression->expression.datatype = type_ptrdiff_t;
+               }
+       } else {
+               parser_print_error_prefix();
+               fprintf(stderr, "invalid operands to binary - (");
+               print_type(orig_type_left);
+               fprintf(stderr, ", ");
+               print_type(orig_type_right);
+               fprintf(stderr, ")\n");
+       }
+}
+
 static void semantic_comparison(binary_expression_t *expression)
 {
        expression_t *left       = expression->left;
@@ -2702,8 +2769,8 @@ CREATE_BINEXPR_PARSER(',', BINEXPR_COMMA,          semantic_comma)
 CREATE_BINEXPR_PARSER('*', BINEXPR_MUL,            semantic_binexpr_arithmetic)
 CREATE_BINEXPR_PARSER('/', BINEXPR_DIV,            semantic_binexpr_arithmetic)
 CREATE_BINEXPR_PARSER('%', BINEXPR_MOD,            semantic_binexpr_arithmetic)
-CREATE_BINEXPR_PARSER('+', BINEXPR_ADD,            semantic_binexpr_arithmetic)
-CREATE_BINEXPR_PARSER('-', BINEXPR_SUB,            semantic_binexpr_arithmetic)
+CREATE_BINEXPR_PARSER('+', BINEXPR_ADD,            semantic_add)
+CREATE_BINEXPR_PARSER('-', BINEXPR_SUB,            semantic_sub)
 CREATE_BINEXPR_PARSER('<', BINEXPR_LESS,           semantic_comparison)
 CREATE_BINEXPR_PARSER('>', BINEXPR_GREATER,        semantic_comparison)
 CREATE_BINEXPR_PARSER('=', BINEXPR_ASSIGN,         semantic_binexpr_assign)
@@ -3346,7 +3413,8 @@ void init_parser(void)
        type_long_double = make_atomic_type(ATOMIC_TYPE_LONG_DOUBLE, 0);
        type_double      = make_atomic_type(ATOMIC_TYPE_DOUBLE, 0);
        type_float       = make_atomic_type(ATOMIC_TYPE_FLOAT, 0);
-       type_size_t      = make_atomic_type(ATOMIC_TYPE_UINT, 0);
+       type_size_t      = make_atomic_type(ATOMIC_TYPE_ULONG, 0);
+       type_ptrdiff_t   = make_atomic_type(ATOMIC_TYPE_LONG, 0);
        type_const_char  = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST);
        type_void        = make_atomic_type(ATOMIC_TYPE_VOID, 0);
        type_string      = make_pointer_type(type_const_char, 0);
diff --git a/type.c b/type.c
index 8ec2495..c694cf8 100644 (file)
--- a/type.c
+++ b/type.c
@@ -462,6 +462,13 @@ bool is_type_scalar(const type_t *type)
        return is_type_arithmetic(type);
 }
 
+bool pointers_compatible(const type_t *type1, const type_t *type2)
+{
+       assert(type1->type == TYPE_POINTER);
+       assert(type2->type == TYPE_POINTER);
+       return true;
+}
+
 type_t *skip_typeref(type_t *type)
 {
        while(1) {
diff --git a/type.h b/type.h
index 3cb81e1..2bf5940 100644 (file)
--- a/type.h
+++ b/type.h
@@ -72,6 +72,8 @@ bool is_type_arithmetic(const type_t *type);
  */
 bool is_type_scalar(const type_t *type);
 
+bool pointers_compatible(const type_t *type1, const type_t *type2);
+
 type_t *skip_typeref(type_t *type);
 
 #endif