X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=ast.cpp;h=7b444f8a402dfdf18efaab0ae3d171c1174972ae;hp=58ed6603b881be4b3c635eac09c31ab3daa1d980;hb=092067482fddeccf1b3e42ff09a046f6555cd11e;hpb=d8e9b1b35d50a9e1ddfe6fa277f2b84e611ee41b diff --git a/ast.cpp b/ast.cpp index 58ed660..7b444f8 100644 --- a/ast.cpp +++ b/ast.cpp @@ -24,9 +24,10 @@ ast_node::~ast_node() } /* weight and side effects */ -void ast_node::propagateSideEffects(ast_node *other) const +void ast_node::propagateSideEffects(const ast_node *other) { - other->m_side_effects = m_side_effects; + if (other->m_side_effects) + m_side_effects = true; } /* General expression initialization */ @@ -36,6 +37,8 @@ ast_expression::ast_expression(lex_ctx_t ctx, int nodetype, qc_type type) { if (OPTS_OPTION_BOOL(OPTION_COVERAGE)) m_flags |= AST_FLAG_BLOCK_COVERAGE; + if (OPTS_FLAG(DEFAULT_ERASEABLE)) + m_flags |= AST_FLAG_ERASEABLE; } ast_expression::ast_expression(lex_ctx_t ctx, int nodetype) : ast_expression(ctx, nodetype, TYPE_VOID) @@ -364,16 +367,20 @@ ast_binstore::~ast_binstore() ast_unary* ast_unary::make(lex_ctx_t ctx, int op, ast_expression *expr) { - if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { - ast_unary *prev = (ast_unary*)((ast_unary*)expr)->m_operand; - - /* Handle for double negation */ - if (((ast_unary*)expr)->m_op == op) - prev = (ast_unary*)((ast_unary*)expr)->m_operand; - - if (ast_istype(prev, ast_unary)) { - ++opts_optimizationcount[OPTIM_PEEPHOLE]; - return prev; + // handle double negation, double bitwise or logical not + if (op == opid2('!','P') || + op == opid2('~','P') || + op == opid2('-','P')) + { + if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { + ast_unary *unary = reinterpret_cast(expr); + if (unary->m_op == op) { + auto out = reinterpret_cast(unary->m_operand); + unary->m_operand = nullptr; + delete unary; + ++opts_optimizationcount[OPTIM_PEEPHOLE]; + return out; + } } } @@ -1036,15 +1043,15 @@ bool ast_value::setGlobalArray() for (i = 0; i != count; ++i) { switch (m_next->m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(m_ir_values[i], m_initlist[i].vfloat)) + if (!m_ir_values[i]->setFloat(m_initlist[i].vfloat)) return false; break; case TYPE_VECTOR: - if (!ir_value_set_vector(m_ir_values[i], m_initlist[i].vvec)) + if (!m_ir_values[i]->setVector(m_initlist[i].vvec)) return false; break; case TYPE_STRING: - if (!ir_value_set_string(m_ir_values[i], m_initlist[i].vstring)) + if (!m_ir_values[i]->setString(m_initlist[i].vstring)) return false; break; case TYPE_ARRAY: @@ -1064,7 +1071,7 @@ bool ast_value::setGlobalArray() compile_error(m_context, "field constant generated before its field"); return false; } - if (!ir_value_set_field(m_ir_values[i], m_initlist[i].vfield->m_ir_v)) + if (!m_ir_values[i]->setField(m_initlist[i].vfield->m_ir_v)) return false; break; default: @@ -1110,9 +1117,9 @@ bool ast_value::generateGlobal(ir_builder *ir, bool isfield) } else { // Arrays don't do this since there's no "array" value which spans across the // whole thing. - v = ir_builder_create_global(ir, m_name, m_vtype); + v = ir->createGlobal(m_name, m_vtype); if (!v) { - compile_error(m_context, "ir_builder_create_global failed on `%s`", m_name); + compile_error(m_context, "ir_builder::createGlobal failed on `%s`", m_name); return false; } codegen_output_type(this, v); @@ -1125,23 +1132,25 @@ bool ast_value::generateGlobal(ir_builder *ir, bool isfield) if (m_flags & AST_FLAG_INCLUDE_DEF) m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (m_flags & AST_FLAG_ERASEABLE) + if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE)) m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (m_flags & AST_FLAG_NOREF) + m_ir_v->m_flags |= IR_FLAG_NOREF; /* initialize */ if (m_hasvalue) { switch (m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(v, m_constval.vfloat)) + if (!v->setFloat(m_constval.vfloat)) return false; break; case TYPE_VECTOR: - if (!ir_value_set_vector(v, m_constval.vvec)) + if (!v->setVector(m_constval.vvec)) return false; break; case TYPE_STRING: - if (!ir_value_set_string(v, m_constval.vstring)) + if (!v->setString(m_constval.vstring)) return false; break; case TYPE_ARRAY: @@ -1163,7 +1172,7 @@ bool ast_value::generateGlobal(ir_builder *ir, bool isfield) compile_error(m_context, "field constant generated before its field"); return false; } - if (!ir_value_set_field(v, m_constval.vfield->m_ir_v)) + if (!v->setField(m_constval.vfield->m_ir_v)) return false; break; default: @@ -1177,7 +1186,7 @@ bool ast_value::generateGlobal(ir_builder *ir, bool isfield) bool ast_value::generateGlobalFunction(ir_builder *ir) { - ir_function *func = ir_builder_create_function(ir, m_name, m_next->m_vtype); + ir_function *func = ir->createFunction(m_name, m_next->m_vtype); if (!func) return false; func->m_context = m_context; @@ -1187,7 +1196,7 @@ bool ast_value::generateGlobalFunction(ir_builder *ir) m_ir_v = func->m_value; if (m_flags & AST_FLAG_INCLUDE_DEF) m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (m_flags & AST_FLAG_ERASEABLE) + if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE)) m_ir_v->m_flags |= IR_FLAG_ERASABLE; if (m_flags & AST_FLAG_BLOCK_COVERAGE) func->m_flags |= IR_FLAG_BLOCK_COVERAGE; @@ -1217,9 +1226,9 @@ bool ast_value::generateGlobalField(ir_builder *ir) ast_expression *elemtype = array->m_next; qc_type vtype = elemtype->m_vtype; - ir_value *v = ir_builder_create_field(ir, m_name, vtype); + ir_value *v = ir->createField(m_name, vtype); if (!v) { - compile_error(m_context, "ir_builder_create_global failed on `%s`", m_name); + compile_error(m_context, "ir_builder::createGlobal failed on `%s`", m_name); return false; } v->m_context = m_context; @@ -1229,8 +1238,10 @@ bool ast_value::generateGlobalField(ir_builder *ir) if (m_flags & AST_FLAG_INCLUDE_DEF) m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (m_flags & AST_FLAG_ERASEABLE) + if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE)) m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (m_flags & AST_FLAG_NOREF) + m_ir_v->m_flags |= IR_FLAG_NOREF; const size_t namelen = m_name.length(); std::unique_ptr name(new char[namelen+16]); @@ -1240,30 +1251,33 @@ bool ast_value::generateGlobalField(ir_builder *ir) array->m_ir_values[0] = v; for (size_t ai = 1; ai < array->m_count; ++ai) { util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai); - array->m_ir_values[ai] = ir_builder_create_field(ir, name.get(), vtype); + array->m_ir_values[ai] = ir->createField(name.get(), vtype); if (!array->m_ir_values[ai]) { - compile_error(m_context, "ir_builder_create_global failed on `%s`", name.get()); + compile_error(m_context, "ir_builder::createGlobal failed on `%s`", name.get()); return false; } array->m_ir_values[ai]->m_context = m_context; array->m_ir_values[ai]->m_unique_life = true; array->m_ir_values[ai]->m_locked = true; if (m_flags & AST_FLAG_INCLUDE_DEF) - m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; + array->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; + if (m_flags & AST_FLAG_NOREF) + array->m_ir_values[ai]->m_flags |= IR_FLAG_NOREF; } } else { - ir_value *v = ir_builder_create_field(ir, m_name, m_next->m_vtype); + ir_value *v = ir->createField(m_name, m_next->m_vtype); if (!v) return false; v->m_context = m_context; m_ir_v = v; if (m_flags & AST_FLAG_INCLUDE_DEF) m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - - if (m_flags & AST_FLAG_ERASEABLE) + if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE)) m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (m_flags & AST_FLAG_NOREF) + m_ir_v->m_flags |= IR_FLAG_NOREF; } return true; } @@ -1282,9 +1296,9 @@ ir_value *ast_value::prepareGlobalArray(ir_builder *ir) if (!checkArray(*this)) return nullptr; - ir_value *v = ir_builder_create_global(ir, m_name, vtype); + ir_value *v = ir->createGlobal(m_name, vtype); if (!v) { - compile_error(m_context, "ir_builder_create_global failed `%s`", m_name); + compile_error(m_context, "ir_builder::createGlobal failed `%s`", m_name); return nullptr; } v->m_context = m_context; @@ -1293,8 +1307,10 @@ ir_value *ast_value::prepareGlobalArray(ir_builder *ir) if (m_flags & AST_FLAG_INCLUDE_DEF) v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (m_flags & AST_FLAG_ERASEABLE) - m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE)) + v->m_flags |= IR_FLAG_ERASABLE; + if (m_flags & AST_FLAG_NOREF) + v->m_flags |= IR_FLAG_NOREF; const size_t namelen = m_name.length(); std::unique_ptr name(new char[namelen+16]); @@ -1304,9 +1320,9 @@ ir_value *ast_value::prepareGlobalArray(ir_builder *ir) m_ir_values[0] = v; for (size_t ai = 1; ai < m_count; ++ai) { util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai); - m_ir_values[ai] = ir_builder_create_global(ir, name.get(), vtype); + m_ir_values[ai] = ir->createGlobal(name.get(), vtype); if (!m_ir_values[ai]) { - compile_error(m_context, "ir_builder_create_global failed `%s`", name.get()); + compile_error(m_context, "ir_builder::createGlobal failed `%s`", name.get()); return nullptr; } m_ir_values[ai]->m_context = m_context; @@ -1314,6 +1330,8 @@ ir_value *ast_value::prepareGlobalArray(ir_builder *ir) m_ir_values[ai]->m_locked = true; if (m_flags & AST_FLAG_INCLUDE_DEF) m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; + if (m_flags & AST_FLAG_NOREF) + m_ir_values[ai]->m_flags |= IR_FLAG_NOREF; } return v; @@ -1360,6 +1378,9 @@ bool ast_value::generateLocal(ir_function *func, bool param) v->m_unique_life = true; v->m_locked = true; + if (m_flags & AST_FLAG_NOREF) + v->m_flags |= IR_FLAG_NOREF; + const size_t namelen = m_name.length(); std::unique_ptr name(new char[namelen+16]); util_strncpy(name.get(), m_name.c_str(), namelen); @@ -1369,12 +1390,15 @@ bool ast_value::generateLocal(ir_function *func, bool param) util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai); m_ir_values[ai] = ir_function_create_local(func, name.get(), vtype, param); if (!m_ir_values[ai]) { - compile_error(m_context, "internal_error: ir_builder_create_global failed on `%s`", name.get()); + compile_error(m_context, "internal_error: ir_builder::createGlobal failed on `%s`", name.get()); return false; } m_ir_values[ai]->m_context = m_context; m_ir_values[ai]->m_unique_life = true; - m_ir_values[ai]->m_locked = true; + m_ir_values[ai]->m_locked = true; + + if (m_flags & AST_FLAG_NOREF) + m_ir_values[ai]->m_flags |= IR_FLAG_NOREF; } } else @@ -1392,15 +1416,15 @@ bool ast_value::generateLocal(ir_function *func, bool param) switch (m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(v, m_constval.vfloat)) + if (!v->setFloat(m_constval.vfloat)) goto error; break; case TYPE_VECTOR: - if (!ir_value_set_vector(v, m_constval.vvec)) + if (!v->setVector(m_constval.vvec)) goto error; break; case TYPE_STRING: - if (!ir_value_set_string(v, m_constval.vstring)) + if (!v->setString(m_constval.vstring)) goto error; break; default: @@ -1413,6 +1437,9 @@ bool ast_value::generateLocal(ir_function *func, bool param) v->m_cvq = m_cvq; m_ir_v = v; + if (m_flags & AST_FLAG_NOREF) + m_ir_v->m_flags |= IR_FLAG_NOREF; + if (!generateAccessors(func->m_owner)) return false; return true; @@ -1485,9 +1512,9 @@ bool ast_function::generateFunction(ir_builder *ir) /* fill the parameter list */ for (auto &it : m_function_type->m_type_params) { if (it->m_vtype == TYPE_FIELD) - vec_push(irf->m_params, it->m_next->m_vtype); + irf->m_params.push_back(it->m_next->m_vtype); else - vec_push(irf->m_params, it->m_vtype); + irf->m_params.push_back(it->m_vtype); if (!m_builtin) { if (!it->generateLocal(m_ir_func, true)) return false; @@ -1534,7 +1561,7 @@ bool ast_function::generateFunction(ir_builder *ir) return false; sub = ir_block_create_binop(m_curblock, m_context, makeLabel("va_count"), INSTR_SUB_F, - ir_builder_get_va_count(ir), fixed); + ir->get_va_count(), fixed); if (!sub) return false; if (!ir_block_create_store_op(m_curblock, m_context, INSTR_STORE_F, @@ -1557,7 +1584,7 @@ bool ast_function::generateFunction(ir_builder *ir) { return ir_block_create_return(m_curblock, m_context, nullptr); } - else if (vec_size(m_curblock->m_entries) || m_curblock == irf->m_first) + else if (m_curblock->m_entries.size() || m_curblock == irf->m_first) { if (m_return_value) { if (!m_return_value->codegen(this, false, &dummy)) @@ -1779,7 +1806,7 @@ bool ast_binary::codegen(ast_function *func, bool lvalue, ir_value **out) return false; } /* use the likely flag */ - vec_last(func->m_curblock->m_instr)->m_likely = true; + func->m_curblock->m_instr.back()->m_likely = true; /* enter the right-expression's block */ func->m_curblock = other; @@ -1907,6 +1934,7 @@ bool ast_binstore::codegen(ast_function *func, bool lvalue, ir_value **out) if (!idx->codegen(func, false, &iridx)) return false; } + if (!m_dest->codegen(func, false, &leftr)) return false; @@ -2093,22 +2121,63 @@ bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out) compile_error(m_context, "not an l-value (member access)"); return false; } - if (m_outl) { + if (lvalue && m_outl) { *out = m_outl; return true; } + if (!lvalue && m_outr) { + *out = m_outr; + return true; + } - if (!m_owner->codegen(func, false, &vec)) + if (ast_istype(m_owner, ast_entfield)) { + ir_value *ent, *field; + auto entfield = reinterpret_cast(m_owner); + if (!entfield->m_entity->codegen(func, false, &ent)) + return false; + if (!entfield->m_field->codegen(func, false, &vec)) + return false; + field = vec->vectorMember(m_field); + if (lvalue) { + *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("mefa"), + ent, field); + } else { + *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("mefv"), + ent, field, m_vtype); + } + if (!*out) { + compile_error(m_context, "failed to create %s instruction (output type %s)", + (lvalue ? "ADDRESS" : "FIELD"), + type_name[m_vtype]); + return false; + } + if (lvalue) + m_outl = *out; + else + m_outr = *out; + return (*out != nullptr); + } + + // Vector member access + if (!m_owner->codegen(func, lvalue, &vec)) return false; if (vec->m_vtype != TYPE_VECTOR && !(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR)) { + compile_error(m_context, "vector member produced neither vector nor field"); return false; } - *out = ir_value_vector_member(vec, m_field); - m_outl = *out; + *out = vec->vectorMember(m_field); + if (!*out) { + compile_error(m_context, "internal error: failed to create vector member access"); + return false; + } + if (lvalue) + m_outl = *out; + else + m_outr = *out; return (*out != nullptr); } @@ -3022,7 +3091,7 @@ bool ast_call::codegen(ast_function *func, bool lvalue, ir_value **out) if (!m_va_count->codegen(func, false, &va_count)) return false; if (!ir_block_create_store_op(func->m_curblock, m_context, INSTR_STORE_F, - ir_builder_get_va_count(builder), va_count)) + builder->get_va_count(), va_count)) { return false; }