From 1869440fd93fdbdc0abf7da0876e591b0a7b11a6 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Sat, 10 Nov 2012 19:35:52 +0100 Subject: [PATCH] Preparing to parse arrays: adding TYPE_ARRAY and union/struct TYPE_ constants to be consistent with fteqcc, filled type-arrays with their data, attempting to parse an array variable and added some error messages to the IR in case of unhandled types --- ast.h | 2 ++ gmqcc.h | 3 +++ ir.c | 60 ++++++++++++++++++++++++++++++++++++++++----- parser.c | 74 +++++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 119 insertions(+), 20 deletions(-) diff --git a/ast.h b/ast.h index ffad710..76f2c26 100644 --- a/ast.h +++ b/ast.h @@ -116,6 +116,8 @@ typedef struct ast_expression_codegen *codegen; int vtype; ast_expression *next; + /* arrays get a member-count */ + size_t count; MEM_VECTOR_MAKE(ast_value*, params); bool variadic; /* The codegen functions should store their output values diff --git a/gmqcc.h b/gmqcc.h index bf9f63f..01ebd4a 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -290,6 +290,9 @@ enum { TYPE_POINTER , TYPE_INTEGER , TYPE_VARIANT , + TYPE_STRUCT , + TYPE_UNION , + TYPE_ARRAY , TYPE_COUNT }; diff --git a/ir.c b/ir.c index 940cfbb..7af6162 100644 --- a/ir.c +++ b/ir.c @@ -38,10 +38,11 @@ const char *type_name[TYPE_COUNT] = { "field", "function", "pointer", -#if 0 "integer", -#endif - "variant" + "variant", + "struct", + "union", + "array" }; size_t type_sizeof[TYPE_COUNT] = { @@ -53,10 +54,11 @@ size_t type_sizeof[TYPE_COUNT] = { 1, /* TYPE_FIELD */ 1, /* TYPE_FUNCTION */ 1, /* TYPE_POINTER */ -#if 0 1, /* TYPE_INTEGER */ -#endif 3, /* TYPE_VARIANT */ + 0, /* TYPE_STRUCT */ + 0, /* TYPE_UNION */ + 0, /* TYPE_ARRAY */ }; uint16_t type_store_instr[TYPE_COUNT] = { @@ -70,9 +72,15 @@ uint16_t type_store_instr[TYPE_COUNT] = { INSTR_STORE_ENT, /* should use I */ #if 0 INSTR_STORE_I, /* integer type */ +#else + INSTR_STORE_F, #endif INSTR_STORE_V, /* variant, should never be accessed */ + + AINSTR_END, /* struct */ + AINSTR_END, /* union */ + AINSTR_END, /* array */ }; uint16_t field_store_instr[TYPE_COUNT] = { @@ -86,9 +94,15 @@ uint16_t field_store_instr[TYPE_COUNT] = { INSTR_STORE_FLD, #if 0 INSTR_STORE_FLD, /* integer type */ +#else + INSTR_STORE_FLD, #endif INSTR_STORE_V, /* variant, should never be accessed */ + + AINSTR_END, /* struct */ + AINSTR_END, /* union */ + AINSTR_END, /* array */ }; uint16_t type_storep_instr[TYPE_COUNT] = { @@ -102,9 +116,15 @@ uint16_t type_storep_instr[TYPE_COUNT] = { INSTR_STOREP_ENT, /* should use I */ #if 0 INSTR_STOREP_ENT, /* integer type */ +#else + INSTR_STOREP_F, #endif INSTR_STOREP_V, /* variant, should never be accessed */ + + AINSTR_END, /* struct */ + AINSTR_END, /* union */ + AINSTR_END, /* array */ }; uint16_t type_eq_instr[TYPE_COUNT] = { @@ -118,9 +138,15 @@ uint16_t type_eq_instr[TYPE_COUNT] = { INSTR_EQ_E, /* should use I */ #if 0 INSTR_EQ_I, +#else + INSTR_EQ_F, #endif INSTR_EQ_V, /* variant, should never be accessed */ + + AINSTR_END, /* struct */ + AINSTR_END, /* union */ + AINSTR_END, /* array */ }; uint16_t type_ne_instr[TYPE_COUNT] = { @@ -134,9 +160,15 @@ uint16_t type_ne_instr[TYPE_COUNT] = { INSTR_NE_E, /* should use I */ #if 0 INSTR_NE_I, +#else + INSTR_NE_F, #endif INSTR_NE_V, /* variant, should never be accessed */ + + AINSTR_END, /* struct */ + AINSTR_END, /* union */ + AINSTR_END, /* array */ }; MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v) @@ -1561,6 +1593,7 @@ ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_va case TYPE_INTEGER: op = INSTR_LOAD_I; break; #endif default: + irerror(self->context, "invalid type for ir_block_create_load_from_ent: %s", type_name[outype]); return NULL; } @@ -1577,6 +1610,7 @@ ir_value* ir_block_create_add(ir_block *self, if (l == r) { switch (l) { default: + irerror(self->context, "invalid type for ir_block_create_add: %s", type_name[l]); return NULL; case TYPE_FLOAT: op = INSTR_ADD_F; @@ -1598,7 +1632,10 @@ ir_value* ir_block_create_add(ir_block *self, op = INSTR_ADD_IF; else #endif + { + irerror(self->context, "invalid type for ir_block_create_add: %s", type_name[l]); return NULL; + } } return ir_block_create_binop(self, label, op, left, right); } @@ -1614,6 +1651,7 @@ ir_value* ir_block_create_sub(ir_block *self, switch (l) { default: + irerror(self->context, "invalid type for ir_block_create_sub: %s", type_name[l]); return NULL; case TYPE_FLOAT: op = INSTR_SUB_F; @@ -1635,7 +1673,10 @@ ir_value* ir_block_create_sub(ir_block *self, op = INSTR_SUB_IF; else #endif + { + irerror(self->context, "invalid type for ir_block_create_sub: %s", type_name[l]); return NULL; + } } return ir_block_create_binop(self, label, op, left, right); } @@ -1651,6 +1692,7 @@ ir_value* ir_block_create_mul(ir_block *self, switch (l) { default: + irerror(self->context, "invalid type for ir_block_create_mul: %s", type_name[l]); return NULL; case TYPE_FLOAT: op = INSTR_MUL_F; @@ -1679,8 +1721,10 @@ ir_value* ir_block_create_mul(ir_block *self, else if ( (l == TYPE_INTEGER && r == TYPE_FLOAT) ) op = INSTR_MUL_IF; #endif - else + else { + irerror(self->context, "invalid type for ir_block_create_mul: %s", type_name[l]); return NULL; + } } return ir_block_create_binop(self, label, op, left, right); } @@ -1696,6 +1740,7 @@ ir_value* ir_block_create_div(ir_block *self, switch (l) { default: + irerror(self->context, "invalid type for ir_block_create_div: %s", type_name[l]); return NULL; case TYPE_FLOAT: op = INSTR_DIV_F; @@ -1716,7 +1761,10 @@ ir_value* ir_block_create_div(ir_block *self, op = INSTR_DIV_IF; else #endif + { + irerror(self->context, "invalid type for ir_block_create_div: %s", type_name[l]); return NULL; + } } return ir_block_create_binop(self, label, op, left, right); } diff --git a/parser.c b/parser.c index ef8d0ae..0616b71 100644 --- a/parser.c +++ b/parser.c @@ -2314,29 +2314,25 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase) return NULL; } - /* an opening paren now starts the parameter-list of a function */ + /* an opening paren now starts the parameter-list of a function + * this is where original-QC has parameter lists. + * We allow a single parameter list here. + * Much like fteqcc we don't allow `float()() x` + */ if (parser->tok == '(') { var = parse_parameter_list(parser, var); if (!var) return NULL; } - /* This is the point where we can turn it into a field */ - if (isfield) { - /* turn it into a field if desired */ - tmp = ast_value_new(ctx, "", TYPE_FIELD); - tmp->expression.next = (ast_expression*)var; - var = tmp; - } - - while (parser->tok == '(') { - var = parse_parameter_list(parser, var); - if (!var) - return NULL; - } /* store the base if requested */ if (storebase) { *storebase = ast_value_copy(var); + if (isfield) { + tmp = ast_value_new(ctx, "", TYPE_FIELD); + tmp->expression.next = (ast_expression*)*storebase; + *storebase = tmp; + } } /* there may be a name now */ @@ -2344,11 +2340,60 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase) name = util_strdup(parser_tokval(parser)); /* parse on */ if (!parser_next(parser)) { + ast_delete(var); parseerror(parser, "error after variable or field declaration"); return NULL; } } + /* now this may be an array */ + if (parser->tok == '[') { + ast_expression *cexp = parse_expression_leave(parser, true); + ast_value *cval; + if (!cexp || !ast_istype(cexp, ast_value)) { + if (cexp) ast_delete(cexp); + ast_delete(var); + parseerror(parser, "expected array-size as constant positive integer"); + return NULL; + } + cval = (ast_value*)cexp; + + tmp = ast_value_new(ctx, "", TYPE_ARRAY); + tmp->expression.next = (ast_expression*)var; + var = tmp; + + if (cval->expression.vtype == TYPE_INTEGER) + tmp->expression.count = cval->constval.vint; + else if (cval->expression.vtype == TYPE_FLOAT) + tmp->expression.count = cval->constval.vfloat; + else { + ast_delete(cexp); + ast_delete(var); + parseerror(parser, "array-size must be a positive integer constant"); + return NULL; + } + ast_delete(cexp); + + if (parser->tok != ']') { + ast_delete(var); + parseerror(parser, "expected ']' after array-size"); + return NULL; + } + if (!parser_next(parser)) { + ast_delete(var); + parseerror(parser, "error after parsing array size"); + return NULL; + } + } + + /* This is the point where we can turn it into a field */ + if (isfield) { + /* turn it into a field if desired */ + tmp = ast_value_new(ctx, "", TYPE_FIELD); + tmp->expression.next = (ast_expression*)var; + var = tmp; + } + /* now there may be function parens again */ if (parser->tok == '(' && opts_standard == COMPILER_QCC) parseerror(parser, "C-style function syntax is not allowed in -std=qcc"); @@ -2357,6 +2402,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase) if (!var) { if (name) mem_d((void*)name); + ast_delete(var); return NULL; } } -- 2.39.2