preliminary Win32 support added
[cparser] / ast2firm.c
index 4a68ed8..a33ce29 100644 (file)
@@ -32,6 +32,7 @@ static int       next_value_number_function;
 static ir_node  *continue_label;
 static ir_node  *break_label;
 static ir_node  *current_switch_cond;
+static bool      saw_default_label;
 static ir_node **imature_blocks;
 
 typedef enum declaration_type_t {
@@ -82,8 +83,8 @@ const char *retrieve_dbg(const dbg_info *dbg, unsigned *line)
 void init_ast2firm(void)
 {
        type_const_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_CONST);
-       type_void       = make_atomic_type(ATOMIC_TYPE_VOID, 0);
-       type_int        = make_atomic_type(ATOMIC_TYPE_INT, 0);
+       type_void       = make_atomic_type(ATOMIC_TYPE_VOID, TYPE_QUALIFIER_NONE);
+       type_int        = make_atomic_type(ATOMIC_TYPE_INT,  TYPE_QUALIFIER_NONE);
 
        ir_type_int        = get_ir_type(type_int);
        ir_type_const_char = get_ir_type(type_const_char);
@@ -501,7 +502,7 @@ static inline ir_mode *get_ir_mode(type_t *type)
                return mode_P;
        }
 
-       ir_mode *mode   = get_type_mode(irtype);
+       ir_mode *mode = get_type_mode(irtype);
        assert(mode != NULL);
        return mode;
 }
@@ -622,13 +623,14 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
        dbg_info      *dbgi        = get_dbg_info(&ref->expression.source_position);
        declaration_t *declaration = ref->declaration;
        type_t        *type        = skip_typeref(declaration->type);
-       ir_mode       *mode        = get_ir_mode(type);
 
        switch((declaration_type_t) declaration->declaration_type) {
        case DECLARATION_TYPE_UNKNOWN:
                break;
-       case DECLARATION_TYPE_LOCAL_VARIABLE:
+       case DECLARATION_TYPE_LOCAL_VARIABLE: {
+               ir_mode *mode = get_ir_mode(type);
                return get_value(declaration->v.value_number, mode);
+       }
        case DECLARATION_TYPE_FUNCTION: {
                return create_symconst(dbgi, declaration->v.entity);
        }
@@ -642,7 +644,19 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
                        return load_from_expression_addr(type, symconst, dbgi);
                }
        }
-       case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY:
+       case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY: {
+               ir_entity *entity = declaration->v.entity;
+               ir_node   *frame  = get_irg_frame(current_ir_graph);
+               ir_node   *sel    = new_d_simpleSel(dbgi, new_NoMem(), frame, entity);
+
+               if(type->type == TYPE_ARRAY || type->type == TYPE_COMPOUND_STRUCT
+                               || type->type == TYPE_COMPOUND_UNION) {
+                       return sel;
+               } else {
+                       return load_from_expression_addr(type, sel, dbgi);
+               }
+       }
+
        case DECLARATION_TYPE_COMPOUND_MEMBER:
        case DECLARATION_TYPE_LABEL_BLOCK:
                panic("not implemented reference type");
@@ -669,7 +683,13 @@ static ir_node *reference_addr(const reference_expression_t *ref)
                ir_node   *symconst = create_symconst(dbgi, entity);
                return symconst;
        }
-       case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY:
+       case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY: {
+               ir_entity *entity = declaration->v.entity;
+               ir_node   *frame  = get_irg_frame(current_ir_graph);
+               ir_node   *sel    = new_d_simpleSel(dbgi, new_NoMem(), frame, entity);
+
+               return sel;
+       }
        case DECLARATION_TYPE_COMPOUND_MEMBER:
        case DECLARATION_TYPE_LABEL_BLOCK:
                panic("not implemented reference type");
@@ -1042,6 +1062,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 +1165,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);
@@ -1223,6 +1278,38 @@ static ir_node *conditional_to_firm(const conditional_expression_t *expression)
        return val;
 }
 
+static ir_node *select_addr(const select_expression_t *expression)
+{
+       dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+
+       ir_node *compound_addr = expression_to_firm(expression->compound);
+
+       declaration_t *entry = expression->compound_entry;
+       assert(entry->declaration_type == DECLARATION_TYPE_COMPOUND_MEMBER);
+       ir_entity     *entity = entry->v.entity;
+
+       assert(entity != NULL);
+
+       ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), compound_addr, entity);
+
+       return sel;
+}
+
+static ir_node *select_to_firm(const select_expression_t *expression)
+{
+       dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+       ir_node  *addr = select_addr(expression);
+       type_t   *type = expression->expression.datatype;
+
+       return load_from_expression_addr(type, addr, dbgi);
+}
+
+static ir_node *dereference_addr(const unary_expression_t *const expression)
+{
+       assert(expression->type == UNEXPR_DEREFERENCE);
+       return expression_to_firm(expression->value);
+}
+
 static ir_node *expression_to_addr(const expression_t *expression)
 {
        switch(expression->type) {
@@ -1230,6 +1317,16 @@ static ir_node *expression_to_addr(const expression_t *expression)
                return reference_addr((const reference_expression_t*) expression);
        case EXPR_ARRAY_ACCESS:
                return array_access_addr((const array_access_expression_t*) expression);
+       case EXPR_SELECT:
+               return select_addr((const select_expression_t*) expression);
+       case EXPR_UNARY: {
+               const unary_expression_t *const unary_expr =
+                       (const unary_expression_t*)expression;
+               if (unary_expr->type == UNEXPR_DEREFERENCE) {
+                       return dereference_addr(unary_expr);
+               }
+               break;
+       }
        default:
                break;
        }
@@ -1260,21 +1357,32 @@ static ir_node *_expression_to_firm(const expression_t *expression)
                return sizeof_to_firm((const sizeof_expression_t*) expression);
        case EXPR_CONDITIONAL:
                return conditional_to_firm((const conditional_expression_t*)expression);
-       default:
+       case EXPR_SELECT:
+               return select_to_firm((const select_expression_t*) expression);
+       case EXPR_FUNCTION:
+       case EXPR_OFFSETOF:
+       case EXPR_PRETTY_FUNCTION:
+       case EXPR_VA_ARG:
+       case EXPR_STATEMENT:
+       case EXPR_BUILTIN_SYMBOL:
+               panic("unimplemented expression found");
+
+       case EXPR_UNKNOWN:
+       case EXPR_INVALID:
                break;
        }
-       panic("unsupported expression found");
+       panic("invalid expression found");
 }
 
 static ir_node *expression_to_firm(const expression_t *expression)
 {
-       ir_node *res  = _expression_to_firm(expression);
+       ir_node *res = _expression_to_firm(expression);
 
-       if(expression->datatype == type_void)
-               return NULL;
+       if(res != NULL && get_irn_mode(res) == mode_b) {
+               ir_mode *mode = get_ir_mode(expression->datatype);
+               res           = create_conv(NULL, res, mode);
+       }
 
-       ir_mode *mode = get_ir_mode(expression->datatype);
-       res           = create_conv(NULL, res, mode);
        return res;
 }
 
@@ -1459,6 +1567,7 @@ static void do_while_statement_to_firm(do_while_statement_t *statement)
        if(get_cur_block() == NULL) {
                mature_immBlock(header_block);
                mature_immBlock(body_block);
+               mature_immBlock(false_block);
                return;
        }
 
@@ -1467,6 +1576,7 @@ static void do_while_statement_to_firm(do_while_statement_t *statement)
        mature_immBlock(header_block);
 
        /* create the condition */
+       set_cur_block(header_block);
        ir_node *condition  = expression_to_modeb(statement->condition);
        ir_node *cond       = new_d_Cond(dbgi, condition);
        ir_node *true_proj  = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true);
@@ -1598,9 +1708,16 @@ static void create_initializer(declaration_t *declaration)
 
 static void create_local_variable(declaration_t *declaration)
 {
+       assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN);
+
        bool needs_entity = declaration->address_taken;
+       type_t *type = skip_typeref(declaration->type);
 
-       assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN);
+       if(type->type == TYPE_ARRAY
+                       || type->type == TYPE_COMPOUND_STRUCT
+                       || type->type == TYPE_COMPOUND_UNION) {
+               needs_entity = true;
+       }
 
        if(needs_entity) {
                ir_type *frame_type = get_irg_frame_type(current_ir_graph);
@@ -1649,6 +1766,9 @@ static void declaration_statement_to_firm(declaration_statement_t *statement)
 static void create_jump_statement(const statement_t *statement,
                                   ir_node *target_block)
 {
+       if(get_cur_block() == NULL)
+               return;
+
        dbg_info *dbgi = get_dbg_info(&statement->source_position);
        ir_node  *jump = new_d_Jmp(dbgi);
        add_immBlock_pred(target_block, jump);
@@ -1666,10 +1786,11 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
 
        set_cur_block(NULL);
 
-       ir_node *old_switch_cond = current_switch_cond;
-       ir_node *old_break_label = break_label;
-       current_switch_cond      = cond;
-       break_label              = break_block;
+       ir_node *const old_switch_cond       = current_switch_cond;
+       ir_node *const old_break_label       = break_label;
+       const bool     old_saw_default_label = saw_default_label;
+       current_switch_cond                  = cond;
+       break_label                          = break_block;
 
        statement_to_firm(statement->body);
 
@@ -1678,10 +1799,18 @@ static void switch_statement_to_firm(const switch_statement_t *statement)
                add_immBlock_pred(break_block, jmp);
        }
 
+       if (!saw_default_label) {
+               set_cur_block(get_nodes_block(cond));
+               ir_node *const proj = new_d_defaultProj(dbgi, cond,
+                                                       MAGIC_DEFAULT_PN_NUMBER);
+               add_immBlock_pred(break_block, proj);
+       }
+
        assert(current_switch_cond == cond);
        assert(break_label         == break_block);
        current_switch_cond = old_switch_cond;
        break_label         = old_break_label;
+       saw_default_label   = old_saw_default_label;
 
        mature_immBlock(break_block);
        set_cur_block(break_block);
@@ -1711,6 +1840,8 @@ static void case_label_to_firm(const case_label_statement_t *statement)
 {
        dbg_info *dbgi = get_dbg_info(&statement->statement.source_position);
 
+       ir_node *const fallthrough = (get_cur_block() == NULL ? NULL : new_Jmp());
+
        /* let's create a node and hope firm constant folding creates a Const
         * node... */
        ir_node *proj;
@@ -1723,11 +1854,15 @@ static void case_label_to_firm(const case_label_statement_t *statement)
                }
                proj = new_d_Proj(dbgi, current_switch_cond, mode_X, pn);
        } else {
+               saw_default_label = true;
                proj = new_d_defaultProj(dbgi, current_switch_cond,
                                         MAGIC_DEFAULT_PN_NUMBER);
        }
 
        ir_node *block = new_immBlock();
+       if (fallthrough != NULL) {
+               add_immBlock_pred(block, fallthrough);
+       }
        add_immBlock_pred(block, proj);
        mature_immBlock(block);
 }
@@ -1848,9 +1983,16 @@ static void initialize_function_parameters(declaration_t *declaration)
        declaration_t *parameter = declaration->context.declarations;
        for( ; parameter != NULL; parameter = parameter->next) {
                assert(parameter->declaration_type == DECLARATION_TYPE_UNKNOWN);
+               type_t *type = parameter->type;
+
+               bool needs_entity = parameter->address_taken;
+               if(type->type == TYPE_COMPOUND_STRUCT
+                               || type->type == TYPE_COMPOUND_UNION) {
+                       needs_entity = true;
+               }
 
-               if(parameter->address_taken) {
-                       panic("address take from parameter not implemented yet");
+               if(needs_entity) {
+                       panic("entities for function parameters not implemented yet");
                }
 
                ir_mode *mode = get_ir_mode(parameter->type);