X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=ast.c;h=66b78ebd1440d04ec27243268592d9c692711413;hb=12a864abf5a5cc79f0a8f11535c26bb2009c0ad9;hp=3531adadf15ee1c03fda93efd719fc960d229915;hpb=4600f1d7ff8d712ff8b70d5ee1c3a5f1bf303283;p=xonotic%2Fgmqcc.git diff --git a/ast.c b/ast.c index 3531ada..66b78eb 100644 --- a/ast.c +++ b/ast.c @@ -27,6 +27,7 @@ #include "gmqcc.h" #include "ast.h" #include "parser.h" +#include "platform.h" #define ast_instantiate(T, ctx, destroyfn) \ T* self = (T*)mem_a(sizeof(T)); \ @@ -259,7 +260,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi if (!e) { if (pos + 6 >= bufsize) goto full; - util_strncpy(buf + pos, "(null)", 6); + platform_strncpy(buf + pos, "(null)", 6); return pos + 6; } @@ -268,7 +269,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi switch (e->vtype) { case TYPE_VARIANT: - util_strncpy(buf + pos, "(variant)", 9); + platform_strncpy(buf + pos, "(variant)", 9); return pos + 9; case TYPE_FIELD: @@ -314,7 +315,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi if (pos + 1 >= bufsize) goto full; buf[pos++] = '['; - pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count); + pos += platform_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count); if (pos + 1 >= bufsize) goto full; buf[pos++] = ']'; @@ -325,7 +326,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi typelen = strlen(typestr); if (pos + typelen >= bufsize) goto full; - util_strncpy(buf + pos, typestr, typelen); + platform_strncpy(buf + pos, typestr, typelen); return pos + typelen; } @@ -438,6 +439,7 @@ bool ast_value_set_name(ast_value *self, const char *name) ast_binary* ast_binary_new(lex_ctx_t ctx, int op, ast_expression* left, ast_expression* right) { + ast_binary *fold; ast_instantiate(ast_binary, ctx, ast_binary_delete); ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binary_codegen); @@ -449,6 +451,11 @@ ast_binary* ast_binary_new(lex_ctx_t ctx, int op, ast_propagate_effects(self, left); ast_propagate_effects(self, right); + if (OPTS_OPTIMIZATION(OPTIM_PEEPHOLE) && (fold = (ast_binary*)fold_superfluous(left, right, op))) { + ast_binary_delete(self); + return fold; + } + if (op >= INSTR_EQ_F && op <= INSTR_GT) self->expression.vtype = TYPE_FLOAT; else if (op == INSTR_AND || op == INSTR_OR) { @@ -515,15 +522,36 @@ ast_unary* ast_unary_new(lex_ctx_t ctx, int op, ast_instantiate(ast_unary, ctx, ast_unary_delete); ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_unary_codegen); - self->op = op; + self->op = op; self->operand = expr; + + if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { + ast_unary *prev = (ast_unary*)((ast_unary*)expr)->operand; + + /* Handle for double negation */ + if ((((ast_unary*)expr)->op == VINSTR_NEG_V && op == VINSTR_NEG_V) || + (((ast_unary*)expr)->op == VINSTR_NEG_F && op == VINSTR_NEG_F)) { + prev = (ast_unary*)((ast_unary*)expr)->operand; + } + + if (ast_istype(prev, ast_unary)) { + ast_expression_delete((ast_expression*)self); + mem_d(self); + ++opts_optimizationcount[OPTIM_PEEPHOLE]; + return prev; + } + } + ast_propagate_effects(self, expr); - if (op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) { + if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) { self->expression.vtype = TYPE_FLOAT; - } else + } else if (op == VINSTR_NEG_V) { + self->expression.vtype = TYPE_VECTOR; + } else { compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]); + } return self; } @@ -1436,12 +1464,12 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + platform_strncpy(name, self->name, namelen); array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->expression.count); array->ir_values[0] = v; for (ai = 1; ai < array->expression.count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); + platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); array->ir_values[ai] = ir_builder_create_field(ir, name, vtype); if (!array->ir_values[ai]) { mem_d(name); @@ -1505,12 +1533,12 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + platform_strncpy(name, self->name, namelen); self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count); self->ir_values[0] = v; for (ai = 1; ai < self->expression.count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); + platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); self->ir_values[ai] = ir_builder_create_global(ir, name, vtype); if (!self->ir_values[ai]) { mem_d(name); @@ -1650,11 +1678,11 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + platform_strncpy(name, self->name, namelen); self->ir_values[0] = v; for (ai = 1; ai < self->expression.count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); + platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); self->ir_values[ai] = ir_function_create_local(func, name, vtype, param); if (!self->ir_values[ai]) { compile_error(ast_ctx(self), "internal_error: ir_builder_create_global failed on `%s`", name); @@ -2582,8 +2610,8 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va /* update the block which will get the jump - because short-logic or ternaries may have changed this */ cond = func->curblock; - /* try constant folding away the if */ - if ((fold = fold_cond(condval, func, self)) != -1) + /* try constant folding away the condition */ + if ((fold = fold_cond_ifthen(condval, func, self)) != -1) return fold; if (self->on_true) { @@ -2666,6 +2694,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ ir_block *ontrue, *ontrue_out = NULL; ir_block *onfalse, *onfalse_out = NULL; ir_block *merge; + int fold = 0; /* Ternary can never create an lvalue... */ if (lvalue) @@ -2690,6 +2719,10 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ return false; cond_out = func->curblock; + /* try constant folding away the condition */ + if ((fold = fold_cond_ternary(condval, func, self)) != -1) + return fold; + /* create on-true block */ ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_T")); if (!ontrue)