more work on local variable support
authorMatthias Braun <matze@braunis.de>
Mon, 12 Nov 2007 19:48:06 +0000 (19:48 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 12 Nov 2007 19:48:06 +0000 (19:48 +0000)
[r18379]

Makefile
TODO
ast2firm.c
ast_t.h
parser.c
tokens.inc

index aeda011..0c3f793 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=pentium4 -fomit-frame-pointer -DNDEBUG
+#CFLAGS += -O3 -march=pentium3 -fomit-frame-pointer -DNDEBUG
 
 LFLAGS = $(FIRM_LIBS)
 
diff --git a/TODO b/TODO
index 3d38be0..b8a641a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -7,3 +7,5 @@ Lexer:
 
 Parser:
 - proper handling of function pointer types
+- outermost typequalifiers can differ between function declarations and
+  implementations...
index f9a64e2..0f1d7b9 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <assert.h>
 #include <string.h>
+#include <stdbool.h>
 
 #include <libfirm/firm.h>
 #include <libfirm/adt/obst.h>
@@ -24,12 +25,12 @@ static type_t *type_const_char;
 static type_t *type_void;
 static type_t *type_int;
 
+static int next_value_number_function;
+
 typedef enum declaration_type_t {
        DECLARATION_TYPE_UNKNOWN,
        DECLARATION_TYPE_FUNCTION,
        DECLARATION_TYPE_GLOBAL_VARIABLE,
-       DECLARATION_TYPE_PARAMETER,
-       DECLARATION_TYPE_PARAMETER_ENTITY,
        DECLARATION_TYPE_LOCAL_VARIABLE,
        DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY,
        DECLARATION_TYPE_COMPOUND_MEMBER
@@ -631,23 +632,17 @@ 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        = declaration->type;
+       ir_mode       *mode        = get_ir_mode(type);
 
        switch((declaration_type_t) declaration->declaration_type) {
        case DECLARATION_TYPE_UNKNOWN:
                break;
-       case DECLARATION_TYPE_PARAMETER: {
-               ir_node *args  = get_irg_args(current_ir_graph);
-               ir_mode *mode  = get_ir_mode(declaration->type);
-               ir_node *block = get_irg_start_block(current_ir_graph);
-               long     pn    = declaration->v.value_number;
-
-               return new_r_Proj(current_ir_graph, block, args, mode, pn);
-       }
+       case DECLARATION_TYPE_LOCAL_VARIABLE:
+               return get_value(declaration->v.value_number, mode);
        case DECLARATION_TYPE_FUNCTION: {
                return create_symconst(dbgi, declaration->v.entity);
        }
-       case DECLARATION_TYPE_PARAMETER_ENTITY:
-       case DECLARATION_TYPE_LOCAL_VARIABLE:
        case DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY:
        case DECLARATION_TYPE_GLOBAL_VARIABLE:
        case DECLARATION_TYPE_COMPOUND_MEMBER:
@@ -751,8 +746,16 @@ static ir_node *expression_addr(const expression_t *expression)
 static void set_value_for_expression(const expression_t *expression,
                                      ir_node *value)
 {
-       (void) expression;
-       (void) value;
+       if(expression->type == EXPR_REFERENCE) {
+               reference_expression_t *ref = (reference_expression_t*) expression;
+
+               declaration_t *declaration = ref->declaration;
+               assert(declaration->declaration_type != DECLARATION_TYPE_UNKNOWN);
+               if(declaration->declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE) {
+                       set_value(declaration->v.value_number, value);
+                       return;
+               }
+       }
        panic("set_value_for_expression not implemented yet");
 }
 
@@ -837,6 +840,50 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression)
        panic("invalid UNEXPR type found");
 }
 
+static long get_pnc(binary_expression_type_t type)
+{
+       switch(type) {
+       case BINEXPR_EQUAL:        return pn_Cmp_Eq;
+       case BINEXPR_NOTEQUAL:     return pn_Cmp_Lg;
+       case BINEXPR_LESS:         return pn_Cmp_Lt;
+       case BINEXPR_LESSEQUAL:    return pn_Cmp_Le;
+       case BINEXPR_GREATER:      return pn_Cmp_Gt;
+       case BINEXPR_GREATEREQUAL: return pn_Cmp_Ge;
+       default:
+               break;
+       }
+       panic("trying to get pn_Cmp from non-comparison binexpr type");
+}
+
+static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
+{
+       dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+
+       binary_expression_type_t type = expression->type;
+       switch(type) {
+       case BINEXPR_EQUAL:
+       case BINEXPR_NOTEQUAL:
+       case BINEXPR_LESS:
+       case BINEXPR_LESSEQUAL:
+       case BINEXPR_GREATER:
+       case BINEXPR_GREATEREQUAL: {
+               ir_node *left  = expression_to_firm(expression->left);
+               ir_node *right = expression_to_firm(expression->right);
+               ir_node *cmp   = new_d_Cmp(dbgi, left, right);
+               long     pnc   = get_pnc(type);
+               ir_node *proj  = new_d_Proj(dbgi, cmp, mode_b, pnc);
+               return proj;
+       }
+       case BINEXPR_ASSIGN: {
+               ir_node *right = expression_to_firm(expression->right);
+               set_value_for_expression(expression->left, right);
+               return right;
+       }
+       default:
+               panic("TODO binexpr type");
+       }
+}
+
 static ir_node *expression_to_firm(const expression_t *expression)
 {
        switch(expression->type) {
@@ -845,12 +892,15 @@ static ir_node *expression_to_firm(const expression_t *expression)
        case EXPR_STRING_LITERAL:
                return string_literal_to_firm((const string_literal_t*) expression);
        case EXPR_REFERENCE:
-               return reference_expression_to_firm((const reference_expression_t*)
-                                                   expression);
+               return reference_expression_to_firm(
+                               (const reference_expression_t*) expression);
        case EXPR_CALL:
                return call_expression_to_firm((const call_expression_t*) expression);
        case EXPR_UNARY:
                return unary_expression_to_firm((const unary_expression_t*) expression);
+       case EXPR_BINARY:
+               return binary_expression_to_firm(
+                               (const binary_expression_t*) expression);
        default:
                break;
        }
@@ -900,7 +950,9 @@ static void if_statement_to_firm(if_statement_t *statement)
        dbg_info *dbgi      = get_dbg_info(&statement->statement.source_position);
        ir_node  *condition = expression_to_firm(statement->condition);
        assert(condition != NULL);
-       assert(get_irn_mode(condition) == mode_b);
+
+       /* make sure we have a mode_b condition */
+       condition = create_conv(dbgi, condition, mode_b);
 
        ir_node *cond       = new_d_Cond(dbgi, condition);
        ir_node *true_proj  = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true);
@@ -938,6 +990,142 @@ static void if_statement_to_firm(if_statement_t *statement)
        set_cur_block(fallthrough_block);
 }
 
+static void while_statement_to_firm(while_statement_t *statement)
+{
+       dbg_info *dbgi      = get_dbg_info(&statement->statement.source_position);
+
+       /* create the header block */
+       ir_node *jmp          = new_Jmp();
+       ir_node *header_block = new_immBlock();
+       add_immBlock_pred(header, jmp);
+
+       /* create the condition */
+       ir_node  *condition = expression_to_firm(statement->condition);
+       assert(condition != NULL);
+       /* make sure we have a mode_b condition */
+       condition = create_conv(dbgi, condition, mode_b);
+
+       ir_node *cond       = new_d_Cond(dbgi, condition);
+       ir_node *true_proj  = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true);
+       ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false);
+
+       /* the loop body */
+       ir_node *body_block = new_immBlock();
+       add_immBlock_pred(body_block, true_proj);
+       mature_immBlock(true_block);
+
+       statement_to_firm(statement->true_statement);
+       if(get_cur_block() != NULL) {
+               ir_node *jmp = new_Jmp();
+               add_immBlock_pred(fallthrough_block, jmp);
+       }
+
+       /* the false (blocks) */
+       if(statement->false_statement != NULL) {
+               ir_node *false_block = new_immBlock();
+               add_immBlock_pred(false_block, false_proj);
+               mature_immBlock(false_block);
+
+               statement_to_firm(statement->false_statement);
+               if(get_cur_block() != NULL) {
+                       ir_node *jmp = new_Jmp();
+                       add_immBlock_pred(fallthrough_block, jmp);
+               }
+       } else {
+               add_immBlock_pred(fallthrough_block, false_proj);
+       }
+       mature_immBlock(fallthrough_block);
+
+       set_cur_block(fallthrough_block);
+}
+
+static void create_declaration_entity(declaration_t *declaration,
+                                      declaration_type_t declaration_type,
+                                      ir_type *parent_type)
+{
+       ident     *id     = new_id_from_str(declaration->symbol->string);
+       ir_type   *irtype = get_ir_type(declaration->type);
+       ir_entity *entity = new_entity(parent_type, id, irtype);
+       set_entity_ld_ident(entity, id);
+
+       declaration->declaration_type = declaration_type;
+       declaration->v.entity         = entity;
+       set_entity_variability(entity, variability_uninitialized);
+       /* TODO: visibility? */
+}
+
+static void create_initializer(declaration_t *declaration)
+{
+       initializer_t *initializer = declaration->init.initializer;
+       if(initializer == NULL)
+               return;
+
+       if(initializer->type == INITIALIZER_VALUE) {
+               assert(initializer->designator == NULL);
+               assert(initializer->next == NULL);
+               ir_node *init_node = expression_to_firm(initializer->v.value);
+
+               if(declaration->declaration_type == DECLARATION_TYPE_LOCAL_VARIABLE) {
+                       set_value(declaration->v.value_number, init_node);
+               } else {
+                       panic("initializer not completely implemented yet");
+               }
+       } else {
+               assert(initializer->type == INITIALIZER_LIST);
+               panic("list initializer not supported yet");
+       }
+}
+
+static void create_local_variable(declaration_t *declaration)
+{
+       bool needs_entity = declaration->address_taken;
+
+       assert(declaration->declaration_type == DECLARATION_TYPE_UNKNOWN);
+
+       if(needs_entity) {
+               ir_type *frame_type = get_irg_frame_type(current_ir_graph);
+               create_declaration_entity(declaration,
+                                         DECLARATION_TYPE_LOCAL_VARIABLE_ENTITY,
+                                         frame_type);
+       } else {
+               declaration->declaration_type = DECLARATION_TYPE_LOCAL_VARIABLE;
+               declaration->v.value_number   = next_value_number_function;
+               ++next_value_number_function;
+       }
+
+       create_initializer(declaration);
+}
+
+static void declaration_statement_to_firm(declaration_statement_t *statement)
+{
+       declaration_t *declaration = statement->declarations_begin;
+       declaration_t *end         = statement->declarations_end->next;
+       for( ; declaration != end; declaration = declaration->next) {
+               type_t *type = declaration->type;
+
+               switch(declaration->storage_class) {
+               case STORAGE_CLASS_TYPEDEF:
+                       continue;
+               case STORAGE_CLASS_STATIC:
+                       panic("static local vars not implemented yet");
+               case STORAGE_CLASS_ENUM_ENTRY:
+                       panic("enum entry declaration in local block found");
+               case STORAGE_CLASS_EXTERN:
+                       panic("extern declaration in local block found");
+               case STORAGE_CLASS_NONE:
+               case STORAGE_CLASS_AUTO:
+               case STORAGE_CLASS_REGISTER:
+                       if(type->type == TYPE_FUNCTION) {
+                               panic("nested functions not supported yet");
+                       } else {
+                               create_local_variable(declaration);
+                       }
+                       continue;
+               }
+               panic("invalid storage class found");
+       }
+}
+
 static void statement_to_firm(statement_t *statement)
 {
        switch(statement->type) {
@@ -953,6 +1141,9 @@ static void statement_to_firm(statement_t *statement)
        case STATEMENT_IF:
                if_statement_to_firm((if_statement_t*) statement);
                return;
+       case STATEMENT_DECLARATION:
+               declaration_statement_to_firm((declaration_statement_t*) statement);
+               return;
        default:
                break;
        }
@@ -968,14 +1159,29 @@ static int get_function_n_local_vars(declaration_t *declaration)
 
 static void initialize_function_parameters(declaration_t *declaration)
 {
+       ir_graph *irg         = current_ir_graph;
+       ir_node  *args        = get_irg_args(irg);
+       ir_node  *start_block = get_irg_start_block(irg);
+
        int            n         = 0;
        declaration_t *parameter = declaration->context.declarations;
        for( ; parameter != NULL; parameter = parameter->next) {
                assert(parameter->declaration_type == DECLARATION_TYPE_UNKNOWN);
 
-               parameter->declaration_type = DECLARATION_TYPE_PARAMETER;
-               parameter->v.value_number   = n;
+               if(parameter->address_taken) {
+                       panic("address take from parameter not implemented yet");
+               }
+
+               ir_mode *mode = get_ir_mode(parameter->type);
+               long     pn   = n;
+               ir_node *proj = new_r_Proj(irg, start_block, args, mode, pn);
                ++n;
+
+               parameter->declaration_type = DECLARATION_TYPE_LOCAL_VARIABLE;
+               parameter->v.value_number   = next_value_number_function;
+               ++next_value_number_function;
+
+               set_value(parameter->v.value_number, proj);
        }
 }
 
@@ -986,12 +1192,13 @@ static void create_function(declaration_t *declaration)
        if(declaration->init.statement == NULL)
                return;
 
-       initialize_function_parameters(declaration);
-
        int        n_local_vars = get_function_n_local_vars(declaration);
        ir_graph  *irg          = new_ir_graph(entity, n_local_vars);
        ir_node   *first_block  = get_cur_block();
 
+       next_value_number_function = 0;
+       initialize_function_parameters(declaration);
+
        statement_to_firm(declaration->init.statement);
 
        ir_node *end_block = get_irg_end_block(irg);
diff --git a/ast_t.h b/ast_t.h
index 61bd6a4..6b922bc 100644 (file)
--- a/ast_t.h
+++ b/ast_t.h
@@ -224,6 +224,7 @@ struct initializer_t {
 struct declaration_t {
        unsigned char       namespace;
        unsigned char       storage_class;
+       unsigned int        address_taken : 1;
        type_t             *type;
        symbol_t           *symbol;
        source_position_t   source_position;
@@ -286,9 +287,6 @@ struct declaration_statement_t {
        statement_t    statement;
        declaration_t *declarations_begin;
        declaration_t *declarations_end;
-
-       int            value_number; /**< filled in by semantic phase */
-       int            refs;
 };
 
 struct if_statement_t {
index 181fe9e..fdb85bd 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -2460,55 +2460,103 @@ CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_PLUSPLUS,   UNEXPR_POSTFIX_INCREMENT,
 CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(T_MINUSMINUS, UNEXPR_POSTFIX_DECREMENT,
                                        get_unexpr_arithmetic_type)
 
-#define CREATE_BINEXPR_PARSER(token_type, binexpression_type)    \
-static                                                           \
-expression_t *parse_##binexpression_type(unsigned precedence,    \
-                                         expression_t *left)     \
-{                                                                \
-       eat(token_type);                                             \
-                                                                 \
-       expression_t *right = parse_sub_expression(precedence);      \
-                                                                 \
-       binary_expression_t *binexpr                                 \
-               = allocate_ast_zero(sizeof(binexpr[0]));                 \
-       binexpr->expression.type = EXPR_BINARY;                      \
-       binexpr->type            = binexpression_type;               \
-       binexpr->left            = left;                             \
-       binexpr->right           = right;                            \
-                                                                 \
-       return (expression_t*) binexpr;                              \
-}
-
-CREATE_BINEXPR_PARSER(',', BINEXPR_COMMA)
-CREATE_BINEXPR_PARSER('*', BINEXPR_MUL)
-CREATE_BINEXPR_PARSER('/', BINEXPR_DIV)
-CREATE_BINEXPR_PARSER('%', BINEXPR_MOD)
-CREATE_BINEXPR_PARSER('+', BINEXPR_ADD)
-CREATE_BINEXPR_PARSER('-', BINEXPR_SUB)
-CREATE_BINEXPR_PARSER('<', BINEXPR_LESS)
-CREATE_BINEXPR_PARSER('>', BINEXPR_GREATER)
-CREATE_BINEXPR_PARSER('=', BINEXPR_ASSIGN)
-CREATE_BINEXPR_PARSER(T_EQUALEQUAL, BINEXPR_EQUAL)
-CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, BINEXPR_NOTEQUAL)
-CREATE_BINEXPR_PARSER(T_LESSEQUAL, BINEXPR_LESSEQUAL)
-CREATE_BINEXPR_PARSER(T_GREATEREQUAL, BINEXPR_GREATEREQUAL)
-CREATE_BINEXPR_PARSER('&', BINEXPR_BITWISE_AND)
-CREATE_BINEXPR_PARSER('|', BINEXPR_BITWISE_OR)
-CREATE_BINEXPR_PARSER('^', BINEXPR_BITWISE_XOR)
-CREATE_BINEXPR_PARSER(T_ANDAND, BINEXPR_LOGICAL_AND)
-CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR)
-CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT)
-CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT)
-CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN)
-CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN)
-CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, BINEXPR_MUL_ASSIGN)
-CREATE_BINEXPR_PARSER(T_SLASHEQUAL, BINEXPR_DIV_ASSIGN)
-CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, BINEXPR_MOD_ASSIGN)
-CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, BINEXPR_SHIFTLEFT_ASSIGN)
-CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, BINEXPR_SHIFTRIGHT_ASSIGN)
-CREATE_BINEXPR_PARSER(T_ANDEQUAL, BINEXPR_BITWISE_AND_ASSIGN)
-CREATE_BINEXPR_PARSER(T_PIPEEQUAL, BINEXPR_BITWISE_OR_ASSIGN)
-CREATE_BINEXPR_PARSER(T_CARETEQUAL, BINEXPR_BITWISE_XOR_ASSIGN)
+static type_t *get_binexpr_int_type(const expression_t *left,
+                                    const expression_t *right)
+{
+       (void) left;
+       (void) right;
+       return type_int;
+}
+
+static type_t *get_binexpr_arithmetic_type(const expression_t *left,
+                                            const expression_t *right)
+{
+       (void) right;
+       return left->datatype;
+}
+
+static type_t *get_binexpr_arithmetic_assign_type(const expression_t *left,
+                                                  const expression_t *right)
+{
+       (void) right;
+       /* TODO */
+       return left->datatype;
+}
+
+static type_t *get_binexpr_right_type(const expression_t *left,
+                                       const expression_t *right)
+{
+       (void) left;
+       return right->datatype;
+}
+
+#define CREATE_BINEXPR_PARSER(token_type, binexpression_type, tfunc)    \
+static expression_t *parse_##binexpression_type(unsigned precedence,    \
+                                                expression_t *left)     \
+{                                                                       \
+       eat(token_type);                                                    \
+                                                                        \
+       expression_t *right = parse_sub_expression(precedence);             \
+                                                                        \
+       binary_expression_t *binexpr                                        \
+               = allocate_ast_zero(sizeof(binexpr[0]));                        \
+       binexpr->expression.type     = EXPR_BINARY;                         \
+       binexpr->type                = binexpression_type;                  \
+       binexpr->left                = left;                                \
+       binexpr->right               = right;                               \
+       binexpr->expression.datatype = tfunc(left, right);                  \
+                                                                        \
+       return (expression_t*) binexpr;                                     \
+}
+
+CREATE_BINEXPR_PARSER(',', BINEXPR_COMMA,   get_binexpr_right_type)
+CREATE_BINEXPR_PARSER('*', BINEXPR_MUL,     get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER('/', BINEXPR_DIV,     get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER('%', BINEXPR_MOD,     get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER('+', BINEXPR_ADD,     get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER('-', BINEXPR_SUB,     get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER('<', BINEXPR_LESS,    get_binexpr_int_type)
+CREATE_BINEXPR_PARSER('>', BINEXPR_GREATER, get_binexpr_int_type)
+CREATE_BINEXPR_PARSER('=', BINEXPR_ASSIGN,  get_binexpr_right_type)
+CREATE_BINEXPR_PARSER(T_EQUALEQUAL, BINEXPR_EQUAL,
+                      get_binexpr_int_type)
+CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, BINEXPR_NOTEQUAL,
+                      get_binexpr_int_type)
+CREATE_BINEXPR_PARSER(T_LESSEQUAL, BINEXPR_LESSEQUAL,
+                      get_binexpr_int_type)
+CREATE_BINEXPR_PARSER(T_GREATEREQUAL, BINEXPR_GREATEREQUAL,
+                      get_binexpr_int_type)
+CREATE_BINEXPR_PARSER('&', BINEXPR_BITWISE_AND, get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER('|', BINEXPR_BITWISE_OR,  get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER('^', BINEXPR_BITWISE_XOR, get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER(T_ANDAND, BINEXPR_LOGICAL_AND,
+                      get_binexpr_int_type)
+CREATE_BINEXPR_PARSER(T_PIPEPIPE, BINEXPR_LOGICAL_OR,
+                      get_binexpr_int_type)
+CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT,
+                      get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT,
+                      get_binexpr_arithmetic_type)
+CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, BINEXPR_MUL_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_SLASHEQUAL, BINEXPR_DIV_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, BINEXPR_MOD_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, BINEXPR_SHIFTLEFT_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, BINEXPR_SHIFTRIGHT_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_ANDEQUAL, BINEXPR_BITWISE_AND_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_PIPEEQUAL, BINEXPR_BITWISE_OR_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
+CREATE_BINEXPR_PARSER(T_CARETEQUAL, BINEXPR_BITWISE_XOR_ASSIGN,
+                      get_binexpr_arithmetic_assign_type)
 
 static expression_t *parse_sub_expression(unsigned precedence)
 {
index 8692cff..c263a16 100644 (file)
@@ -67,6 +67,7 @@ T(asm,                     "asm",)
 T(__asm__,             "__asm__", = T_asm)
 T(inline,               "inline",)
 T(__inline,           "__inline", = T_inline)
+T(__inline__,       "__inline__", = T_inline)
 
 T(MINUSGREATER,             "->",)
 T(PLUSPLUS,                 "++",)