X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=parser.c;h=54577ea1b817860016bce55e18fd17fba207e9ff;hb=38f509077826ded67870f23d6b38f7c1e80cfa69;hp=94bcc620bd141b72699a0442deb36bad48232638;hpb=9c8dc43775285c0056ab539a436b013c7933bc76;p=xonotic%2Fgmqcc.git diff --git a/parser.c b/parser.c index 94bcc62..54577ea 100644 --- a/parser.c +++ b/parser.c @@ -167,7 +167,8 @@ static ast_value* parser_const_float(parser_t *parser, double d) size_t i; ast_value *out; for (i = 0; i < vec_size(parser->imm_float); ++i) { - if (parser->imm_float[i]->constval.vfloat == d) + const double compare = parser->imm_float[i]->constval.vfloat; + if (memcmp((const void*)&compare, (const void *)&d, sizeof(double)) == 0) return parser->imm_float[i]; } out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_FLOAT); @@ -412,7 +413,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy) ast_expression *exprs[3]; ast_block *blocks[3]; ast_value *asvalue[3]; - size_t i, assignop; + size_t i, assignop, addop; qcint generated_op = 0; char ty1[1024]; @@ -460,8 +461,6 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy) (ast_istype((A), ast_value) && ((ast_value*)(A))->isconst) #define CanConstFold(A, B) \ (CanConstFold1(A) && CanConstFold1(B)) -#define CanConstFold3(A, B, C) \ - (CanConstFold1(A) && CanConstFold1(B) && CanConstFold1(C)) #define ConstV(i) (asvalue[(i)]->constval.vvec) #define ConstF(i) (asvalue[(i)]->constval.vfloat) #define ConstS(i) (asvalue[(i)]->constval.vstring) @@ -879,14 +878,37 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy) } out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]); break; + case opid3('+','+','P'): + case opid3('-','-','P'): + /* prefix ++ */ + if (exprs[0]->expression.vtype != TYPE_FLOAT) { + ast_type_to_string(exprs[0], ty1, sizeof(ty1)); + parseerror(parser, "invalid type for prefix increment: %s", ty1); + return false; + } + if (op->id == opid3('+','+','P')) + addop = INSTR_ADD_F; + else + addop = INSTR_SUB_F; + if (ast_istype(exprs[0], ast_entfield)) { + out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, + exprs[0], + (ast_expression*)parser_const_float(parser, 1)); + } else { + out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop, + exprs[0], + (ast_expression*)parser_const_float(parser, 1)); + } + break; case opid2('+','='): case opid2('-','='): if (exprs[0]->expression.vtype != exprs[1]->expression.vtype || (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) ) { + ast_type_to_string(exprs[0], ty1, sizeof(ty1)); + ast_type_to_string(exprs[1], ty2, sizeof(ty2)); parseerror(parser, "invalid types used in expression: cannot add or subtract type %s and %s", - type_name[exprs[0]->expression.vtype], - type_name[exprs[1]->expression.vtype]); + ty1, ty2); return false; } if (ast_istype(exprs[0], ast_entfield)) @@ -1413,6 +1435,8 @@ static bool parse_if(parser_t *parser, ast_block *block, ast_expression **out) lex_ctx ctx = parser_ctx(parser); + (void)block; /* not touching */ + /* skip the 'if', parse an optional 'not' and check for an opening paren */ if (!parser_next(parser)) { parseerror(parser, "expected condition or 'not'"); @@ -1487,6 +1511,8 @@ static bool parse_while(parser_t *parser, ast_block *block, ast_expression **out lex_ctx ctx = parser_ctx(parser); + (void)block; /* not touching */ + /* skip the 'while' and check for opening paren */ if (!parser_next(parser) || parser->tok != '(') { parseerror(parser, "expected 'while' condition in parenthesis"); @@ -1531,6 +1557,8 @@ static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **o lex_ctx ctx = parser_ctx(parser); + (void)block; /* not touching */ + /* skip the 'do' and get the body */ if (!parser_next(parser)) { parseerror(parser, "expected loop body"); @@ -1718,6 +1746,8 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou ast_return *ret = NULL; ast_value *expected = parser->function->vtype; + (void)block; /* not touching */ + if (!parser_next(parser)) { parseerror(parser, "expected return expression"); return false; @@ -1756,6 +1786,8 @@ static bool parse_break_continue(parser_t *parser, ast_block *block, ast_express { lex_ctx ctx = parser_ctx(parser); + (void)block; /* not touching */ + if (!parser_next(parser) || parser->tok != ';') { parseerror(parser, "expected semicolon"); return false; @@ -1777,6 +1809,8 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou lex_ctx ctx = parser_ctx(parser); + (void)block; /* not touching */ + /* parse over the opening paren */ if (!parser_next(parser) || parser->tok != '(') { parseerror(parser, "expected switch operand in parenthesis"); @@ -1826,7 +1860,7 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou /* case list! */ while (parser->tok != '}') { - ast_block *block; + ast_block *caseblock; if (parser->tok != TOKEN_KEYWORD) { ast_delete(switchnode); @@ -1869,13 +1903,13 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou parseerror(parser, "expected statements or case"); return false; } - block = ast_block_new(parser_ctx(parser)); - if (!block) { + caseblock = ast_block_new(parser_ctx(parser)); + if (!caseblock) { if (swcase.value) ast_unref(swcase.value); ast_delete(switchnode); return false; } - swcase.code = (ast_expression*)block; + swcase.code = (ast_expression*)caseblock; vec_push(switchnode->cases, swcase); while (true) { ast_expression *expr; @@ -1888,13 +1922,13 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou break; } } - if (!parse_statement(parser, block, &expr, true)) { + if (!parse_statement(parser, caseblock, &expr, true)) { ast_delete(switchnode); return false; } if (!expr) continue; - vec_push(block->exprs, expr); + vec_push(caseblock->exprs, expr); } } @@ -2116,7 +2150,7 @@ static ast_expression* parse_statement_or_block(parser_t *parser) } /* loop method */ -static bool create_vector_members(parser_t *parser, ast_value *var, varentry_t *ve) +static bool create_vector_members(ast_value *var, varentry_t *ve) { size_t i; size_t len = strlen(var->name); @@ -2378,7 +2412,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) continue; } - if (!create_vector_members(parser, param, ve)) { + if (!create_vector_members(param, ve)) { ast_block_delete(block); return false; } @@ -2475,10 +2509,11 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast lex_ctx ctx = ast_ctx(array); if (from+1 == afterend) { - // set this value + /* set this value */ ast_block *block; ast_return *ret; ast_array_index *subscript; + ast_store *st; int assignop = type_store_instr[value->expression.vtype]; if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR) @@ -2488,7 +2523,7 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast if (!subscript) return NULL; - ast_store *st = ast_store_new(ctx, assignop, (ast_expression*)subscript, (ast_expression*)value); + st = ast_store_new(ctx, assignop, (ast_expression*)subscript, (ast_expression*)value); if (!st) { ast_delete(subscript); return NULL; @@ -2533,11 +2568,12 @@ static ast_expression *array_field_setter_node( lex_ctx ctx = ast_ctx(array); if (from+1 == afterend) { - // set this value + /* set this value */ ast_block *block; ast_return *ret; ast_entfield *entfield; ast_array_index *subscript; + ast_store *st; int assignop = type_storep_instr[value->expression.vtype]; if (value->expression.vtype == TYPE_FIELD && value->expression.next->expression.vtype == TYPE_VECTOR) @@ -2556,7 +2592,7 @@ static ast_expression *array_field_setter_node( return NULL; } - ast_store *st = ast_store_new(ctx, assignop, (ast_expression*)entfield, (ast_expression*)value); + st = ast_store_new(ctx, assignop, (ast_expression*)entfield, (ast_expression*)value); if (!st) { ast_delete(entfield); return NULL; @@ -3280,7 +3316,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield isvector = true; if (isvector) { - if (!create_vector_members(parser, var, ve)) { + if (!create_vector_members(var, ve)) { retval = false; goto cleanup; } @@ -3581,6 +3617,79 @@ static bool parser_global_statement(parser_t *parser) return true; } +static uint16_t progdefs_crc_sum(uint16_t old, const char *str) +{ + return util_crc16(old, str, strlen(str)); +} + +static void progdefs_crc_file(const char *str) +{ + /* write to progdefs.h here */ + (void)str; +} + +static uint16_t progdefs_crc_both(uint16_t old, const char *str) +{ + old = progdefs_crc_sum(old, str); + progdefs_crc_file(str); + return old; +} + +static void generate_checksum(parser_t *parser) +{ + uint16_t crc = 0xFFFF; + size_t i; + + crc = progdefs_crc_both(crc, "\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{"); + crc = progdefs_crc_sum(crc, "\tint\tpad[28];\n"); + /* + progdefs_crc_file("\tint\tpad;\n"); + progdefs_crc_file("\tint\tofs_return[3];\n"); + progdefs_crc_file("\tint\tofs_parm0[3];\n"); + progdefs_crc_file("\tint\tofs_parm1[3];\n"); + progdefs_crc_file("\tint\tofs_parm2[3];\n"); + progdefs_crc_file("\tint\tofs_parm3[3];\n"); + progdefs_crc_file("\tint\tofs_parm4[3];\n"); + progdefs_crc_file("\tint\tofs_parm5[3];\n"); + progdefs_crc_file("\tint\tofs_parm6[3];\n"); + progdefs_crc_file("\tint\tofs_parm7[3];\n"); + */ + for (i = 0; i < parser->crc_globals; ++i) { + if (!ast_istype(parser->globals[i].var, ast_value)) + continue; + switch (parser->globals[i].var->expression.vtype) { + case TYPE_FLOAT: crc = progdefs_crc_both(crc, "\tfloat\t"); break; + case TYPE_VECTOR: crc = progdefs_crc_both(crc, "\tvec3_t\t"); break; + case TYPE_STRING: crc = progdefs_crc_both(crc, "\tstring_t\t"); break; + case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break; + default: + crc = progdefs_crc_both(crc, "\tint\t"); + break; + } + crc = progdefs_crc_both(crc, parser->globals[i].name); + crc = progdefs_crc_both(crc, ";\n"); + } + crc = progdefs_crc_both(crc, "} globalvars_t;\n\ntypedef struct\n{\n"); + for (i = 0; i < parser->crc_fields; ++i) { + if (!ast_istype(parser->fields[i].var, ast_value)) + continue; + switch (parser->fields[i].var->expression.next->expression.vtype) { + case TYPE_FLOAT: crc = progdefs_crc_both(crc, "\tfloat\t"); break; + case TYPE_VECTOR: crc = progdefs_crc_both(crc, "\tvec3_t\t"); break; + case TYPE_STRING: crc = progdefs_crc_both(crc, "\tstring_t\t"); break; + case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break; + default: + crc = progdefs_crc_both(crc, "\tint\t"); + break; + } + crc = progdefs_crc_both(crc, parser->fields[i].name); + crc = progdefs_crc_both(crc, ";\n"); + } + crc = progdefs_crc_both(crc, "} entvars_t;\n\n"); + + code_crc = crc; +} + static parser_t *parser; bool parser_init() @@ -3708,78 +3817,6 @@ void parser_cleanup() mem_d(parser); } -static uint16_t progdefs_crc_sum(uint16_t old, const char *str) -{ - return util_crc16(old, str, strlen(str)); -} - -static void progdefs_crc_file(const char *str) -{ - /* write to progdefs.h here */ -} - -static uint16_t progdefs_crc_both(uint16_t old, const char *str) -{ - old = progdefs_crc_sum(old, str); - progdefs_crc_file(str); - return old; -} - -static void generate_checksum(parser_t *parser) -{ - uint16_t crc = 0xFFFF; - size_t i; - - crc = progdefs_crc_both(crc, "\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{"); - crc = progdefs_crc_sum(crc, "\tint\tpad[28];\n"); - /* - progdefs_crc_file("\tint\tpad;\n"); - progdefs_crc_file("\tint\tofs_return[3];\n"); - progdefs_crc_file("\tint\tofs_parm0[3];\n"); - progdefs_crc_file("\tint\tofs_parm1[3];\n"); - progdefs_crc_file("\tint\tofs_parm2[3];\n"); - progdefs_crc_file("\tint\tofs_parm3[3];\n"); - progdefs_crc_file("\tint\tofs_parm4[3];\n"); - progdefs_crc_file("\tint\tofs_parm5[3];\n"); - progdefs_crc_file("\tint\tofs_parm6[3];\n"); - progdefs_crc_file("\tint\tofs_parm7[3];\n"); - */ - for (i = 0; i < parser->crc_globals; ++i) { - if (!ast_istype(parser->globals[i].var, ast_value)) - continue; - switch (parser->globals[i].var->expression.vtype) { - case TYPE_FLOAT: crc = progdefs_crc_both(crc, "\tfloat\t"); break; - case TYPE_VECTOR: crc = progdefs_crc_both(crc, "\tvec3_t\t"); break; - case TYPE_STRING: crc = progdefs_crc_both(crc, "\tstring_t\t"); break; - case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break; - default: - crc = progdefs_crc_both(crc, "\tint\t"); - break; - } - crc = progdefs_crc_both(crc, parser->globals[i].name); - crc = progdefs_crc_both(crc, ";\n"); - } - crc = progdefs_crc_both(crc, "} globalvars_t;\n\ntypedef struct\n{\n"); - for (i = 0; i < parser->crc_fields; ++i) { - if (!ast_istype(parser->fields[i].var, ast_value)) - continue; - switch (parser->fields[i].var->expression.next->expression.vtype) { - case TYPE_FLOAT: crc = progdefs_crc_both(crc, "\tfloat\t"); break; - case TYPE_VECTOR: crc = progdefs_crc_both(crc, "\tvec3_t\t"); break; - case TYPE_STRING: crc = progdefs_crc_both(crc, "\tstring_t\t"); break; - case TYPE_FUNCTION: crc = progdefs_crc_both(crc, "\tfunc_t\t"); break; - default: - crc = progdefs_crc_both(crc, "\tint\t"); - break; - } - crc = progdefs_crc_both(crc, parser->fields[i].name); - crc = progdefs_crc_both(crc, ";\n"); - } - crc = progdefs_crc_both(crc, "} entvars_t;\n\n"); - - code_crc = crc; -} - bool parser_finish(const char *output) { size_t i; @@ -3921,6 +3958,10 @@ bool parser_finish(const char *output) ir_builder_delete(ir); return false; } + } + if (opts_dump) + ir_builder_dump(ir, con_out); + for (i = 0; i < vec_size(parser->functions); ++i) { if (!ir_function_finalize(parser->functions[i]->ir_func)) { con_out("failed to finalize function %s\n", parser->functions[i]->name); ir_builder_delete(ir); @@ -3929,7 +3970,7 @@ bool parser_finish(const char *output) } if (retval) { - if (opts_dump) + if (opts_dumpfin) ir_builder_dump(ir, con_out); generate_checksum(parser);