X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=parser.c;h=354ad0355e7912cd9755fc900d00b32b817ef51c;hb=bbeb2517c0bdf7477124f9a3acda0213ebe36529;hp=6af6e5e996e6cc41effe4effd818579ef7044171;hpb=0b6637cc67dad84b3e0f357c994ef625528b3e1f;p=xonotic%2Fgmqcc.git diff --git a/parser.c b/parser.c index 6af6e5e..354ad03 100644 --- a/parser.c +++ b/parser.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 + * Copyright (C) 2012, 2013, 2014 * Wolfgang Bumiller * Dale Weiler * @@ -1293,7 +1293,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) if ((fun->flags & AST_FLAG_VARIADIC) && !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin)) { - call->va_count = (ast_expression*)fold_constgen_float(parser->fold, (qcfloat_t)paramcount); + call->va_count = (ast_expression*)fold_constgen_float(parser->fold, (qcfloat_t)paramcount, false); } } @@ -1548,14 +1548,14 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) return true; } else if (parser->tok == TOKEN_FLOATCONST) { - ast_expression *val = fold_constgen_float(parser->fold, (parser_token(parser)->constval.f)); + ast_expression *val = fold_constgen_float(parser->fold, (parser_token(parser)->constval.f), false); if (!val) return false; vec_push(sy->out, syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_INTCONST || parser->tok == TOKEN_CHARCONST) { - ast_expression *val = fold_constgen_float(parser->fold, (qcfloat_t)(parser_token(parser)->constval.i)); + ast_expression *val = fold_constgen_float(parser->fold, (qcfloat_t)(parser_token(parser)->constval.i), false); if (!val) return false; vec_push(sy->out, syexp(parser_ctx(parser), val)); @@ -2822,7 +2822,7 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool * { "inline", AST_FLAG_INLINE }, { "eraseable", AST_FLAG_ERASEABLE }, { "accumulate", AST_FLAG_ACCUMULATE }, - { "definite", AST_FLAG_FINAL_DECL } + { "last", AST_FLAG_FINAL_DECL } }; *cvq = CV_NONE; @@ -2944,6 +2944,47 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool * return false; } } + else if (!strcmp(parser_tokval(parser), "coverage") && !(flags & AST_FLAG_COVERAGE)) { + flags |= AST_FLAG_COVERAGE; + if (!parser_next(parser)) { + error_in_coverage: + parseerror(parser, "parse error in coverage attribute"); + *cvq = CV_WRONG; + return false; + } + if (parser->tok == '(') { + if (!parser_next(parser)) { + bad_coverage_arg: + parseerror(parser, "invalid parameter for coverage() attribute\n" + "valid are: block"); + *cvq = CV_WRONG; + return false; + } + if (parser->tok != ')') { + do { + if (parser->tok != TOKEN_IDENT) + goto bad_coverage_arg; + if (!strcmp(parser_tokval(parser), "block")) + flags |= AST_FLAG_BLOCK_COVERAGE; + else if (!strcmp(parser_tokval(parser), "none")) + flags &= ~(AST_FLAG_COVERAGE_MASK); + else + goto bad_coverage_arg; + if (!parser_next(parser)) + goto error_in_coverage; + if (parser->tok == ',') { + if (!parser_next(parser)) + goto error_in_coverage; + } + } while (parser->tok != ')'); + } + if (parser->tok != ')' || !parser_next(parser)) + goto error_in_coverage; + } else { + /* without parameter [[coverage]] equals [[coverage(block)]] */ + flags |= AST_FLAG_BLOCK_COVERAGE; + } + } else { /* Skip tokens until we hit a ]] */ @@ -3989,7 +4030,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) self_think = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_think); time_plus_1 = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, - gbl_time, (ast_expression*)fold_constgen_float(parser->fold, 0.1f)); + gbl_time, (ast_expression*)fold_constgen_float(parser->fold, 0.1f, false)); if (!self_frame || !self_nextthink || !self_think || !time_plus_1) { if (self_frame) ast_delete(self_frame); @@ -4114,7 +4155,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) goto enderrfn; } func->varargs = varargs; - func->fixedparams = (ast_value*)fold_constgen_float(parser->fold, vec_size(var->expression.params)); + func->fixedparams = (ast_value*)fold_constgen_float(parser->fold, vec_size(var->expression.params), false); } parser->function = func; @@ -4172,7 +4213,7 @@ static ast_expression *array_accessor_split( cmp = ast_binary_new(ctx, INSTR_LT, (ast_expression*)index, - (ast_expression*)fold_constgen_float(parser->fold, middle)); + (ast_expression*)fold_constgen_float(parser->fold, middle, false)); if (!cmp) { ast_delete(left); ast_delete(right); @@ -4205,7 +4246,7 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) assignop = INSTR_STORE_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from, false)); if (!subscript) return NULL; @@ -4271,7 +4312,7 @@ static ast_expression *array_field_setter_node( if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) assignop = INSTR_STOREP_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from, false)); if (!subscript) return NULL; @@ -4334,7 +4375,7 @@ static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast ast_return *ret; ast_array_index *subscript; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from, false)); if (!subscript) return NULL; @@ -4366,6 +4407,7 @@ static bool parser_create_array_accessor(parser_t *parser, ast_value *array, con parseerror(parser, "failed to create accessor function value"); return false; } + fval->expression.flags &= ~(AST_FLAG_COVERAGE_MASK); func = ast_function_new(ast_ctx(array), funcname, fval); if (!func) { @@ -5163,6 +5205,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } var->cvq = qualifier; + if (qflags & AST_FLAG_COVERAGE) /* specified in QC, drop our default */ + var->expression.flags &= ~(AST_FLAG_COVERAGE_MASK); var->expression.flags |= qflags; /* @@ -6201,11 +6245,51 @@ void parser_cleanup(parser_t *parser) mem_d(parser); } +static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) { + size_t i; + ast_expression *expr; + ast_value *cov; + ast_function *func; + + if (!OPTS_OPTION_BOOL(OPTION_COVERAGE)) + return true; + + func = NULL; + for (i = 0; i != vec_size(parser->functions); ++i) { + if (!strcmp(parser->functions[i]->name, "coverage")) { + func = parser->functions[i]; + break; + } + } + if (!func) { + if (OPTS_OPTION_BOOL(OPTION_COVERAGE)) { + con_out("coverage support requested but no coverage() builtin declared\n"); + ir_builder_delete(ir); + return false; + } + return true; + } + + cov = func->vtype; + expr = (ast_expression*)cov; + + if (expr->vtype != TYPE_FUNCTION || vec_size(expr->params) != 0) { + char ty[1024]; + ast_type_to_string(expr, ty, sizeof(ty)); + con_out("invalid type for coverage(): %s\n", ty); + ir_builder_delete(ir); + return false; + } + + ir->coverage_func = func->ir_func->value; + return true; +} + bool parser_finish(parser_t *parser, const char *output) { - size_t i; - ir_builder *ir; - bool retval = true; + size_t i; + ir_builder *ir; + bool retval = true; if (compile_errors) { con_out("*** there were compile errors\n"); @@ -6287,6 +6371,10 @@ bool parser_finish(parser_t *parser, const char *output) if (!fold_generate(parser->fold, ir)) return false; + /* before generating any functions we need to set the coverage_func */ + if (!parser_set_coverage_func(parser, ir)) + return false; + for (i = 0; i < vec_size(parser->globals); ++i) { ast_value *asvalue; if (!ast_istype(parser->globals[i], ast_value))