From: Dale Weiler Date: Fri, 30 Jan 2015 05:20:41 +0000 (-0500) Subject: Merge branch 'cleanup' of github.com:graphitemaster/gmqcc into cleanup X-Git-Tag: xonotic-v0.8.2~9^2~1 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=commitdiff_plain;h=90b5a6538a10f60d08ee3059b8f70e4e076dc30d;hp=866fc3e24769ba8268de06ee5e28fc634612449f Merge branch 'cleanup' of github.com:graphitemaster/gmqcc into cleanup --- diff --git a/algo.h b/algo.h new file mode 100644 index 0000000..3218b1b --- /dev/null +++ b/algo.h @@ -0,0 +1,18 @@ +#ifndef GMQCC_ALGO_HDR +#define GMQCC_ALGO_HDR + +namespace algo { + +template +void shiftback(ITER element, ITER end) { + //typename ITER::value_type backup(move(*element)); // hold the element + typename std::remove_reference::type backup(move(*element)); // hold the element + ITER p = element++; + for (; element != end; p = element++) + *p = move(*element); + *p = move(backup); +} + +} // ::algo + +#endif diff --git a/ast.cpp b/ast.cpp index 4768e6e..df2d676 100644 --- a/ast.cpp +++ b/ast.cpp @@ -8,14 +8,13 @@ #include "fold.h" //#include "parser.h" -#define ast_instantiate(T, ctx, destroyfn) \ - T* self = (T*)mem_a(sizeof(T)); \ - if (!self) { \ - return nullptr; \ - } \ - new (self) T(); \ - ast_node_init((ast_node*)self, ctx, TYPE_##T); \ - ( (ast_node*)self )->destroy = (ast_node_delete*)destroyfn +#include "algo.h" + +#define ast_instantiate(T, ctx, destroyfn) \ + T* self = new T; \ + if (!self) return nullptr; \ + ast_node_init(self, ctx, TYPE_##T); \ + self->m_destroy = (ast_node_delete*)destroyfn /* * forward declarations, these need not be in ast.h for obvious @@ -58,176 +57,162 @@ static void ast_binary_delete(ast_binary*); static bool ast_binary_codegen(ast_binary*, ast_function*, bool lvalue, ir_value**); static bool ast_state_codegen(ast_state*, ast_function*, bool lvalue, ir_value**); -/* It must not be possible to get here. */ -static GMQCC_NORETURN void _ast_node_destroy(ast_node *self) +/* Initialize main ast node aprts */ +ast_node::ast_node(lex_ctx_t ctx, int node_type) + : m_context(ctx) + , m_node_type(node_type) + , m_keep_node(false) + , m_side_effects(false) { - (void)self; - con_err("ast node missing destroy()\n"); - exit(EXIT_FAILURE); } -/* Initialize main ast node aprts */ -static void ast_node_init(ast_node *self, lex_ctx_t ctx, int nodetype) +ast_node::~ast_node() { - self->context = ctx; - self->destroy = &_ast_node_destroy; - self->keep = false; - self->nodetype = nodetype; - self->side_effects = false; } /* weight and side effects */ -static void _ast_propagate_effects(ast_node *self, ast_node *other) +void ast_node::propagate_side_effects(ast_node *other) const { - if (ast_side_effects(other)) - ast_side_effects(self) = true; + other->m_side_effects = m_side_effects; } -#define ast_propagate_effects(s,o) _ast_propagate_effects(((ast_node*)(s)), ((ast_node*)(o))) /* General expression initialization */ -static void ast_expression_init(ast_expression *self, - ast_expression_codegen *codegen) -{ - self->codegen = codegen; - self->vtype = TYPE_VOID; - self->next = nullptr; - self->outl = nullptr; - self->outr = nullptr; - self->count = 0; - self->varparam = nullptr; - self->flags = 0; +ast_expression::ast_expression(lex_ctx_t ctx, int nodetype, qc_type type) + : ast_node(ctx, nodetype) + , m_vtype(type) +{ if (OPTS_OPTION_BOOL(OPTION_COVERAGE)) - self->flags |= AST_FLAG_BLOCK_COVERAGE; + m_flags |= AST_FLAG_BLOCK_COVERAGE; } +ast_expression::ast_expression(lex_ctx_t ctx, int nodetype) + : ast_expression(ctx, nodetype, TYPE_VOID) +{} -static void ast_expression_delete(ast_expression *self) +ast_expression::~ast_expression() { - if (self->next) - ast_delete(self->next); - for (auto &it : self->params) - ast_delete(it); - if (self->varparam) - ast_delete(self->varparam); + if (m_next) + delete m_next; + if (m_varparam) + delete m_varparam; } -static void ast_expression_delete_full(ast_expression *self) +ast_expression::ast_expression(ast_copy_type_t, int nodetype, const ast_expression &other) + : ast_expression(other.m_context, nodetype) { - ast_expression_delete(self); - mem_d(self); + m_vtype = other.m_vtype; + m_count = other.m_count; + m_flags = other.m_flags; + if (other.m_next) + m_next = new ast_expression(ast_copy_type, TYPE_ast_expression, *other.m_next); + m_type_params.reserve(other.m_type_params.size()); + for (auto &it : other.m_type_params) + m_type_params.emplace_back(new ast_value(ast_copy_type, *it)); } -ast_value* ast_value_copy(const ast_value *self) -{ - const ast_expression *fromex; - ast_expression *selfex; - ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype); - if (self->expression.next) { - cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next); - } - fromex = &self->expression; - selfex = &cp->expression; - selfex->count = fromex->count; - selfex->flags = fromex->flags; - for (auto &it : fromex->params) { - ast_value *v = ast_value_copy(it); - selfex->params.push_back(v); - } - return cp; -} +ast_expression::ast_expression(ast_copy_type_t, const ast_expression &other) + : ast_expression(other.m_context, TYPE_ast_expression) +{} -void ast_type_adopt_impl(ast_expression *self, const ast_expression *other) -{ - const ast_expression *fromex; - ast_expression *selfex; - self->vtype = other->vtype; - if (other->next) { - self->next = (ast_expression*)ast_type_copy(ast_ctx(self), other->next); - } - fromex = other; - selfex = self; - selfex->count = fromex->count; - selfex->flags = fromex->flags; - for (auto &it : fromex->params) { - ast_value *v = ast_value_copy(it); - selfex->params.push_back(v); - } +ast_expression *ast_expression::shallow_type(lex_ctx_t ctx, qc_type vtype) { + auto expr = new ast_expression(ctx, TYPE_ast_expression); + expr->m_vtype = vtype; + return expr; } -static ast_expression* ast_shallow_type(lex_ctx_t ctx, int vtype) +void ast_expression::adopt_type(const ast_expression &other) { - ast_instantiate(ast_expression, ctx, ast_expression_delete_full); - ast_expression_init(self, nullptr); - self->codegen = nullptr; - self->next = nullptr; - self->vtype = vtype; - return self; -} - -ast_expression* ast_type_copy(lex_ctx_t ctx, const ast_expression *ex) -{ - const ast_expression *fromex; - ast_expression *selfex; - - if (!ex) - return nullptr; - else - { - ast_instantiate(ast_expression, ctx, ast_expression_delete_full); - ast_expression_init(self, nullptr); - - fromex = ex; - selfex = self; - - /* This may never be codegen()d */ - selfex->codegen = nullptr; - - selfex->vtype = fromex->vtype; - if (fromex->next) - selfex->next = ast_type_copy(ctx, fromex->next); - else - selfex->next = nullptr; - - selfex->count = fromex->count; - selfex->flags = fromex->flags; - for (auto &it : fromex->params) { - ast_value *v = ast_value_copy(it); - selfex->params.push_back(v); - } - - return self; - } + m_vtype = other.m_vtype; + if (other.m_next) + m_next = new ast_expression(ast_copy_type, TYPE_ast_expression, *other.m_next); + m_count = other.m_count; + m_flags = other.m_flags; + m_type_params.clear(); + m_type_params.reserve(other.m_type_params.size()); + for (auto &it : other.m_type_params) + m_type_params.emplace_back(new ast_value(ast_copy_type, *it)); } -bool ast_compare_type(ast_expression *a, ast_expression *b) +bool ast_expression::compare_type(const ast_expression &other) const { - if (a->vtype == TYPE_NIL || - b->vtype == TYPE_NIL) + if (m_vtype == TYPE_NIL || + other.m_vtype == TYPE_NIL) return true; - if (a->vtype != b->vtype) + if (m_vtype != other.m_vtype) return false; - if (!a->next != !b->next) + if (!m_next != !other.m_next) return false; - if (a->params.size() != b->params.size()) + if (m_type_params.size() != other.m_type_params.size()) return false; - if ((a->flags & AST_FLAG_TYPE_MASK) != - (b->flags & AST_FLAG_TYPE_MASK) ) + if ((m_flags & AST_FLAG_TYPE_MASK) != + (other.m_flags & AST_FLAG_TYPE_MASK) ) { return false; } - if (a->params.size()) { + if (m_type_params.size()) { size_t i; - for (i = 0; i < a->params.size(); ++i) { - if (!ast_compare_type((ast_expression*)a->params[i], - (ast_expression*)b->params[i])) + for (i = 0; i < m_type_params.size(); ++i) { + if (!m_type_params[i]->compare_type(*other.m_type_params[i])) return false; } } - if (a->next) - return ast_compare_type(a->next, b->next); + if (m_next) + return m_next->compare_type(*other.m_next); return true; } -static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsize, size_t pos) +ast_value::ast_value(ast_copy_type_t, const ast_value &other, const std::string &name) + : ast_value(ast_copy_type, static_cast(other), name) +{} + +ast_value::ast_value(ast_copy_type_t, const ast_value &other) + : ast_value(ast_copy_type, static_cast(other), other.m_name) +{} + +ast_value::ast_value(ast_copy_type_t, const ast_expression &other, const std::string &name) + : ast_expression(ast_copy_type, other) + , m_name(name) +{} + +ast_value::ast_value(lex_ctx_t ctx, const std::string &name, qc_type t) + : ast_expression(ctx, TYPE_ast_value, t) + , m_name(name) +{ + m_keep_node = true; // keep values, always + memset(&m_constval, 0, sizeof(m_constval)); +} + +ast_value::~ast_value() +{ + if (m_argcounter) + mem_d((void*)m_argcounter); + if (m_hasvalue) { + switch (m_vtype) + { + case TYPE_STRING: + mem_d((void*)m_constval.vstring); + break; + case TYPE_FUNCTION: + // unlink us from the function node + m_constval.vfunc->m_function_type = nullptr; + break; + // NOTE: delete function? currently collected in + // the parser structure + default: + break; + } + } + if (m_ir_values) + mem_d(m_ir_values); + + // initlist imples an array which implies .next in the expression exists. + if (m_initlist.size() && m_next->m_vtype == TYPE_STRING) { + for (auto &it : m_initlist) + if (it.vstring) + mem_d(it.vstring); + } +} + +static size_t ast_type_to_string_impl(const ast_expression *e, char *buf, size_t bufsize, size_t pos) { const char *typestr; size_t typelen; @@ -243,43 +228,43 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi if (pos + 1 >= bufsize) goto full; - switch (e->vtype) { + switch (e->m_vtype) { case TYPE_VARIANT: util_strncpy(buf + pos, "(variant)", 9); return pos + 9; case TYPE_FIELD: buf[pos++] = '.'; - return ast_type_to_string_impl(e->next, buf, bufsize, pos); + return ast_type_to_string_impl(e->m_next, buf, bufsize, pos); case TYPE_POINTER: if (pos + 3 >= bufsize) goto full; buf[pos++] = '*'; buf[pos++] = '('; - pos = ast_type_to_string_impl(e->next, buf, bufsize, pos); + pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos); if (pos + 1 >= bufsize) goto full; buf[pos++] = ')'; return pos; case TYPE_FUNCTION: - pos = ast_type_to_string_impl(e->next, buf, bufsize, pos); + pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos); if (pos + 2 >= bufsize) goto full; - if (e->params.empty()) { + if (e->m_type_params.empty()) { buf[pos++] = '('; buf[pos++] = ')'; return pos; } buf[pos++] = '('; - pos = ast_type_to_string_impl((ast_expression*)(e->params[0]), buf, bufsize, pos); - for (i = 1; i < e->params.size(); ++i) { + pos = ast_type_to_string_impl(e->m_type_params[0].get(), buf, bufsize, pos); + for (i = 1; i < e->m_type_params.size(); ++i) { if (pos + 2 >= bufsize) goto full; buf[pos++] = ','; buf[pos++] = ' '; - pos = ast_type_to_string_impl((ast_expression*)(e->params[i]), buf, bufsize, pos); + pos = ast_type_to_string_impl(e->m_type_params[i].get(), buf, bufsize, pos); } if (pos + 1 >= bufsize) goto full; @@ -287,18 +272,18 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi return pos; case TYPE_ARRAY: - pos = ast_type_to_string_impl(e->next, buf, bufsize, pos); + pos = ast_type_to_string_impl(e->m_next, buf, bufsize, pos); if (pos + 1 >= bufsize) goto full; buf[pos++] = '['; - pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count); + pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->m_count); if (pos + 1 >= bufsize) goto full; buf[pos++] = ']'; return pos; default: - typestr = type_name[e->vtype]; + typestr = type_name[e->m_vtype]; typelen = strlen(typestr); if (pos + typelen >= bufsize) goto full; @@ -313,110 +298,30 @@ full: return bufsize; } -void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize) +void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize) { size_t pos = ast_type_to_string_impl(e, buf, bufsize-1, 0); buf[pos] = 0; } -static bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out); -ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int t) +void ast_value::add_param(ast_value *p) { - ast_instantiate(ast_value, ctx, ast_value_delete); - ast_expression_init((ast_expression*)self, - (ast_expression_codegen*)&ast_value_codegen); - self->expression.node.keep = true; /* keep */ - - self->name = name ? util_strdup(name) : nullptr; - self->expression.vtype = t; - self->expression.next = nullptr; - self->isfield = false; - self->cvq = CV_NONE; - self->hasvalue = false; - self->isimm = false; - self->inexact = false; - self->uses = 0; - memset(&self->constval, 0, sizeof(self->constval)); - - self->ir_v = nullptr; - self->ir_values = nullptr; - self->ir_value_count = 0; - - self->setter = nullptr; - self->getter = nullptr; - self->desc = nullptr; - - self->argcounter = nullptr; - self->intrinsic = false; - - return self; + m_type_params.emplace_back(p); } -void ast_value_delete(ast_value* self) +ast_binary::ast_binary(lex_ctx_t ctx, int op, + ast_expression* left, ast_expression* right) + : ast_expression(ctx, TYPE_ast_binary) + , m_op(op) + // m_left/m_right happen after the peephole step right below + , m_right_first(false) { - if (self->name) - mem_d((void*)self->name); - if (self->argcounter) - mem_d((void*)self->argcounter); - if (self->hasvalue) { - switch (self->expression.vtype) - { - case TYPE_STRING: - mem_d((void*)self->constval.vstring); - break; - case TYPE_FUNCTION: - /* unlink us from the function node */ - self->constval.vfunc->vtype = nullptr; - break; - /* NOTE: delete function? currently collected in - * the parser structure - */ - default: - break; - } - } - if (self->ir_values) - mem_d(self->ir_values); - - if (self->desc) - mem_d(self->desc); - - // initlist imples an array which implies .next in the expression exists. - if (self->initlist.size() && self->expression.next->vtype == TYPE_STRING) { - for (auto &it : self->initlist) - if (it.vstring) - mem_d(it.vstring); - } - - ast_expression_delete((ast_expression*)self); - mem_d(self); -} - -void ast_value_params_add(ast_value *self, ast_value *p) -{ - self->expression.params.push_back(p); -} - -bool ast_value_set_name(ast_value *self, const char *name) -{ - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; -} - -ast_binary* ast_binary_new(lex_ctx_t ctx, int op, - ast_expression* left, ast_expression* right) -{ - ast_instantiate(ast_binary, ctx, ast_binary_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binary_codegen); - if (ast_istype(right, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { ast_unary *unary = ((ast_unary*)right); - ast_expression *normal = unary->operand; + ast_expression *normal = unary->m_operand; /* make a-(-b) => a + b */ - if (unary->op == VINSTR_NEG_F || unary->op == VINSTR_NEG_V) { + if (unary->m_op == VINSTR_NEG_F || unary->m_op == VINSTR_NEG_V) { if (op == INSTR_SUB_F) { op = INSTR_ADD_F; right = normal; @@ -429,417 +334,346 @@ ast_binary* ast_binary_new(lex_ctx_t ctx, int op, } } - self->op = op; - self->left = left; - self->right = right; - self->right_first = false; + m_left = left; + m_right = right; - ast_propagate_effects(self, left); - ast_propagate_effects(self, right); + propagate_side_effects(left); + propagate_side_effects(right); if (op >= INSTR_EQ_F && op <= INSTR_GT) - self->expression.vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; else if (op == INSTR_AND || op == INSTR_OR) { if (OPTS_FLAG(PERL_LOGIC)) - ast_type_adopt(self, right); + adopt_type(*right); else - self->expression.vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; } else if (op == INSTR_BITAND || op == INSTR_BITOR) - self->expression.vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV) - self->expression.vtype = TYPE_VECTOR; + m_vtype = TYPE_VECTOR; else if (op == INSTR_MUL_V) - self->expression.vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; else - self->expression.vtype = left->vtype; - - /* references all */ - self->refs = AST_REF_ALL; + m_vtype = left->m_vtype; - return self; + // references all + m_refs = AST_REF_ALL; } -void ast_binary_delete(ast_binary *self) +ast_binary::~ast_binary() { - if (self->refs & AST_REF_LEFT) ast_unref(self->left); - if (self->refs & AST_REF_RIGHT) ast_unref(self->right); - - ast_expression_delete((ast_expression*)self); - mem_d(self); + if (m_refs & AST_REF_LEFT) ast_unref(m_left); + if (m_refs & AST_REF_RIGHT) ast_unref(m_right); } -ast_binstore* ast_binstore_new(lex_ctx_t ctx, int storop, int op, - ast_expression* left, ast_expression* right) +ast_binstore::ast_binstore(lex_ctx_t ctx, int storop, int mathop, + ast_expression* left, ast_expression* right) + : ast_expression(ctx, TYPE_ast_binstore) + , m_opstore(storop) + , m_opbin(mathop) + , m_dest(left) + , m_source(right) + , m_keep_dest(false) { - ast_instantiate(ast_binstore, ctx, ast_binstore_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_binstore_codegen); - - ast_side_effects(self) = true; - - self->opstore = storop; - self->opbin = op; - self->dest = left; - self->source = right; - - self->keep_dest = false; - - ast_type_adopt(self, left); - return self; + m_side_effects = true; + adopt_type(*left); } -void ast_binstore_delete(ast_binstore *self) +ast_binstore::~ast_binstore() { - if (!self->keep_dest) - ast_unref(self->dest); - ast_unref(self->source); - ast_expression_delete((ast_expression*)self); - mem_d(self); + if (!m_keep_dest) + ast_unref(m_dest); + ast_unref(m_source); } -ast_unary* ast_unary_new(lex_ctx_t ctx, int op, - ast_expression *expr) +ast_unary* ast_unary::make(lex_ctx_t ctx, int op, ast_expression *expr) { - ast_instantiate(ast_unary, ctx, ast_unary_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_unary_codegen); - - 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; + ast_unary *prev = (ast_unary*)((ast_unary*)expr)->m_operand; /* Handle for double negation */ - if (((ast_unary*)expr)->op == op) - prev = (ast_unary*)((ast_unary*)expr)->operand; + if (((ast_unary*)expr)->m_op == op) + prev = (ast_unary*)((ast_unary*)expr)->m_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); + return new ast_unary(ctx, op, expr); +} +ast_unary::ast_unary(lex_ctx_t ctx, int op, ast_expression *expr) + : ast_expression(ctx, TYPE_ast_unary) + , m_op(op) + , m_operand(expr) +{ + propagate_side_effects(expr); if ((op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || op == VINSTR_NEG_F) { - self->expression.vtype = TYPE_FLOAT; + m_vtype = TYPE_FLOAT; } else if (op == VINSTR_NEG_V) { - self->expression.vtype = TYPE_VECTOR; + m_vtype = TYPE_VECTOR; } else { compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]); } - - return self; } -void ast_unary_delete(ast_unary *self) +ast_unary::~ast_unary() { - if (self->operand) ast_unref(self->operand); - ast_expression_delete((ast_expression*)self); - mem_d(self); + if (m_operand) + ast_unref(m_operand); } -ast_return* ast_return_new(lex_ctx_t ctx, ast_expression *expr) +ast_return::ast_return(lex_ctx_t ctx, ast_expression *expr) + : ast_expression(ctx, TYPE_ast_return) + , m_operand(expr) { - ast_instantiate(ast_return, ctx, ast_return_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_return_codegen); - - self->operand = expr; - if (expr) - ast_propagate_effects(self, expr); - - return self; + propagate_side_effects(expr); } -void ast_return_delete(ast_return *self) +ast_return::~ast_return() { - if (self->operand) - ast_unref(self->operand); - ast_expression_delete((ast_expression*)self); - mem_d(self); + if (m_operand) + ast_unref(m_operand); } -ast_entfield* ast_entfield_new(lex_ctx_t ctx, ast_expression *entity, ast_expression *field) +ast_entfield::ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field) + : ast_entfield(ctx, entity, field, field->m_next) { - if (field->vtype != TYPE_FIELD) { - compile_error(ctx, "ast_entfield_new with expression not of type field"); - return nullptr; - } - return ast_entfield_new_force(ctx, entity, field, field->next); + if (field->m_vtype != TYPE_FIELD) + compile_error(ctx, "ast_entfield with expression not of type field"); } -ast_entfield* ast_entfield_new_force(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype) +ast_entfield::ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype) + : ast_expression(ctx, TYPE_ast_entfield) + , m_entity(entity) + , m_field(field) { - ast_instantiate(ast_entfield, ctx, ast_entfield_delete); + propagate_side_effects(m_entity); + propagate_side_effects(m_field); if (!outtype) { - mem_d(self); - /* Error: field has no type... */ - return nullptr; + compile_error(ctx, "ast_entfield: field has no type"); + m_vtype = TYPE_VOID; } - - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_entfield_codegen); - - self->entity = entity; - self->field = field; - ast_propagate_effects(self, entity); - ast_propagate_effects(self, field); - - ast_type_adopt(self, outtype); - return self; + else + adopt_type(*outtype); } -void ast_entfield_delete(ast_entfield *self) +ast_entfield::~ast_entfield() { - ast_unref(self->entity); - ast_unref(self->field); - ast_expression_delete((ast_expression*)self); - mem_d(self); + ast_unref(m_entity); + ast_unref(m_field); } -ast_member* ast_member_new(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const char *name) +ast_member *ast_member::make(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name) { - ast_instantiate(ast_member, ctx, ast_member_delete); if (field >= 3) { - mem_d(self); + compile_error(ctx, "ast_member: invalid field (>=3): %u", field); return nullptr; } - - if (owner->vtype != TYPE_VECTOR && - owner->vtype != TYPE_FIELD) { - compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->vtype]); - mem_d(self); + if (owner->m_vtype != TYPE_VECTOR && + owner->m_vtype != TYPE_FIELD) + { + compile_error(ctx, "member-access on an invalid owner of type %s", type_name[owner->m_vtype]); return nullptr; } + return new ast_member(ctx, owner, field, name); +} - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen); - self->expression.node.keep = true; /* keep */ +ast_member::ast_member(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name) + : ast_expression(ctx, TYPE_ast_member) + , m_owner(owner) + , m_field(field) + , m_name(name) + , m_rvalue(false) +{ + m_keep_node = true; - if (owner->vtype == TYPE_VECTOR) { - self->expression.vtype = TYPE_FLOAT; - self->expression.next = nullptr; + if (m_owner->m_vtype == TYPE_VECTOR) { + m_vtype = TYPE_FLOAT; + m_next = nullptr; } else { - self->expression.vtype = TYPE_FIELD; - self->expression.next = ast_shallow_type(ctx, TYPE_FLOAT); + m_vtype = TYPE_FIELD; + m_next = ast_shallow_type(ctx, TYPE_FLOAT); } - self->rvalue = false; - self->owner = owner; - ast_propagate_effects(self, owner); - - self->field = field; - if (name) - self->name = util_strdup(name); - else - self->name = nullptr; - - return self; -} - -void ast_member_delete(ast_member *self) -{ - /* The owner is always an ast_value, which has .keep=true, - * also: ast_members are usually deleted after the owner, thus - * this will cause invalid access - ast_unref(self->owner); - * once we allow (expression).x to access a vector-member, we need - * to change this: preferably by creating an alternate ast node for this - * purpose that is not garbage-collected. - */ - ast_expression_delete((ast_expression*)self); - mem_d(self->name); - mem_d(self); + propagate_side_effects(owner); } -bool ast_member_set_name(ast_member *self, const char *name) +ast_member::~ast_member() { - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; + // The owner is always an ast_value, which has .keep_node=true, + // also: ast_members are usually deleted after the owner, thus + // this will cause invalid access + //ast_unref(self->m_owner); + // once we allow (expression).x to access a vector-member, we need + // to change this: preferably by creating an alternate ast node for this + // purpose that is not garbage-collected. } -ast_array_index* ast_array_index_new(lex_ctx_t ctx, ast_expression *array, ast_expression *index) +ast_array_index* ast_array_index::make(lex_ctx_t ctx, ast_expression *array, ast_expression *index) { - ast_expression *outtype; - ast_instantiate(ast_array_index, ctx, ast_array_index_delete); - - outtype = array->next; + ast_expression *outtype = array->m_next; if (!outtype) { - mem_d(self); - /* Error: field has no type... */ + // field has no type return nullptr; } - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_array_index_codegen); + return new ast_array_index(ctx, array, index); +} - self->array = array; - self->index = index; - ast_propagate_effects(self, array); - ast_propagate_effects(self, index); +ast_array_index::ast_array_index(lex_ctx_t ctx, ast_expression *array, ast_expression *index) + : ast_expression(ctx, TYPE_ast_array_index) + , m_array(array) + , m_index(index) +{ + propagate_side_effects(array); + propagate_side_effects(index); - ast_type_adopt(self, outtype); - if (array->vtype == TYPE_FIELD && outtype->vtype == TYPE_ARRAY) { - if (self->expression.vtype != TYPE_ARRAY) { - compile_error(ast_ctx(self), "array_index node on type"); - ast_array_index_delete(self); - return nullptr; - } - self->array = outtype; - self->expression.vtype = TYPE_FIELD; + ast_expression *outtype = m_array->m_next; + adopt_type(*outtype); + + if (array->m_vtype == TYPE_FIELD && outtype->m_vtype == TYPE_ARRAY) { + // FIXME: investigate - this is not possible after adopt_type + //if (m_vtype != TYPE_ARRAY) { + // compile_error(self->m_context, "array_index node on type"); + // ast_array_index_delete(self); + // return nullptr; + //} + + m_array = outtype; + m_vtype = TYPE_FIELD; } +} - return self; +ast_array_index::~ast_array_index() +{ + if (m_array) + ast_unref(m_array); + if (m_index) + ast_unref(m_index); } -void ast_array_index_delete(ast_array_index *self) +ast_argpipe::ast_argpipe(lex_ctx_t ctx, ast_expression *index) + : ast_expression(ctx, TYPE_ast_argpipe) + , m_index(index) { - if (self->array) - ast_unref(self->array); - if (self->index) - ast_unref(self->index); - ast_expression_delete((ast_expression*)self); - mem_d(self); + m_vtype = TYPE_NOEXPR; } -ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index) +ast_argpipe::~ast_argpipe() { - ast_instantiate(ast_argpipe, ctx, ast_argpipe_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_argpipe_codegen); - self->index = index; - self->expression.vtype = TYPE_NOEXPR; - return self; + if (m_index) + ast_unref(m_index); } -void ast_argpipe_delete(ast_argpipe *self) +ast_store::ast_store(lex_ctx_t ctx, int op, ast_expression *dest, ast_expression *source) + : ast_expression(ctx, TYPE_ast_store) + , m_op(op) + , m_dest(dest) + , m_source(source) { - if (self->index) - ast_unref(self->index); - ast_expression_delete((ast_expression*)self); - mem_d(self); + m_side_effects = true; + adopt_type(*dest); } -ast_ifthen* ast_ifthen_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse) +ast_store::~ast_store() { - ast_instantiate(ast_ifthen, ctx, ast_ifthen_delete); - if (!ontrue && !onfalse) { - /* because it is invalid */ - mem_d(self); - return nullptr; - } - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ifthen_codegen); + ast_unref(m_dest); + ast_unref(m_source); +} - self->cond = cond; - self->on_true = ontrue; - self->on_false = onfalse; - ast_propagate_effects(self, cond); +ast_ifthen::ast_ifthen(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse) + : ast_expression(ctx, TYPE_ast_ifthen) + , m_cond(cond) + , m_on_true(ontrue) + , m_on_false(onfalse) +{ + propagate_side_effects(cond); if (ontrue) - ast_propagate_effects(self, ontrue); + propagate_side_effects(ontrue); if (onfalse) - ast_propagate_effects(self, onfalse); - - return self; + propagate_side_effects(onfalse); } -void ast_ifthen_delete(ast_ifthen *self) +ast_ifthen::~ast_ifthen() { - ast_unref(self->cond); - if (self->on_true) - ast_unref(self->on_true); - if (self->on_false) - ast_unref(self->on_false); - ast_expression_delete((ast_expression*)self); - mem_d(self); + ast_unref(m_cond); + if (m_on_true) + ast_unref(m_on_true); + if (m_on_false) + ast_unref(m_on_false); } -ast_ternary* ast_ternary_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse) +ast_ternary::ast_ternary(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse) + : ast_expression(ctx, TYPE_ast_ternary) + , m_cond(cond) + , m_on_true(ontrue) + , m_on_false(onfalse) { - ast_expression *exprtype = ontrue; - ast_instantiate(ast_ternary, ctx, ast_ternary_delete); - /* This time NEITHER must be nullptr */ - if (!ontrue || !onfalse) { - mem_d(self); - return nullptr; - } - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_ternary_codegen); + propagate_side_effects(cond); + propagate_side_effects(ontrue); + propagate_side_effects(onfalse); - self->cond = cond; - self->on_true = ontrue; - self->on_false = onfalse; - ast_propagate_effects(self, cond); - ast_propagate_effects(self, ontrue); - ast_propagate_effects(self, onfalse); - - if (ontrue->vtype == TYPE_NIL) - exprtype = onfalse; - ast_type_adopt(self, exprtype); - - return self; + if (ontrue->m_vtype == TYPE_NIL) + adopt_type(onfalse); + else + adopt_type(ontrue); } -void ast_ternary_delete(ast_ternary *self) +ast_ternary::~ast_ternary() { /* the if()s are only there because computed-gotos can set them * to nullptr */ - if (self->cond) ast_unref(self->cond); - if (self->on_true) ast_unref(self->on_true); - if (self->on_false) ast_unref(self->on_false); - ast_expression_delete((ast_expression*)self); - mem_d(self); -} - -ast_loop* ast_loop_new(lex_ctx_t ctx, - ast_expression *initexpr, - ast_expression *precond, bool pre_not, - ast_expression *postcond, bool post_not, - ast_expression *increment, - ast_expression *body) + if (m_cond) ast_unref(m_cond); + if (m_on_true) ast_unref(m_on_true); + if (m_on_false) ast_unref(m_on_false); +} + +ast_loop::ast_loop(lex_ctx_t ctx, + ast_expression *initexpr, + ast_expression *precond, bool pre_not, + ast_expression *postcond, bool post_not, + ast_expression *increment, + ast_expression *body) + , ast_expression(ctx, TYPE_ast_loop) + , m_initexpr(initexpr) + , m_precond(precond) + , m_postcond(postcond) + , m_increment(increment) + , m_body(body) + , m_pre_not(pre_not) + , m_post_not(post_not) { - ast_instantiate(ast_loop, ctx, ast_loop_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_loop_codegen); - - self->initexpr = initexpr; - self->precond = precond; - self->postcond = postcond; - self->increment = increment; - self->body = body; - - self->pre_not = pre_not; - self->post_not = post_not; - if (initexpr) - ast_propagate_effects(self, initexpr); + propagate_side_effects(initexpr); if (precond) - ast_propagate_effects(self, precond); + propagate_side_effects(precond); if (postcond) - ast_propagate_effects(self, postcond); + propagate_side_effects(postcond); if (increment) - ast_propagate_effects(self, increment); + propagate_side_effects(increment); if (body) - ast_propagate_effects(self, body); - - return self; + propagate_side_effects(body); } -void ast_loop_delete(ast_loop *self) +ast_loop::~ast_loop() { - if (self->initexpr) - ast_unref(self->initexpr); - if (self->precond) - ast_unref(self->precond); - if (self->postcond) - ast_unref(self->postcond); - if (self->increment) - ast_unref(self->increment); - if (self->body) - ast_unref(self->body); - ast_expression_delete((ast_expression*)self); - mem_d(self); + if (m_initexpr) + ast_unref(m_initexpr); + if (m_precond) + ast_unref(m_precond); + if (m_postcond) + ast_unref(m_postcond); + if (m_increment) + ast_unref(m_increment); + if (m_body) + ast_unref(m_body); } ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels) @@ -847,8 +681,8 @@ ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels ast_instantiate(ast_breakcont, ctx, ast_breakcont_delete); ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_breakcont_codegen); - self->is_continue = iscont; - self->levels = levels; + self->m_is_continue = iscont; + self->m_levels = levels; return self; } @@ -856,6 +690,7 @@ ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels void ast_breakcont_delete(ast_breakcont *self) { ast_expression_delete((ast_expression*)self); + self->~ast_breakcont(); mem_d(self); } @@ -864,24 +699,25 @@ ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op) ast_instantiate(ast_switch, ctx, ast_switch_delete); ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_switch_codegen); - self->operand = op; + self->m_operand = op; - ast_propagate_effects(self, op); + self->propagate_side_effects(op); return self; } void ast_switch_delete(ast_switch *self) { - ast_unref(self->operand); + ast_unref(self->m_operand); - for (auto &it : self->cases) { - if (it.value) - ast_unref(it.value); - ast_unref(it.code); + for (auto &it : self->m_cases) { + if (it.m_value) + ast_unref(it.m_value); + ast_unref(it.m_code); } ast_expression_delete((ast_expression*)self); + self->~ast_switch(); mem_d(self); } @@ -890,25 +726,26 @@ ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined) ast_instantiate(ast_label, ctx, ast_label_delete); ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_label_codegen); - self->expression.vtype = TYPE_NOEXPR; + self->m_vtype = TYPE_NOEXPR; - self->name = util_strdup(name); - self->irblock = nullptr; - self->undefined = undefined; + self->m_name = util_strdup(name); + self->m_irblock = nullptr; + self->m_undefined = undefined; return self; } void ast_label_delete(ast_label *self) { - mem_d((void*)self->name); + mem_d((void*)self->m_name); ast_expression_delete((ast_expression*)self); + self->~ast_label(); mem_d(self); } static void ast_label_register_goto(ast_label *self, ast_goto *g) { - self->gotos.push_back(g); + self->m_gotos.push_back(g); } ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name) @@ -916,42 +753,44 @@ ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name) ast_instantiate(ast_goto, ctx, ast_goto_delete); ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_goto_codegen); - self->name = util_strdup(name); - self->target = nullptr; - self->irblock_from = nullptr; + self->m_name = util_strdup(name); + self->m_target = nullptr; + self->m_irblock_from = nullptr; return self; } void ast_goto_delete(ast_goto *self) { - mem_d((void*)self->name); + mem_d((void*)self->m_name); ast_expression_delete((ast_expression*)self); + self->~ast_goto(); mem_d(self); } void ast_goto_set_label(ast_goto *self, ast_label *label) { - self->target = label; + self->m_target = label; } ast_state* ast_state_new(lex_ctx_t ctx, ast_expression *frame, ast_expression *think) { ast_instantiate(ast_state, ctx, ast_state_delete); ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_state_codegen); - self->framenum = frame; - self->nextthink = think; + self->m_framenum = frame; + self->m_nextthink = think; return self; } void ast_state_delete(ast_state *self) { - if (self->framenum) - ast_unref(self->framenum); - if (self->nextthink) - ast_unref(self->nextthink); + if (self->m_framenum) + ast_unref(self->m_framenum); + if (self->m_nextthink) + ast_unref(self->m_nextthink); ast_expression_delete((ast_expression*)self); + self->~ast_state(); mem_d(self); } @@ -959,35 +798,36 @@ ast_call* ast_call_new(lex_ctx_t ctx, ast_expression *funcexpr) { ast_instantiate(ast_call, ctx, ast_call_delete); - if (!funcexpr->next) { + if (!funcexpr->m_next) { compile_error(ctx, "not a function"); mem_d(self); return nullptr; } ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_call_codegen); - ast_side_effects(self) = true; + self->m_side_effects = true; - self->func = funcexpr; - self->va_count = nullptr; + self->m_func = funcexpr; + self->m_va_count = nullptr; - ast_type_adopt(self, funcexpr->next); + ast_type_adopt(self, funcexpr->m_next); return self; } void ast_call_delete(ast_call *self) { - for (auto &it : self->params) + for (auto &it : self->m_params) ast_unref(it); - if (self->func) - ast_unref(self->func); + if (self->m_func) + ast_unref(self->m_func); - if (self->va_count) - ast_unref(self->va_count); + if (self->m_va_count) + ast_unref(self->m_va_count); ast_expression_delete((ast_expression*)self); + self->~ast_call(); mem_d(self); } @@ -1004,12 +844,12 @@ static bool ast_call_check_vararg(ast_call *self, ast_expression *va_type, ast_e ast_type_to_string(va_type, tgot, sizeof(tgot)); ast_type_to_string(exp_type, texp, sizeof(texp)); if (OPTS_FLAG(UNSAFE_VARARGS)) { - if (compile_warning(ast_ctx(self), WARN_UNSAFE_TYPES, + if (compile_warning(self->m_context, WARN_UNSAFE_TYPES, "piped variadic argument differs in type: constrained to type %s, expected type %s", tgot, texp)) return false; } else { - compile_error(ast_ctx(self), + compile_error(self->m_context, "piped variadic argument differs in type: constrained to type %s, expected type %s", tgot, texp); return false; @@ -1019,12 +859,12 @@ static bool ast_call_check_vararg(ast_call *self, ast_expression *va_type, ast_e { ast_type_to_string(exp_type, texp, sizeof(texp)); if (OPTS_FLAG(UNSAFE_VARARGS)) { - if (compile_warning(ast_ctx(self), WARN_UNSAFE_TYPES, + if (compile_warning(self->m_context, WARN_UNSAFE_TYPES, "piped variadic argument may differ in type: expected type %s", texp)) return false; } else { - compile_error(ast_ctx(self), + compile_error(self->m_context, "piped variadic argument may differ in type: expected type %s", texp); return false; @@ -1040,48 +880,48 @@ bool ast_call_check_types(ast_call *self, ast_expression *va_type) char tgot[1024]; size_t i; bool retval = true; - const ast_expression *func = self->func; - size_t count = self->params.size(); - if (count > func->params.size()) - count = func->params.size(); + const ast_expression *func = self->m_func; + size_t count = self->m_params.size(); + if (count > func->m_type_params.size()) + count = func->m_type_params.size(); for (i = 0; i < count; ++i) { - if (ast_istype(self->params[i], ast_argpipe)) { + if (ast_istype(self->m_params[i], ast_argpipe)) { /* warn about type safety instead */ if (i+1 != count) { - compile_error(ast_ctx(self), "argpipe must be the last parameter to a function call"); + compile_error(self->m_context, "argpipe must be the last parameter to a function call"); return false; } - if (!ast_call_check_vararg(self, va_type, (ast_expression*)func->params[i])) + if (!ast_call_check_vararg(self, va_type, (ast_expression*)func->m_type_params[i])) retval = false; } - else if (!ast_compare_type(self->params[i], (ast_expression*)(func->params[i]))) + else if (!ast_compare_type(self->m_params[i], (ast_expression*)(func->m_type_params[i]))) { - ast_type_to_string(self->params[i], tgot, sizeof(tgot)); - ast_type_to_string((ast_expression*)func->params[i], texp, sizeof(texp)); - compile_error(ast_ctx(self), "invalid type for parameter %u in function call: expected %s, got %s", + ast_type_to_string(self->m_params[i], tgot, sizeof(tgot)); + ast_type_to_string((ast_expression*)func->m_type_params[i], texp, sizeof(texp)); + compile_error(self->m_context, "invalid type for parameter %u in function call: expected %s, got %s", (unsigned int)(i+1), texp, tgot); /* we don't immediately return */ retval = false; } } - count = self->params.size(); - if (count > func->params.size() && func->varparam) { + count = self->m_params.size(); + if (count > func->m_type_params.size() && func->m_varparam) { for (; i < count; ++i) { - if (ast_istype(self->params[i], ast_argpipe)) { + if (ast_istype(self->m_params[i], ast_argpipe)) { /* warn about type safety instead */ if (i+1 != count) { - compile_error(ast_ctx(self), "argpipe must be the last parameter to a function call"); + compile_error(self->m_context, "argpipe must be the last parameter to a function call"); return false; } - if (!ast_call_check_vararg(self, va_type, func->varparam)) + if (!ast_call_check_vararg(self, va_type, func->m_varparam)) retval = false; } - else if (!ast_compare_type(self->params[i], func->varparam)) + else if (!ast_compare_type(self->m_params[i], func->m_varparam)) { - ast_type_to_string(self->params[i], tgot, sizeof(tgot)); - ast_type_to_string(func->varparam, texp, sizeof(texp)); - compile_error(ast_ctx(self), "invalid type for variadic parameter %u in function call: expected %s, got %s", + ast_type_to_string(self->m_params[i], tgot, sizeof(tgot)); + ast_type_to_string(func->m_varparam, texp, sizeof(texp)); + compile_error(self->m_context, "invalid type for variadic parameter %u in function call: expected %s, got %s", (unsigned int)(i+1), texp, tgot); /* we don't immediately return */ retval = false; @@ -1091,31 +931,6 @@ bool ast_call_check_types(ast_call *self, ast_expression *va_type) return retval; } -ast_store* ast_store_new(lex_ctx_t ctx, int op, - ast_expression *dest, ast_expression *source) -{ - ast_instantiate(ast_store, ctx, ast_store_delete); - ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_store_codegen); - - ast_side_effects(self) = true; - - self->op = op; - self->dest = dest; - self->source = source; - - ast_type_adopt(self, dest); - - return self; -} - -void ast_store_delete(ast_store *self) -{ - ast_unref(self->dest); - ast_unref(self->source); - ast_expression_delete((ast_expression*)self); - mem_d(self); -} - ast_block* ast_block_new(lex_ctx_t ctx) { ast_instantiate(ast_block, ctx, ast_block_delete); @@ -1126,11 +941,11 @@ ast_block* ast_block_new(lex_ctx_t ctx) bool ast_block_add_expr(ast_block *self, ast_expression *e) { - ast_propagate_effects(self, e); - self->exprs.push_back(e); - if (self->expression.next) { - ast_delete(self->expression.next); - self->expression.next = nullptr; + self->propagate_side_effects(e); + self->m_exprs.push_back(e); + if (self->m_next) { + ast_delete(self->m_next); + self->m_next = nullptr; } ast_type_adopt(self, e); return true; @@ -1138,23 +953,24 @@ bool ast_block_add_expr(ast_block *self, ast_expression *e) void ast_block_collect(ast_block *self, ast_expression *expr) { - self->collect.push_back(expr); - expr->node.keep = true; + self->m_collect.push_back(expr); + expr->m_keep_node = true; } void ast_block_delete(ast_block *self) { - for (auto &it : self->exprs) ast_unref(it); - for (auto &it : self->locals) ast_delete(it); - for (auto &it : self->collect) ast_delete(it); + for (auto &it : self->m_exprs) ast_unref(it); + for (auto &it : self->m_locals) ast_delete(it); + for (auto &it : self->m_collect) ast_delete(it); ast_expression_delete((ast_expression*)self); + self->~ast_block(); mem_d(self); } void ast_block_set_type(ast_block *self, ast_expression *from) { - if (self->expression.next) - ast_delete(self->expression.next); + if (self->m_next) + ast_delete(self->m_next); ast_type_adopt(self, from); } @@ -1163,33 +979,33 @@ ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype ast_instantiate(ast_function, ctx, ast_function_delete); if (!vtype) { - compile_error(ast_ctx(self), "internal error: ast_function_new condition 0"); + compile_error(self->m_context, "internal error: ast_function_new condition 0"); goto cleanup; - } else if (vtype->hasvalue || vtype->expression.vtype != TYPE_FUNCTION) { - compile_error(ast_ctx(self), "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)", + } else if (vtype->m_hasvalue || vtype->m_vtype != TYPE_FUNCTION) { + compile_error(self->m_context, "internal error: ast_function_new condition %i %i type=%i (probably 2 bodies?)", (int)!vtype, - (int)vtype->hasvalue, - vtype->expression.vtype); + (int)vtype->m_hasvalue, + vtype->m_vtype); goto cleanup; } - self->vtype = vtype; - self->name = name ? util_strdup(name) : nullptr; + self->m_function_type = vtype; + self->m_name = name ? util_strdup(name) : nullptr; - self->labelcount = 0; - self->builtin = 0; + self->m_labelcount = 0; + self->m_builtin = 0; - self->ir_func = nullptr; - self->curblock = nullptr; + self->m_ir_func = nullptr; + self->m_curblock = nullptr; - vtype->hasvalue = true; - vtype->constval.vfunc = self; + vtype->m_hasvalue = true; + vtype->m_constval.vfunc = self; - self->varargs = nullptr; - self->argc = nullptr; - self->fixedparams = nullptr; - self->return_value = nullptr; - self->static_count = 0; + self->m_varargs = nullptr; + self->m_argc = nullptr; + self->m_fixedparams = nullptr; + self->m_return_value = nullptr; + self->m_static_count = 0; return self; @@ -1200,29 +1016,31 @@ cleanup: void ast_function_delete(ast_function *self) { - if (self->name) - mem_d((void*)self->name); - if (self->vtype) { - /* ast_value_delete(self->vtype); */ - self->vtype->hasvalue = false; - self->vtype->constval.vfunc = nullptr; + if (self->m_name) + mem_d((void*)self->m_name); + if (self->m_function_type) { + /* ast_value_delete(self->m_function_type); */ + self->m_function_type->m_hasvalue = false; + self->m_function_type->m_constval.vfunc = nullptr; /* We use unref - if it was stored in a global table it is supposed * to be deleted from *there* */ - ast_unref(self->vtype); + ast_unref(self->m_function_type); } - for (auto &it : self->static_names) + for (auto &it : self->m_static_names) mem_d(it); - for (auto &it : self->blocks) - ast_delete(it); - if (self->varargs) - ast_delete(self->varargs); - if (self->argc) - ast_delete(self->argc); - if (self->fixedparams) - ast_unref(self->fixedparams); - if (self->return_value) - ast_unref(self->return_value); + // FIXME::DELME:: unique_ptr used on ast_block + //for (auto &it : self->m_blocks) + // ast_delete(it); + if (self->m_varargs) + ast_delete(self->m_varargs); + if (self->m_argc) + ast_delete(self->m_argc); + if (self->m_fixedparams) + ast_unref(self->m_fixedparams); + if (self->m_return_value) + ast_unref(self->m_return_value); + self->~ast_function(); mem_d(self); } @@ -1239,10 +1057,10 @@ const char* ast_function_label(ast_function *self, const char *prefix) return nullptr; } - id = (self->labelcount++); + id = (self->m_labelcount++); len = strlen(prefix); - from = self->labelbuf + sizeof(self->labelbuf)-1; + from = self->m_labelbuf + sizeof(self->m_labelbuf)-1; *from-- = 0; do { *from-- = (id%10) + '0'; @@ -1262,90 +1080,90 @@ const char* ast_function_label(ast_function *self, const char *prefix) static void _ast_codegen_output_type(ast_expression *self, ir_value *out) { - if (out->vtype == TYPE_FIELD) - out->fieldtype = self->next->vtype; - if (out->vtype == TYPE_FUNCTION) - out->outtype = self->next->vtype; + if (out->m_vtype == TYPE_FIELD) + out->m_fieldtype = self->m_next->m_vtype; + if (out->m_vtype == TYPE_FUNCTION) + out->m_outtype = self->m_next->m_vtype; } -#define codegen_output_type(a,o) (_ast_codegen_output_type(&((a)->expression),(o))) +#define codegen_output_type(a,o) (_ast_codegen_output_type(static_cast((a)),(o))) bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out) { (void)func; (void)lvalue; - if (self->expression.vtype == TYPE_NIL) { - *out = func->ir_func->owner->nil; + if (self->m_vtype == TYPE_NIL) { + *out = func->m_ir_func->m_owner->m_nil; return true; } - /* NOTE: This is the codegen for a variable used in an expression. + /* NOTE: This is the codegen for a variable used in an * It is not the codegen to generate the value. For this purpose, * ast_local_codegen and ast_global_codegen are to be used before this * is executed. ast_function_codegen should take care of its locals, * and the ast-user should take care of ast_global_codegen to be used * on all the globals. */ - if (!self->ir_v) { + if (!self->m_ir_v) { char tname[1024]; /* typename is reserved in C++ */ ast_type_to_string((ast_expression*)self, tname, sizeof(tname)); - compile_error(ast_ctx(self), "ast_value used before generated %s %s", tname, self->name); + compile_error(self->m_context, "ast_value used before generated %s %s", tname, self->m_name); return false; } - *out = self->ir_v; + *out = self->m_ir_v; return true; } static bool ast_global_array_set(ast_value *self) { - size_t count = self->initlist.size(); + size_t count = self->m_initlist.size(); size_t i; - if (count > self->expression.count) { - compile_error(ast_ctx(self), "too many elements in initializer"); - count = self->expression.count; + if (count > self->m_count) { + compile_error(self->m_context, "too many elements in initializer"); + count = self->m_count; } - else if (count < self->expression.count) { + else if (count < self->m_count) { /* add this? - compile_warning(ast_ctx(self), "not all elements are initialized"); + compile_warning(self->m_context, "not all elements are initialized"); */ } for (i = 0; i != count; ++i) { - switch (self->expression.next->vtype) { + switch (self->m_next->m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(self->ir_values[i], self->initlist[i].vfloat)) + if (!ir_value_set_float(self->m_ir_values[i], self->m_initlist[i].vfloat)) return false; break; case TYPE_VECTOR: - if (!ir_value_set_vector(self->ir_values[i], self->initlist[i].vvec)) + if (!ir_value_set_vector(self->m_ir_values[i], self->m_initlist[i].vvec)) return false; break; case TYPE_STRING: - if (!ir_value_set_string(self->ir_values[i], self->initlist[i].vstring)) + if (!ir_value_set_string(self->m_ir_values[i], self->m_initlist[i].vstring)) return false; break; case TYPE_ARRAY: /* we don't support them in any other place yet either */ - compile_error(ast_ctx(self), "TODO: nested arrays"); + compile_error(self->m_context, "TODO: nested arrays"); return false; case TYPE_FUNCTION: /* this requiers a bit more work - similar to the fields I suppose */ - compile_error(ast_ctx(self), "global of type function not properly generated"); + compile_error(self->m_context, "global of type function not properly generated"); return false; case TYPE_FIELD: - if (!self->initlist[i].vfield) { - compile_error(ast_ctx(self), "field constant without vfield set"); + if (!self->m_initlist[i].vfield) { + compile_error(self->m_context, "field constant without vfield set"); return false; } - if (!self->initlist[i].vfield->ir_v) { - compile_error(ast_ctx(self), "field constant generated before its field"); + if (!self->m_initlist[i].vfield->m_ir_v) { + compile_error(self->m_context, "field constant generated before its field"); return false; } - if (!ir_value_set_field(self->ir_values[i], self->initlist[i].vfield->ir_v)) + if (!ir_value_set_field(self->m_ir_values[i], self->m_initlist[i].vfield->m_ir_v)) return false; break; default: - compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype); + compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype); break; } } @@ -1354,13 +1172,13 @@ static bool ast_global_array_set(ast_value *self) static bool check_array(ast_value *self, ast_value *array) { - if (array->expression.flags & AST_FLAG_ARRAY_INIT && array->initlist.empty()) { - compile_error(ast_ctx(self), "array without size: %s", self->name); + if (array->m_flags & AST_FLAG_ARRAY_INIT && array->m_initlist.empty()) { + compile_error(self->m_context, "array without size: %s", self->m_name); return false; } /* we are lame now - considering the way QC works we won't tolerate arrays > 1024 elements */ - if (!array->expression.count || array->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) { - compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)array->expression.count); + if (!array->m_count || array->m_count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) { + compile_error(self->m_context, "Invalid array of size %lu", (unsigned long)array->m_count); return false; } return true; @@ -1370,122 +1188,122 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) { ir_value *v = nullptr; - if (self->expression.vtype == TYPE_NIL) { - compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL"); + if (self->m_vtype == TYPE_NIL) { + compile_error(self->m_context, "internal error: trying to generate a variable of TYPE_NIL"); return false; } - if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION) + if (self->m_hasvalue && self->m_vtype == TYPE_FUNCTION) { - ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->vtype); + ir_function *func = ir_builder_create_function(ir, self->m_name, self->m_next->m_vtype); if (!func) return false; - func->context = ast_ctx(self); - func->value->context = ast_ctx(self); - - self->constval.vfunc->ir_func = func; - self->ir_v = func->value; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - self->ir_v->flags |= IR_FLAG_INCLUDE_DEF; - if (self->expression.flags & AST_FLAG_ERASEABLE) - self->ir_v->flags |= IR_FLAG_ERASABLE; - if (self->expression.flags & AST_FLAG_BLOCK_COVERAGE) - func->flags |= IR_FLAG_BLOCK_COVERAGE; + func->m_context = self->m_context; + func->m_value->m_context = self->m_context; + + self->m_constval.vfunc->m_ir_func = func; + self->m_ir_v = func->m_value; + if (self->m_flags & AST_FLAG_INCLUDE_DEF) + self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (self->m_flags & AST_FLAG_ERASEABLE) + self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; + if (self->m_flags & AST_FLAG_BLOCK_COVERAGE) + func->m_flags |= IR_FLAG_BLOCK_COVERAGE; /* The function is filled later on ast_function_codegen... */ return true; } - if (isfield && self->expression.vtype == TYPE_FIELD) { - ast_expression *fieldtype = self->expression.next; + if (isfield && self->m_vtype == TYPE_FIELD) { + ast_expression *fieldtype = self->m_next; - if (self->hasvalue) { - compile_error(ast_ctx(self), "TODO: constant field pointers with value"); + if (self->m_hasvalue) { + compile_error(self->m_context, "TODO: constant field pointers with value"); goto error; } - if (fieldtype->vtype == TYPE_ARRAY) { + if (fieldtype->m_vtype == TYPE_ARRAY) { size_t ai; char *name; size_t namelen; ast_expression *elemtype; - int vtype; + qc_type vtype; ast_value *array = (ast_value*)fieldtype; if (!ast_istype(fieldtype, ast_value)) { - compile_error(ast_ctx(self), "internal error: ast_value required"); + compile_error(self->m_context, "internal error: ast_value required"); return false; } if (!check_array(self, array)) return false; - elemtype = array->expression.next; - vtype = elemtype->vtype; + elemtype = array->m_next; + vtype = elemtype->m_vtype; - v = ir_builder_create_field(ir, self->name, vtype); + v = ir_builder_create_field(ir, self->m_name, vtype); if (!v) { - compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name); + compile_error(self->m_context, "ir_builder_create_global failed on `%s`", self->m_name); return false; } - v->context = ast_ctx(self); - v->unique_life = true; - v->locked = true; - array->ir_v = self->ir_v = v; + v->m_context = self->m_context; + v->m_unique_life = true; + v->m_locked = true; + array->m_ir_v = self->m_ir_v = v; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - self->ir_v->flags |= IR_FLAG_INCLUDE_DEF; - if (self->expression.flags & AST_FLAG_ERASEABLE) - self->ir_v->flags |= IR_FLAG_ERASABLE; + if (self->m_flags & AST_FLAG_INCLUDE_DEF) + self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (self->m_flags & AST_FLAG_ERASEABLE) + self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; - namelen = strlen(self->name); + namelen = strlen(self->m_name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + util_strncpy(name, self->m_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) { + array->m_ir_values = (ir_value**)mem_a(sizeof(array->m_ir_values[0]) * array->m_count); + array->m_ir_values[0] = v; + for (ai = 1; ai < array->m_count; ++ai) { util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); - array->ir_values[ai] = ir_builder_create_field(ir, name, vtype); - if (!array->ir_values[ai]) { + array->m_ir_values[ai] = ir_builder_create_field(ir, name, vtype); + if (!array->m_ir_values[ai]) { mem_d(name); - compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", name); + compile_error(self->m_context, "ir_builder_create_global failed on `%s`", name); return false; } - array->ir_values[ai]->context = ast_ctx(self); - array->ir_values[ai]->unique_life = true; - array->ir_values[ai]->locked = true; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF; + array->m_ir_values[ai]->m_context = self->m_context; + array->m_ir_values[ai]->m_unique_life = true; + array->m_ir_values[ai]->m_locked = true; + if (self->m_flags & AST_FLAG_INCLUDE_DEF) + self->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; } mem_d(name); } else { - v = ir_builder_create_field(ir, self->name, self->expression.next->vtype); + v = ir_builder_create_field(ir, self->m_name, self->m_next->m_vtype); if (!v) return false; - v->context = ast_ctx(self); - self->ir_v = v; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - self->ir_v->flags |= IR_FLAG_INCLUDE_DEF; + v->m_context = self->m_context; + self->m_ir_v = v; + if (self->m_flags & AST_FLAG_INCLUDE_DEF) + self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; - if (self->expression.flags & AST_FLAG_ERASEABLE) - self->ir_v->flags |= IR_FLAG_ERASABLE; + if (self->m_flags & AST_FLAG_ERASEABLE) + self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; } return true; } - if (self->expression.vtype == TYPE_ARRAY) { + if (self->m_vtype == TYPE_ARRAY) { size_t ai; char *name; size_t namelen; - ast_expression *elemtype = self->expression.next; - int vtype = elemtype->vtype; + ast_expression *elemtype = self->m_next; + qc_type vtype = elemtype->m_vtype; - if (self->expression.flags & AST_FLAG_ARRAY_INIT && !self->expression.count) { - compile_error(ast_ctx(self), "array `%s' has no size", self->name); + if (self->m_flags & AST_FLAG_ARRAY_INIT && !self->m_count) { + compile_error(self->m_context, "array `%s' has no size", self->m_name); return false; } @@ -1493,39 +1311,39 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) if (!check_array(self, self)) return false; - v = ir_builder_create_global(ir, self->name, vtype); + v = ir_builder_create_global(ir, self->m_name, vtype); if (!v) { - compile_error(ast_ctx(self), "ir_builder_create_global failed `%s`", self->name); + compile_error(self->m_context, "ir_builder_create_global failed `%s`", self->m_name); return false; } - v->context = ast_ctx(self); - v->unique_life = true; - v->locked = true; + v->m_context = self->m_context; + v->m_unique_life = true; + v->m_locked = true; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - v->flags |= IR_FLAG_INCLUDE_DEF; - if (self->expression.flags & AST_FLAG_ERASEABLE) - self->ir_v->flags |= IR_FLAG_ERASABLE; + if (self->m_flags & AST_FLAG_INCLUDE_DEF) + v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (self->m_flags & AST_FLAG_ERASEABLE) + self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; - namelen = strlen(self->name); + namelen = strlen(self->m_name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + util_strncpy(name, self->m_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) { + self->m_ir_values = (ir_value**)mem_a(sizeof(self->m_ir_values[0]) * self->m_count); + self->m_ir_values[0] = v; + for (ai = 1; ai < self->m_count; ++ai) { util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); - self->ir_values[ai] = ir_builder_create_global(ir, name, vtype); - if (!self->ir_values[ai]) { + self->m_ir_values[ai] = ir_builder_create_global(ir, name, vtype); + if (!self->m_ir_values[ai]) { mem_d(name); - compile_error(ast_ctx(self), "ir_builder_create_global failed `%s`", name); + compile_error(self->m_context, "ir_builder_create_global failed `%s`", name); return false; } - self->ir_values[ai]->context = ast_ctx(self); - self->ir_values[ai]->unique_life = true; - self->ir_values[ai]->locked = true; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - self->ir_values[ai]->flags |= IR_FLAG_INCLUDE_DEF; + self->m_ir_values[ai]->m_context = self->m_context; + self->m_ir_values[ai]->m_unique_life = true; + self->m_ir_values[ai]->m_locked = true; + if (self->m_flags & AST_FLAG_INCLUDE_DEF) + self->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF; } mem_d(name); } @@ -1534,70 +1352,70 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) /* Arrays don't do this since there's no "array" value which spans across the * whole thing. */ - v = ir_builder_create_global(ir, self->name, self->expression.vtype); + v = ir_builder_create_global(ir, self->m_name, self->m_vtype); if (!v) { - compile_error(ast_ctx(self), "ir_builder_create_global failed on `%s`", self->name); + compile_error(self->m_context, "ir_builder_create_global failed on `%s`", self->m_name); return false; } codegen_output_type(self, v); - v->context = ast_ctx(self); + v->m_context = self->m_context; } /* link us to the ir_value */ - v->cvq = self->cvq; - self->ir_v = v; + v->m_cvq = self->m_cvq; + self->m_ir_v = v; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - self->ir_v->flags |= IR_FLAG_INCLUDE_DEF; - if (self->expression.flags & AST_FLAG_ERASEABLE) - self->ir_v->flags |= IR_FLAG_ERASABLE; + if (self->m_flags & AST_FLAG_INCLUDE_DEF) + self->m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF; + if (self->m_flags & AST_FLAG_ERASEABLE) + self->m_ir_v->m_flags |= IR_FLAG_ERASABLE; /* initialize */ - if (self->hasvalue) { - switch (self->expression.vtype) + if (self->m_hasvalue) { + switch (self->m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(v, self->constval.vfloat)) + if (!ir_value_set_float(v, self->m_constval.vfloat)) goto error; break; case TYPE_VECTOR: - if (!ir_value_set_vector(v, self->constval.vvec)) + if (!ir_value_set_vector(v, self->m_constval.vvec)) goto error; break; case TYPE_STRING: - if (!ir_value_set_string(v, self->constval.vstring)) + if (!ir_value_set_string(v, self->m_constval.vstring)) goto error; break; case TYPE_ARRAY: ast_global_array_set(self); break; case TYPE_FUNCTION: - compile_error(ast_ctx(self), "global of type function not properly generated"); + compile_error(self->m_context, "global of type function not properly generated"); goto error; /* Cannot generate an IR value for a function, * need a pointer pointing to a function rather. */ case TYPE_FIELD: - if (!self->constval.vfield) { - compile_error(ast_ctx(self), "field constant without vfield set"); + if (!self->m_constval.vfield) { + compile_error(self->m_context, "field constant without vfield set"); goto error; } - if (!self->constval.vfield->ir_v) { - compile_error(ast_ctx(self), "field constant generated before its field"); + if (!self->m_constval.vfield->m_ir_v) { + compile_error(self->m_context, "field constant generated before its field"); goto error; } - if (!ir_value_set_field(v, self->constval.vfield->ir_v)) + if (!ir_value_set_field(v, self->m_constval.vfield->m_ir_v)) goto error; break; default: - compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype); + compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype); break; } } return true; error: /* clean up */ - if(v) ir_value_delete(v); + if (v) delete v; return false; } @@ -1605,12 +1423,12 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) { ir_value *v = nullptr; - if (self->expression.vtype == TYPE_NIL) { - compile_error(ast_ctx(self), "internal error: trying to generate a variable of TYPE_NIL"); + if (self->m_vtype == TYPE_NIL) { + compile_error(self->m_context, "internal error: trying to generate a variable of TYPE_NIL"); return false; } - if (self->hasvalue && self->expression.vtype == TYPE_FUNCTION) + if (self->m_hasvalue && self->m_vtype == TYPE_FUNCTION) { /* Do we allow local functions? I think not... * this is NOT a function pointer atm. @@ -1618,18 +1436,18 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) return false; } - if (self->expression.vtype == TYPE_ARRAY) { + if (self->m_vtype == TYPE_ARRAY) { size_t ai; char *name; size_t namelen; - ast_expression *elemtype = self->expression.next; - int vtype = elemtype->vtype; + ast_expression *elemtype = self->m_next; + qc_type vtype = elemtype->m_vtype; - func->flags |= IR_FLAG_HAS_ARRAYS; + func->m_flags |= IR_FLAG_HAS_ARRAYS; - if (param && !(self->expression.flags & AST_FLAG_IS_VARARG)) { - compile_error(ast_ctx(self), "array-parameters are not supported"); + if (param && !(self->m_flags & AST_FLAG_IS_VARARG)) { + compile_error(self->m_context, "array-parameters are not supported"); return false; } @@ -1637,82 +1455,82 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) if (!check_array(self, self)) return false; - self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count); - if (!self->ir_values) { - compile_error(ast_ctx(self), "failed to allocate array values"); + self->m_ir_values = (ir_value**)mem_a(sizeof(self->m_ir_values[0]) * self->m_count); + if (!self->m_ir_values) { + compile_error(self->m_context, "failed to allocate array values"); return false; } - v = ir_function_create_local(func, self->name, vtype, param); + v = ir_function_create_local(func, self->m_name, vtype, param); if (!v) { - compile_error(ast_ctx(self), "internal error: ir_function_create_local failed"); + compile_error(self->m_context, "internal error: ir_function_create_local failed"); return false; } - v->context = ast_ctx(self); - v->unique_life = true; - v->locked = true; + v->m_context = self->m_context; + v->m_unique_life = true; + v->m_locked = true; - namelen = strlen(self->name); + namelen = strlen(self->m_name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + util_strncpy(name, self->m_name, namelen); - self->ir_values[0] = v; - for (ai = 1; ai < self->expression.count; ++ai) { + self->m_ir_values[0] = v; + for (ai = 1; ai < self->m_count; ++ai) { util_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); + self->m_ir_values[ai] = ir_function_create_local(func, name, vtype, param); + if (!self->m_ir_values[ai]) { + compile_error(self->m_context, "internal_error: ir_builder_create_global failed on `%s`", name); return false; } - self->ir_values[ai]->context = ast_ctx(self); - self->ir_values[ai]->unique_life = true; - self->ir_values[ai]->locked = true; + self->m_ir_values[ai]->m_context = self->m_context; + self->m_ir_values[ai]->m_unique_life = true; + self->m_ir_values[ai]->m_locked = true; } mem_d(name); } else { - v = ir_function_create_local(func, self->name, self->expression.vtype, param); + v = ir_function_create_local(func, self->m_name, self->m_vtype, param); if (!v) return false; codegen_output_type(self, v); - v->context = ast_ctx(self); + v->m_context = self->m_context; } /* A constant local... hmmm... * I suppose the IR will have to deal with this */ - if (self->hasvalue) { - switch (self->expression.vtype) + if (self->m_hasvalue) { + switch (self->m_vtype) { case TYPE_FLOAT: - if (!ir_value_set_float(v, self->constval.vfloat)) + if (!ir_value_set_float(v, self->m_constval.vfloat)) goto error; break; case TYPE_VECTOR: - if (!ir_value_set_vector(v, self->constval.vvec)) + if (!ir_value_set_vector(v, self->m_constval.vvec)) goto error; break; case TYPE_STRING: - if (!ir_value_set_string(v, self->constval.vstring)) + if (!ir_value_set_string(v, self->m_constval.vstring)) goto error; break; default: - compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype); + compile_error(self->m_context, "TODO: global constant type %i", self->m_vtype); break; } } /* link us to the ir_value */ - v->cvq = self->cvq; - self->ir_v = v; + v->m_cvq = self->m_cvq; + self->m_ir_v = v; - if (!ast_generate_accessors(self, func->owner)) + if (!ast_generate_accessors(self, func->m_owner)) return false; return true; error: /* clean up */ - ir_value_delete(v); + delete v; return false; } @@ -1720,47 +1538,46 @@ bool ast_generate_accessors(ast_value *self, ir_builder *ir) { size_t i; bool warn = OPTS_WARN(WARN_USED_UNINITIALIZED); - if (!self->setter || !self->getter) + if (!self->m_setter || !self->m_getter) return true; - for (i = 0; i < self->expression.count; ++i) { - if (!self->ir_values) { - compile_error(ast_ctx(self), "internal error: no array values generated for `%s`", self->name); + for (i = 0; i < self->m_count; ++i) { + if (!self->m_ir_values) { + compile_error(self->m_context, "internal error: no array values generated for `%s`", self->m_name); return false; } - if (!self->ir_values[i]) { - compile_error(ast_ctx(self), "internal error: not all array values have been generated for `%s`", self->name); + if (!self->m_ir_values[i]) { + compile_error(self->m_context, "internal error: not all array values have been generated for `%s`", self->m_name); return false; } - if (self->ir_values[i]->life) { - compile_error(ast_ctx(self), "internal error: function containing `%s` already generated", self->name); + if (!self->m_ir_values[i]->m_life.empty()) { + compile_error(self->m_context, "internal error: function containing `%s` already generated", self->m_name); return false; } } opts_set(opts.warn, WARN_USED_UNINITIALIZED, false); - if (self->setter) { - if (!ast_global_codegen (self->setter, ir, false) || - !ast_function_codegen(self->setter->constval.vfunc, ir) || - !ir_function_finalize(self->setter->constval.vfunc->ir_func)) + if (self->m_setter) { + if (!ast_global_codegen (self->m_setter, ir, false) || + !ast_function_codegen(self->m_setter->m_constval.vfunc, ir) || + !ir_function_finalize(self->m_setter->m_constval.vfunc->m_ir_func)) { - compile_error(ast_ctx(self), "internal error: failed to generate setter for `%s`", self->name); + compile_error(self->m_context, "internal error: failed to generate setter for `%s`", self->m_name); opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn); return false; } } - if (self->getter) { - if (!ast_global_codegen (self->getter, ir, false) || - !ast_function_codegen(self->getter->constval.vfunc, ir) || - !ir_function_finalize(self->getter->constval.vfunc->ir_func)) + if (self->m_getter) { + if (!ast_global_codegen (self->m_getter, ir, false) || + !ast_function_codegen(self->m_getter->m_constval.vfunc, ir) || + !ir_function_finalize(self->m_getter->m_constval.vfunc->m_ir_func)) { - compile_error(ast_ctx(self), "internal error: failed to generate getter for `%s`", self->name); + compile_error(self->m_context, "internal error: failed to generate getter for `%s`", self->m_name); opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn); return false; } } - for (i = 0; i < self->expression.count; ++i) { - vec_free(self->ir_values[i]->life); - } + for (i = 0; i < self->m_count; ++i) + self->m_ir_values[i]->m_life.clear(); opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn); return true; } @@ -1774,106 +1591,106 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir) (void)ir; - irf = self->ir_func; + irf = self->m_ir_func; if (!irf) { - compile_error(ast_ctx(self), "internal error: ast_function's related ast_value was not generated yet"); + compile_error(self->m_context, "internal error: ast_function's related ast_value was not generated yet"); return false; } /* fill the parameter list */ - ec = &self->vtype->expression; - for (auto &it : ec->params) { - if (it->expression.vtype == TYPE_FIELD) - vec_push(irf->params, it->expression.next->vtype); + ec = self->m_function_type; + for (auto &it : ec->m_type_params) { + if (it->m_vtype == TYPE_FIELD) + vec_push(irf->m_params, it->m_next->m_vtype); else - vec_push(irf->params, it->expression.vtype); - if (!self->builtin) { - if (!ast_local_codegen(it, self->ir_func, true)) + vec_push(irf->m_params, it->m_vtype); + if (!self->m_builtin) { + if (!ast_local_codegen(it, self->m_ir_func, true)) return false; } } - if (self->varargs) { - if (!ast_local_codegen(self->varargs, self->ir_func, true)) + if (self->m_varargs) { + if (!ast_local_codegen(self->m_varargs, self->m_ir_func, true)) return false; - irf->max_varargs = self->varargs->expression.count; + irf->m_max_varargs = self->m_varargs->m_count; } - if (self->builtin) { - irf->builtin = self->builtin; + if (self->m_builtin) { + irf->m_builtin = self->m_builtin; return true; } /* have a local return value variable? */ - if (self->return_value) { - if (!ast_local_codegen(self->return_value, self->ir_func, false)) + if (self->m_return_value) { + if (!ast_local_codegen(self->m_return_value, self->m_ir_func, false)) return false; } - if (self->blocks.empty()) { - compile_error(ast_ctx(self), "function `%s` has no body", self->name); + if (self->m_blocks.empty()) { + compile_error(self->m_context, "function `%s` has no body", self->m_name); return false; } - irf->first = self->curblock = ir_function_create_block(ast_ctx(self), irf, "entry"); - if (!self->curblock) { - compile_error(ast_ctx(self), "failed to allocate entry block for `%s`", self->name); + irf->m_first = self->m_curblock = ir_function_create_block(self->m_context, irf, "entry"); + if (!self->m_curblock) { + compile_error(self->m_context, "failed to allocate entry block for `%s`", self->m_name); return false; } - if (self->argc) { + if (self->m_argc) { ir_value *va_count; ir_value *fixed; ir_value *sub; - if (!ast_local_codegen(self->argc, self->ir_func, true)) + if (!ast_local_codegen(self->m_argc, self->m_ir_func, true)) return false; - cgen = self->argc->expression.codegen; - if (!(*cgen)((ast_expression*)(self->argc), self, false, &va_count)) + cgen = self->m_argc->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_argc), self, false, &va_count)) return false; - cgen = self->fixedparams->expression.codegen; - if (!(*cgen)((ast_expression*)(self->fixedparams), self, false, &fixed)) + cgen = self->m_fixedparams->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_fixedparams), self, false, &fixed)) return false; - sub = ir_block_create_binop(self->curblock, ast_ctx(self), + sub = ir_block_create_binop(self->m_curblock, self->m_context, ast_function_label(self, "va_count"), INSTR_SUB_F, ir_builder_get_va_count(ir), fixed); if (!sub) return false; - if (!ir_block_create_store_op(self->curblock, ast_ctx(self), INSTR_STORE_F, + if (!ir_block_create_store_op(self->m_curblock, self->m_context, INSTR_STORE_F, va_count, sub)) { return false; } } - for (auto &it : self->blocks) { - cgen = it->expression.codegen; - if (!(*cgen)((ast_expression*)it, self, false, &dummy)) + for (auto &it : self->m_blocks) { + cgen = it->m_codegen; + if (!(*cgen)(it.get(), self, false, &dummy)) return false; } /* TODO: check return types */ - if (!self->curblock->final) + if (!self->m_curblock->m_final) { - if (!self->vtype->expression.next || - self->vtype->expression.next->vtype == TYPE_VOID) + if (!self->m_function_type->m_next || + self->m_function_type->m_next->m_vtype == TYPE_VOID) { - return ir_block_create_return(self->curblock, ast_ctx(self), nullptr); + return ir_block_create_return(self->m_curblock, self->m_context, nullptr); } - else if (vec_size(self->curblock->entries) || self->curblock == irf->first) + else if (vec_size(self->m_curblock->m_entries) || self->m_curblock == irf->m_first) { - if (self->return_value) { - cgen = self->return_value->expression.codegen; - if (!(*cgen)((ast_expression*)(self->return_value), self, false, &dummy)) + if (self->m_return_value) { + cgen = self->m_return_value->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_return_value), self, false, &dummy)) return false; - return ir_block_create_return(self->curblock, ast_ctx(self), dummy); + return ir_block_create_return(self->m_curblock, self->m_context, dummy); } - else if (compile_warning(ast_ctx(self), WARN_MISSING_RETURN_VALUES, + else if (compile_warning(self->m_context, WARN_MISSING_RETURN_VALUES, "control reaches end of non-void function (`%s`) via %s", - self->name, self->curblock->label)) + self->m_name, self->m_curblock->m_label.c_str())) { return false; } - return ir_block_create_return(self->curblock, ast_ctx(self), nullptr); + return ir_block_create_return(self->m_curblock, self->m_context, nullptr); } } return true; @@ -1883,7 +1700,7 @@ static bool starts_a_label(ast_expression *ex) { while (ex && ast_istype(ex, ast_block)) { ast_block *b = (ast_block*)ex; - ex = b->exprs[0]; + ex = b->m_exprs[0]; } if (!ex) return false; @@ -1903,12 +1720,12 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu * of the form: (a, b, c) = x should not assign to c... */ if (lvalue) { - compile_error(ast_ctx(self), "not an l-value (code-block)"); + compile_error(self->m_context, "not an l-value (code-block)"); return false; } - if (self->expression.outr) { - *out = self->expression.outr; + if (self->m_outr) { + *out = self->m_outr; return true; } @@ -1921,27 +1738,27 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu *out = nullptr; /* generate locals */ - for (auto &it : self->locals) { - if (!ast_local_codegen(it, func->ir_func, false)) { + for (auto &it : self->m_locals) { + if (!ast_local_codegen(it, func->m_ir_func, false)) { if (OPTS_OPTION_BOOL(OPTION_DEBUG)) - compile_error(ast_ctx(self), "failed to generate local `%s`", it->name); + compile_error(self->m_context, "failed to generate local `%s`", it->m_name); return false; } } - for (auto &it : self->exprs) { + for (auto &it : self->m_exprs) { ast_expression_codegen *gen; - if (func->curblock->final && !starts_a_label(it)) { - if (compile_warning(ast_ctx(it), WARN_UNREACHABLE_CODE, "unreachable statement")) + if (func->m_curblock->m_final && !starts_a_label(it)) { + if (compile_warning(it->m_context, WARN_UNREACHABLE_CODE, "unreachable statement")) return false; continue; } - gen = it->codegen; + gen = it->m_codegen; if (!(*gen)(it, func, false, out)) return false; } - self->expression.outr = *out; + self->m_outr = *out; return true; } @@ -1956,23 +1773,23 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu ast_value *idx = 0; ast_array_index *ai = nullptr; - if (lvalue && self->expression.outl) { - *out = self->expression.outl; + if (lvalue && self->m_outl) { + *out = self->m_outl; return true; } - if (!lvalue && self->expression.outr) { - *out = self->expression.outr; + if (!lvalue && self->m_outr) { + *out = self->m_outr; return true; } - if (ast_istype(self->dest, ast_array_index)) + if (ast_istype(self->m_dest, ast_array_index)) { - ai = (ast_array_index*)self->dest; - idx = (ast_value*)ai->index; + ai = (ast_array_index*)self->m_dest; + idx = (ast_value*)ai->m_index; - if (ast_istype(ai->index, ast_value) && idx->hasvalue && idx->cvq == CV_CONST) + if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST) ai = nullptr; } @@ -1982,53 +1799,53 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu ir_instr *call; if (lvalue) { - compile_error(ast_ctx(self), "array-subscript assignment cannot produce lvalues"); + compile_error(self->m_context, "array-subscript assignment cannot produce lvalues"); return false; } - arr = (ast_value*)ai->array; - if (!ast_istype(ai->array, ast_value) || !arr->setter) { - compile_error(ast_ctx(self), "value has no setter (%s)", arr->name); + arr = (ast_value*)ai->m_array; + if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) { + compile_error(self->m_context, "value has no setter (%s)", arr->m_name); return false; } - cgen = idx->expression.codegen; + cgen = idx->m_codegen; if (!(*cgen)((ast_expression*)(idx), func, false, &iridx)) return false; - cgen = arr->setter->expression.codegen; - if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval)) + cgen = arr->m_setter->m_codegen; + if (!(*cgen)((ast_expression*)(arr->m_setter), func, true, &funval)) return false; - cgen = self->source->codegen; - if (!(*cgen)((ast_expression*)(self->source), func, false, &right)) + cgen = self->m_source->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right)) return false; - call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval, false); + call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "store"), funval, false); if (!call) return false; ir_call_param(call, iridx); ir_call_param(call, right); - self->expression.outr = right; + self->m_outr = right; } else { /* regular code */ - cgen = self->dest->codegen; + cgen = self->m_dest->m_codegen; /* lvalue! */ - if (!(*cgen)((ast_expression*)(self->dest), func, true, &left)) + if (!(*cgen)((ast_expression*)(self->m_dest), func, true, &left)) return false; - self->expression.outl = left; + self->m_outl = left; - cgen = self->source->codegen; + cgen = self->m_source->m_codegen; /* rvalue! */ - if (!(*cgen)((ast_expression*)(self->source), func, false, &right)) + if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right)) return false; - if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->op, left, right)) + if (!ir_block_create_store_op(func->m_curblock, self->m_context, self->m_op, left, right)) return false; - self->expression.outr = right; + self->m_outr = right; } /* Theoretically, an assinment returns its left side as an @@ -2050,17 +1867,17 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va /* A binary operation cannot yield an l-value */ if (lvalue) { - compile_error(ast_ctx(self), "not an l-value (binop)"); + compile_error(self->m_context, "not an l-value (binop)"); return false; } - if (self->expression.outr) { - *out = self->expression.outr; + if (self->m_outr) { + *out = self->m_outr; return true; } if ((OPTS_FLAG(SHORT_LOGIC) || OPTS_FLAG(PERL_LOGIC)) && - (self->op == INSTR_AND || self->op == INSTR_OR)) + (self->m_op == INSTR_AND || self->m_op == INSTR_OR)) { /* NOTE: The short-logic path will ignore right_first */ @@ -2071,50 +1888,54 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va size_t merge_id; /* prepare end-block */ - merge_id = vec_size(func->ir_func->blocks); - merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge")); + merge_id = func->m_ir_func->m_blocks.size(); + merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "sce_merge")); /* generate the left expression */ - cgen = self->left->codegen; - if (!(*cgen)((ast_expression*)(self->left), func, false, &left)) + cgen = self->m_left->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left)) return false; /* remember the block */ - from_left = func->curblock; + from_left = func->m_curblock; /* create a new block for the right expression */ - other = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_other")); - if (self->op == INSTR_AND) { + other = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "sce_other")); + if (self->m_op == INSTR_AND) { /* on AND: left==true -> other */ - if (!ir_block_create_if(func->curblock, ast_ctx(self), left, other, merge)) + if (!ir_block_create_if(func->m_curblock, self->m_context, left, other, merge)) return false; } else { /* on OR: left==false -> other */ - if (!ir_block_create_if(func->curblock, ast_ctx(self), left, merge, other)) + if (!ir_block_create_if(func->m_curblock, self->m_context, left, merge, other)) return false; } /* use the likely flag */ - vec_last(func->curblock->instr)->likely = true; + vec_last(func->m_curblock->m_instr)->m_likely = true; /* enter the right-expression's block */ - func->curblock = other; + func->m_curblock = other; /* generate */ - cgen = self->right->codegen; - if (!(*cgen)((ast_expression*)(self->right), func, false, &right)) + cgen = self->m_right->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right)) return false; /* remember block */ - from_right = func->curblock; + from_right = func->m_curblock; /* jump to the merge block */ - if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge)) + if (!ir_block_create_jump(func->m_curblock, self->m_context, merge)) return false; - vec_remove(func->ir_func->blocks, merge_id, 1); - vec_push(func->ir_func->blocks, merge); + algo::shiftback(func->m_ir_func->m_blocks.begin() + merge_id, + func->m_ir_func->m_blocks.end()); + // FIXME::DELME:: + //func->m_ir_func->m_blocks[merge_id].release(); + //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + merge_id); + //func->m_ir_func->m_blocks.emplace_back(merge); - func->curblock = merge; - phi = ir_block_create_phi(func->curblock, ast_ctx(self), + func->m_curblock = merge; + phi = ir_block_create_phi(func->m_curblock, self->m_context, ast_function_label(func, "sce_value"), - self->expression.vtype); + self->m_vtype); ir_phi_add(phi, from_left, left); ir_phi_add(phi, from_right, right); *out = ir_phi_value(phi); @@ -2123,32 +1944,32 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va if (!OPTS_FLAG(PERL_LOGIC)) { /* cast-to-bool */ - if (OPTS_FLAG(CORRECT_LOGIC) && (*out)->vtype == TYPE_VECTOR) { - *out = ir_block_create_unary(func->curblock, ast_ctx(self), + if (OPTS_FLAG(CORRECT_LOGIC) && (*out)->m_vtype == TYPE_VECTOR) { + *out = ir_block_create_unary(func->m_curblock, self->m_context, ast_function_label(func, "sce_bool_v"), INSTR_NOT_V, *out); if (!*out) return false; - *out = ir_block_create_unary(func->curblock, ast_ctx(self), + *out = ir_block_create_unary(func->m_curblock, self->m_context, ast_function_label(func, "sce_bool"), INSTR_NOT_F, *out); if (!*out) return false; } - else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && (*out)->vtype == TYPE_STRING) { - *out = ir_block_create_unary(func->curblock, ast_ctx(self), + else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && (*out)->m_vtype == TYPE_STRING) { + *out = ir_block_create_unary(func->m_curblock, self->m_context, ast_function_label(func, "sce_bool_s"), INSTR_NOT_S, *out); if (!*out) return false; - *out = ir_block_create_unary(func->curblock, ast_ctx(self), + *out = ir_block_create_unary(func->m_curblock, self->m_context, ast_function_label(func, "sce_bool"), INSTR_NOT_F, *out); if (!*out) return false; } else { - *out = ir_block_create_binop(func->curblock, ast_ctx(self), + *out = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "sce_bool"), INSTR_AND, *out, *out); if (!*out) @@ -2156,32 +1977,32 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va } } - self->expression.outr = *out; + self->m_outr = *out; codegen_output_type(self, *out); return true; } - if (self->right_first) { - cgen = self->right->codegen; - if (!(*cgen)((ast_expression*)(self->right), func, false, &right)) + if (self->m_right_first) { + cgen = self->m_right->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right)) return false; - cgen = self->left->codegen; - if (!(*cgen)((ast_expression*)(self->left), func, false, &left)) + cgen = self->m_left->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left)) return false; } else { - cgen = self->left->codegen; - if (!(*cgen)((ast_expression*)(self->left), func, false, &left)) + cgen = self->m_left->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_left), func, false, &left)) return false; - cgen = self->right->codegen; - if (!(*cgen)((ast_expression*)(self->right), func, false, &right)) + cgen = self->m_right->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_right), func, false, &right)) return false; } - *out = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "bin"), - self->op, left, right); + *out = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "bin"), + self->m_op, left, right); if (!*out) return false; - self->expression.outr = *out; + self->m_outr = *out; codegen_output_type(self, *out); return true; @@ -2197,47 +2018,46 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i ast_array_index *ai = nullptr; ir_value *iridx = nullptr; - if (lvalue && self->expression.outl) { - *out = self->expression.outl; + if (lvalue && self->m_outl) { + *out = self->m_outl; return true; } - if (!lvalue && self->expression.outr) { - *out = self->expression.outr; + if (!lvalue && self->m_outr) { + *out = self->m_outr; return true; } - if (ast_istype(self->dest, ast_array_index)) + if (ast_istype(self->m_dest, ast_array_index)) { - ai = (ast_array_index*)self->dest; - idx = (ast_value*)ai->index; + ai = (ast_array_index*)self->m_dest; + idx = (ast_value*)ai->m_index; - if (ast_istype(ai->index, ast_value) && idx->hasvalue && idx->cvq == CV_CONST) + if (ast_istype(ai->m_index, ast_value) && idx->m_hasvalue && idx->m_cvq == CV_CONST) ai = nullptr; } /* for a binstore we need both an lvalue and an rvalue for the left side */ /* rvalue of destination! */ if (ai) { - cgen = idx->expression.codegen; + cgen = idx->m_codegen; if (!(*cgen)((ast_expression*)(idx), func, false, &iridx)) return false; } - cgen = self->dest->codegen; - if (!(*cgen)((ast_expression*)(self->dest), func, false, &leftr)) + cgen = self->m_dest->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_dest), func, false, &leftr)) return false; /* source as rvalue only */ - cgen = self->source->codegen; - if (!(*cgen)((ast_expression*)(self->source), func, false, &right)) + cgen = self->m_source->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_source), func, false, &right)) return false; /* now the binary */ - bin = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "binst"), - self->opbin, leftr, right); - self->expression.outr = bin; - + bin = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "binst"), + self->m_opbin, leftr, right); + self->m_outr = bin; if (ai) { /* we need to call the setter */ @@ -2245,37 +2065,37 @@ bool ast_binstore_codegen(ast_binstore *self, ast_function *func, bool lvalue, i ir_instr *call; if (lvalue) { - compile_error(ast_ctx(self), "array-subscript assignment cannot produce lvalues"); + compile_error(self->m_context, "array-subscript assignment cannot produce lvalues"); return false; } - arr = (ast_value*)ai->array; - if (!ast_istype(ai->array, ast_value) || !arr->setter) { - compile_error(ast_ctx(self), "value has no setter (%s)", arr->name); + arr = (ast_value*)ai->m_array; + if (!ast_istype(ai->m_array, ast_value) || !arr->m_setter) { + compile_error(self->m_context, "value has no setter (%s)", arr->m_name); return false; } - cgen = arr->setter->expression.codegen; - if (!(*cgen)((ast_expression*)(arr->setter), func, true, &funval)) + cgen = arr->m_setter->m_codegen; + if (!(*cgen)((ast_expression*)(arr->m_setter), func, true, &funval)) return false; - call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "store"), funval, false); + call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "store"), funval, false); if (!call) return false; ir_call_param(call, iridx); ir_call_param(call, bin); - self->expression.outr = bin; + self->m_outr = bin; } else { /* now store them */ - cgen = self->dest->codegen; + cgen = self->m_dest->m_codegen; /* lvalue of destination */ - if (!(*cgen)((ast_expression*)(self->dest), func, true, &leftl)) + if (!(*cgen)((ast_expression*)(self->m_dest), func, true, &leftl)) return false; - self->expression.outl = leftl; + self->m_outl = leftl; - if (!ir_block_create_store_op(func->curblock, ast_ctx(self), self->opstore, leftl, bin)) + if (!ir_block_create_store_op(func->m_curblock, self->m_context, self->m_opstore, leftl, bin)) return false; - self->expression.outr = bin; + self->m_outr = bin; } /* Theoretically, an assinment returns its left side as an @@ -2297,25 +2117,25 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu /* An unary operation cannot yield an l-value */ if (lvalue) { - compile_error(ast_ctx(self), "not an l-value (binop)"); + compile_error(self->m_context, "not an l-value (binop)"); return false; } - if (self->expression.outr) { - *out = self->expression.outr; + if (self->m_outr) { + *out = self->m_outr; return true; } - cgen = self->operand->codegen; + cgen = self->m_operand->m_codegen; /* lvalue! */ - if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand)) + if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &operand)) return false; - *out = ir_block_create_unary(func->curblock, ast_ctx(self), ast_function_label(func, "unary"), - self->op, operand); + *out = ir_block_create_unary(func->m_curblock, self->m_context, ast_function_label(func, "unary"), + self->m_op, operand); if (!*out) return false; - self->expression.outr = *out; + self->m_outr = *out; return true; } @@ -2331,26 +2151,26 @@ bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_va * anything... */ if (lvalue) { - compile_error(ast_ctx(self), "return-expression is not an l-value"); + compile_error(self->m_context, "return-expression is not an l-value"); return false; } - if (self->expression.outr) { - compile_error(ast_ctx(self), "internal error: ast_return cannot be reused, it bears no result!"); + if (self->m_outr) { + compile_error(self->m_context, "internal error: ast_return cannot be reused, it bears no result!"); return false; } - self->expression.outr = (ir_value*)1; + self->m_outr = (ir_value*)1; - if (self->operand) { - cgen = self->operand->codegen; + if (self->m_operand) { + cgen = self->m_operand->m_codegen; /* lvalue! */ - if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand)) + if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &operand)) return false; - if (!ir_block_create_return(func->curblock, ast_ctx(self), operand)) + if (!ir_block_create_return(func->m_curblock, self->m_context, operand)) return false; } else { - if (!ir_block_create_return(func->curblock, ast_ctx(self), nullptr)) + if (!ir_block_create_return(func->m_curblock, self->m_context, nullptr)) return false; } @@ -2367,48 +2187,48 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i * value in a temp. */ - if (lvalue && self->expression.outl) { - *out = self->expression.outl; + if (lvalue && self->m_outl) { + *out = self->m_outl; return true; } - if (!lvalue && self->expression.outr) { - *out = self->expression.outr; + if (!lvalue && self->m_outr) { + *out = self->m_outr; return true; } - cgen = self->entity->codegen; - if (!(*cgen)((ast_expression*)(self->entity), func, false, &ent)) + cgen = self->m_entity->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_entity), func, false, &ent)) return false; - cgen = self->field->codegen; - if (!(*cgen)((ast_expression*)(self->field), func, false, &field)) + cgen = self->m_field->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_field), func, false, &field)) return false; if (lvalue) { /* address! */ - *out = ir_block_create_fieldaddress(func->curblock, ast_ctx(self), ast_function_label(func, "efa"), + *out = ir_block_create_fieldaddress(func->m_curblock, self->m_context, ast_function_label(func, "efa"), ent, field); } else { - *out = ir_block_create_load_from_ent(func->curblock, ast_ctx(self), ast_function_label(func, "efv"), - ent, field, self->expression.vtype); + *out = ir_block_create_load_from_ent(func->m_curblock, self->m_context, ast_function_label(func, "efv"), + ent, field, self->m_vtype); /* Done AFTER error checking: codegen_output_type(self, *out); */ } if (!*out) { - compile_error(ast_ctx(self), "failed to create %s instruction (output type %s)", + compile_error(self->m_context, "failed to create %s instruction (output type %s)", (lvalue ? "ADDRESS" : "FIELD"), - type_name[self->expression.vtype]); + type_name[self->m_vtype]); return false; } if (!lvalue) codegen_output_type(self, *out); if (lvalue) - self->expression.outl = *out; + self->m_outl = *out; else - self->expression.outr = *out; + self->m_outr = *out; /* Hm that should be it... */ return true; @@ -2420,27 +2240,27 @@ bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_va ir_value *vec; /* in QC this is always an lvalue */ - if (lvalue && self->rvalue) { - compile_error(ast_ctx(self), "not an l-value (member access)"); + if (lvalue && self->m_rvalue) { + compile_error(self->m_context, "not an l-value (member access)"); return false; } - if (self->expression.outl) { - *out = self->expression.outl; + if (self->m_outl) { + *out = self->m_outl; return true; } - cgen = self->owner->codegen; - if (!(*cgen)((ast_expression*)(self->owner), func, false, &vec)) + cgen = self->m_owner->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_owner), func, false, &vec)) return false; - if (vec->vtype != TYPE_VECTOR && - !(vec->vtype == TYPE_FIELD && self->owner->next->vtype == TYPE_VECTOR)) + if (vec->m_vtype != TYPE_VECTOR && + !(vec->m_vtype == TYPE_FIELD && self->m_owner->m_next->m_vtype == TYPE_VECTOR)) { return false; } - *out = ir_value_vector_member(vec, self->field); - self->expression.outl = *out; + *out = ir_value_vector_member(vec, self->m_field); + self->m_outl = *out; return (*out != nullptr); } @@ -2450,17 +2270,17 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva ast_value *arr; ast_value *idx; - if (!lvalue && self->expression.outr) { - *out = self->expression.outr; + if (!lvalue && self->m_outr) { + *out = self->m_outr; return true; } - if (lvalue && self->expression.outl) { - *out = self->expression.outl; + if (lvalue && self->m_outl) { + *out = self->m_outl; return true; } - if (!ast_istype(self->array, ast_value)) { - compile_error(ast_ctx(self), "array indexing this way is not supported"); + if (!ast_istype(self->m_array, ast_value)) { + compile_error(self->m_context, "array indexing this way is not supported"); /* note this would actually be pointer indexing because the left side is * not an actual array but (hopefully) an indexable expression. * Once we get integer arithmetic, and GADDRESS/GSTORE/GLOAD instruction @@ -2469,68 +2289,68 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva return false; } - arr = (ast_value*)self->array; - idx = (ast_value*)self->index; + arr = (ast_value*)self->m_array; + idx = (ast_value*)self->m_index; - if (!ast_istype(self->index, ast_value) || !idx->hasvalue || idx->cvq != CV_CONST) { + if (!ast_istype(self->m_index, ast_value) || !idx->m_hasvalue || idx->m_cvq != CV_CONST) { /* Time to use accessor functions */ ast_expression_codegen *cgen; ir_value *iridx, *funval; ir_instr *call; if (lvalue) { - compile_error(ast_ctx(self), "(.2) array indexing here needs a compile-time constant"); + compile_error(self->m_context, "(.2) array indexing here needs a compile-time constant"); return false; } - if (!arr->getter) { - compile_error(ast_ctx(self), "value has no getter, don't know how to index it"); + if (!arr->m_getter) { + compile_error(self->m_context, "value has no getter, don't know how to index it"); return false; } - cgen = self->index->codegen; - if (!(*cgen)((ast_expression*)(self->index), func, false, &iridx)) + cgen = self->m_index->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_index), func, false, &iridx)) return false; - cgen = arr->getter->expression.codegen; - if (!(*cgen)((ast_expression*)(arr->getter), func, true, &funval)) + cgen = arr->m_getter->m_codegen; + if (!(*cgen)((ast_expression*)(arr->m_getter), func, true, &funval)) return false; - call = ir_block_create_call(func->curblock, ast_ctx(self), ast_function_label(func, "fetch"), funval, false); + call = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "fetch"), funval, false); if (!call) return false; ir_call_param(call, iridx); *out = ir_call_value(call); - self->expression.outr = *out; - (*out)->vtype = self->expression.vtype; + self->m_outr = *out; + (*out)->m_vtype = self->m_vtype; codegen_output_type(self, *out); return true; } - if (idx->expression.vtype == TYPE_FLOAT) { - unsigned int arridx = idx->constval.vfloat; - if (arridx >= self->array->count) + if (idx->m_vtype == TYPE_FLOAT) { + unsigned int arridx = idx->m_constval.vfloat; + if (arridx >= self->m_array->m_count) { - compile_error(ast_ctx(self), "array index out of bounds: %i", arridx); + compile_error(self->m_context, "array index out of bounds: %i", arridx); return false; } - *out = arr->ir_values[arridx]; + *out = arr->m_ir_values[arridx]; } - else if (idx->expression.vtype == TYPE_INTEGER) { - unsigned int arridx = idx->constval.vint; - if (arridx >= self->array->count) + else if (idx->m_vtype == TYPE_INTEGER) { + unsigned int arridx = idx->m_constval.vint; + if (arridx >= self->m_array->m_count) { - compile_error(ast_ctx(self), "array index out of bounds: %i", arridx); + compile_error(self->m_context, "array index out of bounds: %i", arridx); return false; } - *out = arr->ir_values[arridx]; + *out = arr->m_ir_values[arridx]; } else { - compile_error(ast_ctx(self), "array indexing here needs an integer constant"); + compile_error(self->m_context, "array indexing here needs an integer constant"); return false; } - (*out)->vtype = self->expression.vtype; + (*out)->m_vtype = self->m_vtype; codegen_output_type(self, *out); return true; } @@ -2539,12 +2359,12 @@ bool ast_argpipe_codegen(ast_argpipe *self, ast_function *func, bool lvalue, ir_ { *out = nullptr; if (lvalue) { - compile_error(ast_ctx(self), "argpipe node: not an lvalue"); + compile_error(self->m_context, "argpipe node: not an lvalue"); return false; } (void)func; (void)out; - compile_error(ast_ctx(self), "TODO: argpipe codegen not implemented"); + compile_error(self->m_context, "TODO: argpipe codegen not implemented"); return false; } @@ -2567,81 +2387,81 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va (void)out; (void)lvalue; - if (self->expression.outr) { - compile_error(ast_ctx(self), "internal error: ast_ifthen cannot be reused, it bears no result!"); + if (self->m_outr) { + compile_error(self->m_context, "internal error: ast_ifthen cannot be reused, it bears no result!"); return false; } - self->expression.outr = (ir_value*)1; + self->m_outr = (ir_value*)1; /* generate the condition */ - cgen = self->cond->codegen; - if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval)) + cgen = self->m_cond->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_cond), func, false, &condval)) return false; /* update the block which will get the jump - because short-logic or ternaries may have changed this */ - cond = func->curblock; + cond = func->m_curblock; /* try constant folding away the condition */ if ((folded = fold::cond_ifthen(condval, func, self)) != -1) return folded; - if (self->on_true) { + if (self->m_on_true) { /* create on-true block */ - ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "ontrue")); + ontrue = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "ontrue")); if (!ontrue) return false; /* enter the block */ - func->curblock = ontrue; + func->m_curblock = ontrue; /* generate */ - cgen = self->on_true->codegen; - if (!(*cgen)((ast_expression*)(self->on_true), func, false, &dummy)) + cgen = self->m_on_true->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_on_true), func, false, &dummy)) return false; /* we now need to work from the current endpoint */ - ontrue_endblock = func->curblock; + ontrue_endblock = func->m_curblock; } else ontrue = nullptr; /* on-false path */ - if (self->on_false) { + if (self->m_on_false) { /* create on-false block */ - onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "onfalse")); + onfalse = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "onfalse")); if (!onfalse) return false; /* enter the block */ - func->curblock = onfalse; + func->m_curblock = onfalse; /* generate */ - cgen = self->on_false->codegen; - if (!(*cgen)((ast_expression*)(self->on_false), func, false, &dummy)) + cgen = self->m_on_false->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_on_false), func, false, &dummy)) return false; /* we now need to work from the current endpoint */ - onfalse_endblock = func->curblock; + onfalse_endblock = func->m_curblock; } else onfalse = nullptr; /* Merge block were they all merge in to */ - if (!ontrue || !onfalse || !ontrue_endblock->final || !onfalse_endblock->final) + if (!ontrue || !onfalse || !ontrue_endblock->m_final || !onfalse_endblock->m_final) { - merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "endif")); + merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "endif")); if (!merge) return false; /* add jumps ot the merge block */ - if (ontrue && !ontrue_endblock->final && !ir_block_create_jump(ontrue_endblock, ast_ctx(self), merge)) + if (ontrue && !ontrue_endblock->m_final && !ir_block_create_jump(ontrue_endblock, self->m_context, merge)) return false; - if (onfalse && !onfalse_endblock->final && !ir_block_create_jump(onfalse_endblock, ast_ctx(self), merge)) + if (onfalse && !onfalse_endblock->m_final && !ir_block_create_jump(onfalse_endblock, self->m_context, merge)) return false; /* Now enter the merge block */ - func->curblock = merge; + func->m_curblock = merge; } /* we create the if here, that way all blocks are ordered :) */ - if (!ir_block_create_if(cond, ast_ctx(self), condval, + if (!ir_block_create_if(cond, self->m_context, condval, (ontrue ? ontrue : merge), (onfalse ? onfalse : merge))) { @@ -2659,7 +2479,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ ir_value *trueval, *falseval; ir_instr *phi; - ir_block *cond = func->curblock; + ir_block *cond = func->m_curblock; ir_block *cond_out = nullptr; ir_block *ontrue, *ontrue_out = nullptr; ir_block *onfalse, *onfalse_out = nullptr; @@ -2675,95 +2495,95 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ * may still happen, thus we remember a created ir_value and simply return one * if it already exists. */ - if (self->expression.outr) { - *out = self->expression.outr; + if (self->m_outr) { + *out = self->m_outr; return true; } /* In the following, contraty to ast_ifthen, we assume both paths exist. */ /* generate the condition */ - func->curblock = cond; - cgen = self->cond->codegen; - if (!(*cgen)((ast_expression*)(self->cond), func, false, &condval)) + func->m_curblock = cond; + cgen = self->m_cond->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_cond), func, false, &condval)) return false; - cond_out = func->curblock; + cond_out = func->m_curblock; /* try constant folding away the condition */ if ((folded = fold::cond_ternary(condval, func, self)) != -1) return folded; /* create on-true block */ - ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_T")); + ontrue = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_T")); if (!ontrue) return false; else { /* enter the block */ - func->curblock = ontrue; + func->m_curblock = ontrue; /* generate */ - cgen = self->on_true->codegen; - if (!(*cgen)((ast_expression*)(self->on_true), func, false, &trueval)) + cgen = self->m_on_true->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_on_true), func, false, &trueval)) return false; - ontrue_out = func->curblock; + ontrue_out = func->m_curblock; } /* create on-false block */ - onfalse = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_F")); + onfalse = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_F")); if (!onfalse) return false; else { /* enter the block */ - func->curblock = onfalse; + func->m_curblock = onfalse; /* generate */ - cgen = self->on_false->codegen; - if (!(*cgen)((ast_expression*)(self->on_false), func, false, &falseval)) + cgen = self->m_on_false->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_on_false), func, false, &falseval)) return false; - onfalse_out = func->curblock; + onfalse_out = func->m_curblock; } /* create merge block */ - merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_out")); + merge = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "tern_out")); if (!merge) return false; /* jump to merge block */ - if (!ir_block_create_jump(ontrue_out, ast_ctx(self), merge)) + if (!ir_block_create_jump(ontrue_out, self->m_context, merge)) return false; - if (!ir_block_create_jump(onfalse_out, ast_ctx(self), merge)) + if (!ir_block_create_jump(onfalse_out, self->m_context, merge)) return false; /* create if instruction */ - if (!ir_block_create_if(cond_out, ast_ctx(self), condval, ontrue, onfalse)) + if (!ir_block_create_if(cond_out, self->m_context, condval, ontrue, onfalse)) return false; /* Now enter the merge block */ - func->curblock = merge; + func->m_curblock = merge; /* Here, now, we need a PHI node * but first some sanity checking... */ - if (trueval->vtype != falseval->vtype && trueval->vtype != TYPE_NIL && falseval->vtype != TYPE_NIL) { + if (trueval->m_vtype != falseval->m_vtype && trueval->m_vtype != TYPE_NIL && falseval->m_vtype != TYPE_NIL) { /* error("ternary with different types on the two sides"); */ - compile_error(ast_ctx(self), "internal error: ternary operand types invalid"); + compile_error(self->m_context, "internal error: ternary operand types invalid"); return false; } /* create PHI */ - phi = ir_block_create_phi(merge, ast_ctx(self), ast_function_label(func, "phi"), self->expression.vtype); + phi = ir_block_create_phi(merge, self->m_context, ast_function_label(func, "phi"), self->m_vtype); if (!phi) { - compile_error(ast_ctx(self), "internal error: failed to generate phi node"); + compile_error(self->m_context, "internal error: failed to generate phi node"); return false; } ir_phi_add(phi, ontrue_out, trueval); ir_phi_add(phi, onfalse_out, falseval); - self->expression.outr = ir_phi_value(phi); - *out = self->expression.outr; + self->m_outr = ir_phi_value(phi); + *out = self->m_outr; codegen_output_type(self, *out); @@ -2800,11 +2620,11 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value (void)lvalue; (void)out; - if (self->expression.outr) { - compile_error(ast_ctx(self), "internal error: ast_loop cannot be reused, it bears no result!"); + if (self->m_outr) { + compile_error(self->m_context, "internal error: ast_loop cannot be reused, it bears no result!"); return false; } - self->expression.outr = (ir_value*)1; + self->m_outr = (ir_value*)1; /* NOTE: * Should we ever need some kind of block ordering, better make this function @@ -2815,22 +2635,22 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value /* initexpr doesn't get its own block, it's pointless, it could create more blocks * anyway if for example it contains a ternary. */ - if (self->initexpr) + if (self->m_initexpr) { - cgen = self->initexpr->codegen; - if (!(*cgen)((ast_expression*)(self->initexpr), func, false, &dummy)) + cgen = self->m_initexpr->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_initexpr), func, false, &dummy)) return false; } /* Store the block from which we enter this chaos */ - bin = func->curblock; + bin = func->m_curblock; /* The pre-loop condition needs its own block since we * need to be able to jump to the start of that expression. */ - if (self->precond) + if (self->m_precond) { - bprecond = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "pre_loop_cond")); + bprecond = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "pre_loop_cond")); if (!bprecond) return false; @@ -2838,14 +2658,14 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value bcontinue = bprecond; /* enter */ - func->curblock = bprecond; + func->m_curblock = bprecond; /* generate */ - cgen = self->precond->codegen; - if (!(*cgen)((ast_expression*)(self->precond), func, false, &precond)) + cgen = self->m_precond->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_precond), func, false, &precond)) return false; - end_bprecond = func->curblock; + end_bprecond = func->m_curblock; } else { bprecond = end_bprecond = nullptr; } @@ -2853,8 +2673,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value /* Now the next blocks won't be ordered nicely, but we need to * generate them this early for 'break' and 'continue'. */ - if (self->increment) { - bincrement = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "loop_increment")); + if (self->m_increment) { + bincrement = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "loop_increment")); if (!bincrement) return false; bcontinue = bincrement; /* increment comes before the pre-loop-condition */ @@ -2862,8 +2682,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value bincrement = end_bincrement = nullptr; } - if (self->postcond) { - bpostcond = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "post_loop_cond")); + if (self->m_postcond) { + bpostcond = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "post_loop_cond")); if (!bpostcond) return false; bcontinue = bpostcond; /* postcond comes before the increment */ @@ -2871,70 +2691,70 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value bpostcond = end_bpostcond = nullptr; } - bout_id = vec_size(func->ir_func->blocks); - bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_loop")); + bout_id = func->m_ir_func->m_blocks.size(); + bout = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "after_loop")); if (!bout) return false; bbreak = bout; /* The loop body... */ - /* if (self->body) */ + /* if (self->m_body) */ { - bbody = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "loop_body")); + bbody = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "loop_body")); if (!bbody) return false; /* enter */ - func->curblock = bbody; + func->m_curblock = bbody; - func->breakblocks.push_back(bbreak); + func->m_breakblocks.push_back(bbreak); if (bcontinue) - func->continueblocks.push_back(bcontinue); + func->m_continueblocks.push_back(bcontinue); else - func->continueblocks.push_back(bbody); + func->m_continueblocks.push_back(bbody); /* generate */ - if (self->body) { - cgen = self->body->codegen; - if (!(*cgen)((ast_expression*)(self->body), func, false, &dummy)) + if (self->m_body) { + cgen = self->m_body->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_body), func, false, &dummy)) return false; } - end_bbody = func->curblock; - func->breakblocks.pop_back(); - func->continueblocks.pop_back(); + end_bbody = func->m_curblock; + func->m_breakblocks.pop_back(); + func->m_continueblocks.pop_back(); } /* post-loop-condition */ - if (self->postcond) + if (self->m_postcond) { /* enter */ - func->curblock = bpostcond; + func->m_curblock = bpostcond; /* generate */ - cgen = self->postcond->codegen; - if (!(*cgen)((ast_expression*)(self->postcond), func, false, &postcond)) + cgen = self->m_postcond->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_postcond), func, false, &postcond)) return false; - end_bpostcond = func->curblock; + end_bpostcond = func->m_curblock; } /* The incrementor */ - if (self->increment) + if (self->m_increment) { /* enter */ - func->curblock = bincrement; + func->m_curblock = bincrement; /* generate */ - cgen = self->increment->codegen; - if (!(*cgen)((ast_expression*)(self->increment), func, false, &dummy)) + cgen = self->m_increment->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_increment), func, false, &dummy)) return false; - end_bincrement = func->curblock; + end_bincrement = func->m_curblock; } /* In any case now, we continue from the outgoing block */ - func->curblock = bout; + func->m_curblock = bout; /* Now all blocks are in place */ /* From 'bin' we jump to whatever comes first */ @@ -2946,7 +2766,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else tmpblock = bout; */ - if (!ir_block_create_jump(bin, ast_ctx(self), tmpblock)) + if (!ir_block_create_jump(bin, self->m_context, tmpblock)) return false; /* From precond */ @@ -2961,12 +2781,12 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value */ onfalse = bout; - if (self->pre_not) { + if (self->m_pre_not) { tmpblock = ontrue; ontrue = onfalse; onfalse = tmpblock; } - if (!ir_block_create_if(end_bprecond, ast_ctx(self), precond, ontrue, onfalse)) + if (!ir_block_create_if(end_bprecond, self->m_context, precond, ontrue, onfalse)) return false; } @@ -2977,7 +2797,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else if (bpostcond) tmpblock = bpostcond; else if (bprecond) tmpblock = bprecond; else tmpblock = bbody; - if (!end_bbody->final && !ir_block_create_jump(end_bbody, ast_ctx(self), tmpblock)) + if (!end_bbody->m_final && !ir_block_create_jump(end_bbody, self->m_context, tmpblock)) return false; } @@ -2988,7 +2808,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value else if (bprecond) tmpblock = bprecond; else if (bbody) tmpblock = bbody; else tmpblock = bout; - if (!ir_block_create_jump(end_bincrement, ast_ctx(self), tmpblock)) + if (!ir_block_create_jump(end_bincrement, self->m_context, tmpblock)) return false; } @@ -3005,18 +2825,22 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value */ onfalse = bout; - if (self->post_not) { + if (self->m_post_not) { tmpblock = ontrue; ontrue = onfalse; onfalse = tmpblock; } - if (!ir_block_create_if(end_bpostcond, ast_ctx(self), postcond, ontrue, onfalse)) + if (!ir_block_create_if(end_bpostcond, self->m_context, postcond, ontrue, onfalse)) return false; } /* Move 'bout' to the end */ - vec_remove(func->ir_func->blocks, bout_id, 1); - vec_push(func->ir_func->blocks, bout); + algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id, + func->m_ir_func->m_blocks.end()); + // FIXME::DELME:: + //func->m_ir_func->m_blocks[bout_id].release(); // it's a vector> + //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id); + //func->m_ir_func->m_blocks.emplace_back(bout); return true; } @@ -3028,27 +2852,27 @@ bool ast_breakcont_codegen(ast_breakcont *self, ast_function *func, bool lvalue, *out = nullptr; if (lvalue) { - compile_error(ast_ctx(self), "break/continue expression is not an l-value"); + compile_error(self->m_context, "break/continue expression is not an l-value"); return false; } - if (self->expression.outr) { - compile_error(ast_ctx(self), "internal error: ast_breakcont cannot be reused!"); + if (self->m_outr) { + compile_error(self->m_context, "internal error: ast_breakcont cannot be reused!"); return false; } - self->expression.outr = (ir_value*)1; + self->m_outr = (ir_value*)1; - if (self->is_continue) - target = func->continueblocks[func->continueblocks.size()-1-self->levels]; + if (self->m_is_continue) + target = func->m_continueblocks[func->m_continueblocks.size()-1-self->m_levels]; else - target = func->breakblocks[func->breakblocks.size()-1-self->levels]; + target = func->m_breakblocks[func->m_breakblocks.size()-1-self->m_levels]; if (!target) { - compile_error(ast_ctx(self), "%s is lacking a target block", (self->is_continue ? "continue" : "break")); + compile_error(self->m_context, "%s is lacking a target block", (self->m_is_continue ? "continue" : "break")); return false; } - if (!ir_block_create_jump(func->curblock, ast_ctx(self), target)) + if (!ir_block_create_jump(func->m_curblock, self->m_context, target)) return false; return true; } @@ -3072,91 +2896,95 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va uint16_t cmpinstr; if (lvalue) { - compile_error(ast_ctx(self), "switch expression is not an l-value"); + compile_error(self->m_context, "switch expression is not an l-value"); return false; } - if (self->expression.outr) { - compile_error(ast_ctx(self), "internal error: ast_switch cannot be reused!"); + if (self->m_outr) { + compile_error(self->m_context, "internal error: ast_switch cannot be reused!"); return false; } - self->expression.outr = (ir_value*)1; + self->m_outr = (ir_value*)1; (void)lvalue; (void)out; - cgen = self->operand->codegen; - if (!(*cgen)((ast_expression*)(self->operand), func, false, &irop)) + cgen = self->m_operand->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_operand), func, false, &irop)) return false; - if (self->cases.empty()) + if (self->m_cases.empty()) return true; - cmpinstr = type_eq_instr[irop->vtype]; + cmpinstr = type_eq_instr[irop->m_vtype]; if (cmpinstr >= VINSTR_END) { - ast_type_to_string(self->operand, typestr, sizeof(typestr)); - compile_error(ast_ctx(self), "invalid type to perform a switch on: %s", typestr); + ast_type_to_string(self->m_operand, typestr, sizeof(typestr)); + compile_error(self->m_context, "invalid type to perform a switch on: %s", typestr); return false; } - bout_id = vec_size(func->ir_func->blocks); - bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_switch")); + bout_id = func->m_ir_func->m_blocks.size(); + bout = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "after_switch")); if (!bout) return false; /* setup the break block */ - func->breakblocks.push_back(bout); + func->m_breakblocks.push_back(bout); /* Now create all cases */ - for (auto &it : self->cases) { + for (auto &it : self->m_cases) { ir_value *cond, *val; ir_block *bcase, *bnot; size_t bnot_id; ast_switch_case *swcase = ⁢ - if (swcase->value) { + if (swcase->m_value) { /* A regular case */ /* generate the condition operand */ - cgen = swcase->value->codegen; - if (!(*cgen)((ast_expression*)(swcase->value), func, false, &val)) + cgen = swcase->m_value->m_codegen; + if (!(*cgen)((ast_expression*)(swcase->m_value), func, false, &val)) return false; /* generate the condition */ - cond = ir_block_create_binop(func->curblock, ast_ctx(self), ast_function_label(func, "switch_eq"), cmpinstr, irop, val); + cond = ir_block_create_binop(func->m_curblock, self->m_context, ast_function_label(func, "switch_eq"), cmpinstr, irop, val); if (!cond) return false; - bcase = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "case")); - bnot_id = vec_size(func->ir_func->blocks); - bnot = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "not_case")); + bcase = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "case")); + bnot_id = func->m_ir_func->m_blocks.size(); + bnot = ir_function_create_block(self->m_context, func->m_ir_func, ast_function_label(func, "not_case")); if (!bcase || !bnot) return false; if (set_def_bfall_to) { set_def_bfall_to = false; def_bfall_to = bcase; } - if (!ir_block_create_if(func->curblock, ast_ctx(self), cond, bcase, bnot)) + if (!ir_block_create_if(func->m_curblock, self->m_context, cond, bcase, bnot)) return false; /* Make the previous case-end fall through */ - if (bfall && !bfall->final) { - if (!ir_block_create_jump(bfall, ast_ctx(self), bcase)) + if (bfall && !bfall->m_final) { + if (!ir_block_create_jump(bfall, self->m_context, bcase)) return false; } /* enter the case */ - func->curblock = bcase; - cgen = swcase->code->codegen; - if (!(*cgen)((ast_expression*)swcase->code, func, false, &dummy)) + func->m_curblock = bcase; + cgen = swcase->m_code->m_codegen; + if (!(*cgen)((ast_expression*)swcase->m_code, func, false, &dummy)) return false; /* remember this block to fall through from */ - bfall = func->curblock; + bfall = func->m_curblock; /* enter the else and move it down */ - func->curblock = bnot; - vec_remove(func->ir_func->blocks, bnot_id, 1); - vec_push(func->ir_func->blocks, bnot); + func->m_curblock = bnot; + algo::shiftback(func->m_ir_func->m_blocks.begin() + bnot_id, + func->m_ir_func->m_blocks.end()); + // FIXME::DELME:: + //func->m_ir_func->m_blocks[bnot_id].release(); + //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bnot_id); + //func->m_ir_func->m_blocks.emplace_back(bnot); } else { /* The default case */ /* Remember where to fall through from: */ @@ -3170,9 +2998,9 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va } /* Jump from the last bnot to bout */ - if (bfall && !bfall->final && !ir_block_create_jump(bfall, ast_ctx(self), bout)) { + if (bfall && !bfall->m_final && !ir_block_create_jump(bfall, self->m_context, bout)) { /* - astwarning(ast_ctx(bfall), WARN_???, "missing break after last case"); + astwarning(bfall->m_context, WARN_???, "missing break after last case"); */ return false; } @@ -3182,39 +3010,43 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va ir_block *bcase; /* No need to create an extra block */ - bcase = func->curblock; + bcase = func->m_curblock; /* Insert the fallthrough jump */ - if (def_bfall && !def_bfall->final) { - if (!ir_block_create_jump(def_bfall, ast_ctx(self), bcase)) + if (def_bfall && !def_bfall->m_final) { + if (!ir_block_create_jump(def_bfall, self->m_context, bcase)) return false; } /* Now generate the default code */ - cgen = def_case->code->codegen; - if (!(*cgen)((ast_expression*)def_case->code, func, false, &dummy)) + cgen = def_case->m_code->m_codegen; + if (!(*cgen)((ast_expression*)def_case->m_code, func, false, &dummy)) return false; /* see if we need to fall through */ - if (def_bfall_to && !func->curblock->final) + if (def_bfall_to && !func->m_curblock->m_final) { - if (!ir_block_create_jump(func->curblock, ast_ctx(self), def_bfall_to)) + if (!ir_block_create_jump(func->m_curblock, self->m_context, def_bfall_to)) return false; } } /* Jump from the last bnot to bout */ - if (!func->curblock->final && !ir_block_create_jump(func->curblock, ast_ctx(self), bout)) + if (!func->m_curblock->m_final && !ir_block_create_jump(func->m_curblock, self->m_context, bout)) return false; /* enter the outgoing block */ - func->curblock = bout; + func->m_curblock = bout; /* restore the break block */ - func->breakblocks.pop_back(); + func->m_breakblocks.pop_back(); /* Move 'bout' to the end, it's nicer */ - vec_remove(func->ir_func->blocks, bout_id, 1); - vec_push(func->ir_func->blocks, bout); + algo::shiftback(func->m_ir_func->m_blocks.begin() + bout_id, + func->m_ir_func->m_blocks.end()); + // FIXME::DELME:: + //func->m_ir_func->m_blocks[bout_id].release(); + //func->m_ir_func->m_blocks.erase(func->m_ir_func->m_blocks.begin() + bout_id); + //func->m_ir_func->m_blocks.emplace_back(bout); return true; } @@ -3223,33 +3055,33 @@ bool ast_label_codegen(ast_label *self, ast_function *func, bool lvalue, ir_valu { ir_value *dummy; - if (self->undefined) { - compile_error(ast_ctx(self), "internal error: ast_label never defined"); + if (self->m_undefined) { + compile_error(self->m_context, "internal error: ast_label never defined"); return false; } *out = nullptr; if (lvalue) { - compile_error(ast_ctx(self), "internal error: ast_label cannot be an lvalue"); + compile_error(self->m_context, "internal error: ast_label cannot be an lvalue"); return false; } /* simply create a new block and jump to it */ - self->irblock = ir_function_create_block(ast_ctx(self), func->ir_func, self->name); - if (!self->irblock) { - compile_error(ast_ctx(self), "failed to allocate label block `%s`", self->name); + self->m_irblock = ir_function_create_block(self->m_context, func->m_ir_func, self->m_name); + if (!self->m_irblock) { + compile_error(self->m_context, "failed to allocate label block `%s`", self->m_name); return false; } - if (!func->curblock->final) { - if (!ir_block_create_jump(func->curblock, ast_ctx(self), self->irblock)) + if (!func->m_curblock->m_final) { + if (!ir_block_create_jump(func->m_curblock, self->m_context, self->m_irblock)) return false; } /* enter the new block */ - func->curblock = self->irblock; + func->m_curblock = self->m_irblock; /* Generate all the leftover gotos */ - for (auto &it : self->gotos) { + for (auto &it : self->m_gotos) { if (!ast_goto_codegen(it, func, false, &dummy)) return false; } @@ -3261,23 +3093,23 @@ bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value { *out = nullptr; if (lvalue) { - compile_error(ast_ctx(self), "internal error: ast_goto cannot be an lvalue"); + compile_error(self->m_context, "internal error: ast_goto cannot be an lvalue"); return false; } - if (self->target->irblock) { - if (self->irblock_from) { + if (self->m_target->m_irblock) { + if (self->m_irblock_from) { /* we already tried once, this is the callback */ - self->irblock_from->final = false; - if (!ir_block_create_goto(self->irblock_from, ast_ctx(self), self->target->irblock)) { - compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name); + self->m_irblock_from->m_final = false; + if (!ir_block_create_goto(self->m_irblock_from, self->m_context, self->m_target->m_irblock)) { + compile_error(self->m_context, "failed to generate goto to `%s`", self->m_name); return false; } } else { - if (!ir_block_create_goto(func->curblock, ast_ctx(self), self->target->irblock)) { - compile_error(ast_ctx(self), "failed to generate goto to `%s`", self->name); + if (!ir_block_create_goto(func->m_curblock, self->m_context, self->m_target->m_irblock)) { + compile_error(self->m_context, "failed to generate goto to `%s`", self->m_name); return false; } } @@ -3287,9 +3119,9 @@ bool ast_goto_codegen(ast_goto *self, ast_function *func, bool lvalue, ir_value /* the target has not yet been created... * close this block in a sneaky way: */ - func->curblock->final = true; - self->irblock_from = func->curblock; - ast_label_register_goto(self->target, self); + func->m_curblock->m_final = true; + self->m_irblock_from = func->m_curblock; + ast_label_register_goto(self->m_target, self); } return true; @@ -3303,33 +3135,33 @@ bool ast_state_codegen(ast_state *self, ast_function *func, bool lvalue, ir_valu ir_value *frameval, *thinkval; if (lvalue) { - compile_error(ast_ctx(self), "not an l-value (state operation)"); + compile_error(self->m_context, "not an l-value (state operation)"); return false; } - if (self->expression.outr) { - compile_error(ast_ctx(self), "internal error: ast_state cannot be reused!"); + if (self->m_outr) { + compile_error(self->m_context, "internal error: ast_state cannot be reused!"); return false; } *out = nullptr; - cgen = self->framenum->codegen; - if (!(*cgen)((ast_expression*)(self->framenum), func, false, &frameval)) + cgen = self->m_framenum->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_framenum), func, false, &frameval)) return false; if (!frameval) return false; - cgen = self->nextthink->codegen; - if (!(*cgen)((ast_expression*)(self->nextthink), func, false, &thinkval)) + cgen = self->m_nextthink->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_nextthink), func, false, &thinkval)) return false; if (!frameval) return false; - if (!ir_block_create_state_op(func->curblock, ast_ctx(self), frameval, thinkval)) { - compile_error(ast_ctx(self), "failed to create STATE instruction"); + if (!ir_block_create_state_op(func->m_curblock, self->m_context, frameval, thinkval)) { + compile_error(self->m_context, "failed to create STATE instruction"); return false; } - self->expression.outr = (ir_value*)1; + self->m_outr = (ir_value*)1; return true; } @@ -3343,25 +3175,25 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value /* return values are never lvalues */ if (lvalue) { - compile_error(ast_ctx(self), "not an l-value (function call)"); + compile_error(self->m_context, "not an l-value (function call)"); return false; } - if (self->expression.outr) { - *out = self->expression.outr; + if (self->m_outr) { + *out = self->m_outr; return true; } - cgen = self->func->codegen; - if (!(*cgen)((ast_expression*)(self->func), func, false, &funval)) + cgen = self->m_func->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_func), func, false, &funval)) return false; if (!funval) return false; /* parameters */ - for (auto &it : self->params) { + for (auto &it : self->m_params) { ir_value *param; - cgen = it->codegen; + cgen = it->m_codegen; if (!(*cgen)(it, func, false, ¶m)) return false; if (!param) @@ -3370,22 +3202,22 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value } /* varargs counter */ - if (self->va_count) { + if (self->m_va_count) { ir_value *va_count; - ir_builder *builder = func->curblock->owner->owner; - cgen = self->va_count->codegen; - if (!(*cgen)((ast_expression*)(self->va_count), func, false, &va_count)) + ir_builder *builder = func->m_curblock->m_owner->m_owner; + cgen = self->m_va_count->m_codegen; + if (!(*cgen)((ast_expression*)(self->m_va_count), func, false, &va_count)) return false; - if (!ir_block_create_store_op(func->curblock, ast_ctx(self), INSTR_STORE_F, + if (!ir_block_create_store_op(func->m_curblock, self->m_context, INSTR_STORE_F, ir_builder_get_va_count(builder), va_count)) { return false; } } - callinstr = ir_block_create_call(func->curblock, ast_ctx(self), + callinstr = ir_block_create_call(func->m_curblock, self->m_context, ast_function_label(func, "call"), - funval, !!(self->func->flags & AST_FLAG_NORETURN)); + funval, !!(self->m_func->m_flags & AST_FLAG_NORETURN)); if (!callinstr) return false; @@ -3393,7 +3225,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value ir_call_param(callinstr, it); *out = ir_call_value(callinstr); - self->expression.outr = *out; + self->m_outr = *out; codegen_output_type(self, *out); diff --git a/ast.h b/ast.h index 09f901a..354ce05 100644 --- a/ast.h +++ b/ast.h @@ -93,9 +93,7 @@ enum { TYPE_ast_state /* 22 */ }; -#define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) ) -#define ast_ctx(node) (((ast_node*)(node))->context) -#define ast_side_effects(node) (((ast_node*)(node))->side_effects) +#define ast_istype(x, t) ( (x)->m_node_type == (TYPE_##t) ) /* Node interface with common components */ @@ -103,25 +101,32 @@ typedef void ast_node_delete(ast_node*); struct ast_node { - lex_ctx_t context; + ast_node() = delete; + ast_node(lex_ctx_t, int nodetype); + virtual ~ast_node(); + + lex_ctx_t m_context; /* I don't feel comfortable using keywords like 'delete' as names... */ - ast_node_delete *destroy; - int nodetype; - /* keep: if a node contains this node, 'keep' + int m_node_type; + /* keep_node: if a node contains this node, 'keep_node' * prevents its dtor from destroying this node as well. */ - bool keep; - bool side_effects; + bool m_keep_node; + bool m_side_effects; + + void propagate_side_effects(ast_node *other) const; }; -#define ast_delete(x) (*( ((ast_node*)(x))->destroy ))((ast_node*)(x)) -#define ast_unref(x) do \ -{ \ - if (! (((ast_node*)(x))->keep) ) { \ - ast_delete(x); \ - } \ +#define ast_unref(x) do \ +{ \ + if (! (x)->m_keep_node ) { \ + delete (x); \ + } \ } while(0) +enum class ast_copy_type_t { value }; +static const ast_copy_type_t ast_copy_type = ast_copy_type_t::value; + /* Expression interface * * Any expression or block returns an ir_value, and needs @@ -141,29 +146,37 @@ typedef bool ast_expression_codegen(ast_expression*, * type `expression`, so the ast_ident's codegen would search for * variables through the environment (or functions, constants...). */ -struct ast_expression { - ast_expression() {} +struct ast_expression : ast_node { + ast_expression() = delete; + ast_expression(lex_ctx_t ctx, int nodetype, qc_type vtype); + ast_expression(lex_ctx_t ctx, int nodetype); + ~ast_expression(); + ast_expression(ast_copy_type_t, int nodetype, const ast_expression&); + ast_expression(ast_copy_type_t, const ast_expression&); + + static ast_expression *shallow_type(lex_ctx_t ctx, qc_type vtype); + + bool compare_type(const ast_expression &other) const; + void adopt_type(const ast_expression &other); - ast_node node; - ast_expression_codegen *codegen; - int vtype; - ast_expression *next; + qc_type m_vtype = TYPE_VOID; + ast_expression *m_next = nullptr; /* arrays get a member-count */ - size_t count; - std::vector params; + size_t m_count = 0; + std::vector> m_type_params; - ast_flag_t flags; + ast_flag_t m_flags = 0; /* void foo(string...) gets varparam set as a restriction * for variadic parameters */ - ast_expression *varparam; + ast_expression *m_varparam = nullptr; /* The codegen functions should store their output values * so we can call it multiple times without re-evaluating. * Store lvalue and rvalue seperately though. So that * ast_entfield for example can generate both if required. */ - ir_value *outl; - ir_value *outr; + ir_value *m_outl = nullptr; + ir_value *m_outr = nullptr; }; /* Value @@ -174,72 +187,62 @@ struct ast_expression { * is like creating a 'float foo', foo serving as the type's name. */ union basic_value_t { - qcfloat_t vfloat; - int vint; - vec3_t vvec; - const char *vstring; - int ventity; + qcfloat_t vfloat; + int vint; + vec3_t vvec; + const char *vstring; + int ventity; ast_function *vfunc; - ast_value *vfield; + ast_value *vfield; }; -struct ast_value +struct ast_value : ast_expression { - ast_expression expression; + ast_value() = delete; + ast_value(lex_ctx_t ctx, const std::string &name, qc_type qctype); + ~ast_value(); - const char *name; - const char *desc; + ast_value(ast_copy_type_t, const ast_expression&, const std::string&); + ast_value(ast_copy_type_t, const ast_value&); + ast_value(ast_copy_type_t, const ast_value&, const std::string&); - const char *argcounter; + void add_param(ast_value*); - int cvq; /* const/var qualifier */ - bool isfield; /* this declares a field */ - bool isimm; /* an immediate, not just const */ - bool hasvalue; - bool inexact; /* inexact coming from folded expression */ - basic_value_t constval; + std::string m_name; + std::string m_desc; + + const char *m_argcounter = nullptr; + + int m_cvq = CV_NONE; /* const/var qualifier */ + bool m_isfield = false; /* this declares a field */ + bool m_isimm = false; /* an immediate, not just const */ + bool m_hasvalue = false; + bool m_inexact = false; /* inexact coming from folded expression */ + basic_value_t m_constval; /* for TYPE_ARRAY we have an optional vector * of constants when an initializer list * was provided. */ - std::vector initlist; + std::vector m_initlist; /* usecount for the parser */ - size_t uses; + size_t m_uses = 0; - ir_value *ir_v; - ir_value **ir_values; - size_t ir_value_count; + ir_value *m_ir_v = nullptr; + ir_value **m_ir_values = nullptr; + size_t m_ir_value_count = 0; /* ONLY for arrays in progs version up to 6 */ - ast_value *setter; - ast_value *getter; + ast_value *m_setter = nullptr; + ast_value *m_getter = nullptr; - bool intrinsic; /* true if associated with intrinsic */ + bool m_intrinsic = false; /* true if associated with intrinsic */ }; -ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int qctype); -ast_value* ast_value_copy(const ast_value *self); -/* This will NOT delete an underlying ast_function */ -void ast_value_delete(ast_value*); - -bool ast_value_set_name(ast_value*, const char *name); - -/* -bool ast_value_codegen(ast_value*, ast_function*, bool lvalue, ir_value**); -bool ast_local_codegen(ast_value *self, ir_function *func, bool isparam); -*/ - bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield); -void ast_value_params_add(ast_value*, ast_value*); - -bool ast_compare_type(ast_expression *a, ast_expression *b); -ast_expression* ast_type_copy(lex_ctx_t ctx, const ast_expression *ex); -#define ast_type_adopt(a, b) ast_type_adopt_impl((ast_expression*)(a), (ast_expression*)(b)) -void ast_type_adopt_impl(ast_expression *self, const ast_expression *other); -void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize); +void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize); enum ast_binary_ref { AST_REF_NONE = 0, @@ -253,34 +256,36 @@ enum ast_binary_ref { * * A value-returning binary expression. */ -struct ast_binary +struct ast_binary : ast_expression { - ast_expression expression; - int op; - ast_expression *left; - ast_expression *right; - ast_binary_ref refs; - bool right_first; + ast_binary() = delete; + ast_binary(lex_ctx_t ctx, int op, ast_expression *l, ast_expression *r); + ~ast_binary(); + + int m_op; + ast_expression *m_left; + ast_expression *m_right; + ast_binary_ref m_refs; + bool m_right_first; }; -ast_binary* ast_binary_new(lex_ctx_t ctx, - int op, - ast_expression *left, - ast_expression *right); /* Binstore * * An assignment including a binary expression with the source as left operand. * Eg. a += b; is a binstore { INSTR_STORE, INSTR_ADD, a, b } */ -struct ast_binstore +struct ast_binstore : ast_expression { - ast_expression expression; - int opstore; - int opbin; - ast_expression *dest; - ast_expression *source; + ast_binstore() = delete; + ast_binstore(lex_ctx_t ctx, int storeop, int mathop, ast_expression *l, ast_expression *r); + ~ast_binstore(); + + int m_opstore; + int m_opbin; + ast_expression *m_dest; + ast_expression *m_source; /* for &~= which uses the destination in a binary in source we can use this */ - bool keep_dest; + bool m_keep_dest; }; ast_binstore* ast_binstore_new(lex_ctx_t ctx, int storeop, @@ -292,15 +297,16 @@ ast_binstore* ast_binstore_new(lex_ctx_t ctx, * * Regular unary expressions: not,neg */ -struct ast_unary +struct ast_unary : ast_expression { - ast_expression expression; - int op; - ast_expression *operand; + ast_unary() = delete; + ~ast_unary(); + int m_op; + ast_expression *m_operand; + static ast_unary* make(lex_ctx_t ctx, int op, ast_expression *expr); +private: + ast_unary(lex_ctx_t ctx, int op, ast_expression *expr); }; -ast_unary* ast_unary_new(lex_ctx_t ctx, - int op, - ast_expression *expr); /* Return * @@ -308,13 +314,13 @@ ast_unary* ast_unary_new(lex_ctx_t ctx, * will refuse to create further instructions. * This should be honored by the parser. */ -struct ast_return +struct ast_return : ast_expression { - ast_expression expression; - ast_expression *operand; + ast_return() = delete; + ast_return(lex_ctx_t ctx, ast_expression *expr); + ~ast_return(); + ast_expression *m_operand; }; -ast_return* ast_return_new(lex_ctx_t ctx, - ast_expression *expr); /* Entity-field * @@ -329,34 +335,37 @@ ast_return* ast_return_new(lex_ctx_t ctx, * For this we will have to extend the codegen() functions with * a flag saying whether or not we need an L or an R-value. */ -struct ast_entfield +struct ast_entfield : ast_expression { - ast_expression expression; - /* The entity can come from an expression of course. */ - ast_expression *entity; - /* As can the field, it just must result in a value of TYPE_FIELD */ - ast_expression *field; + ast_entfield() = delete; + ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field); + ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype); + ~ast_entfield(); + // The entity can come from an expression of course. + ast_expression *m_entity; + // As can the field, it just must result in a value of TYPE_FIELD + ast_expression *m_field; }; -ast_entfield* ast_entfield_new(lex_ctx_t ctx, ast_expression *entity, ast_expression *field); -ast_entfield* ast_entfield_new_force(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype); /* Member access: * * For now used for vectors. If we get structs or unions * we can have them handled here as well. */ -struct ast_member +struct ast_member : ast_expression { - ast_expression expression; - ast_expression *owner; - unsigned int field; - const char *name; - bool rvalue; -}; -ast_member* ast_member_new(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const char *name); -void ast_member_delete(ast_member*); -bool ast_member_set_name(ast_member*, const char *name); + static ast_member *make(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name); + ~ast_member(); + ast_expression *m_owner; + unsigned int m_field; + std::string m_name; + bool m_rvalue; + +private: + ast_member() = delete; + ast_member(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name); +}; /* Array index access: * @@ -368,39 +377,43 @@ bool ast_member_set_name(ast_member*, const char *name); * In any case, accessing an element via a compiletime-constant index will * result in quick access to that variable. */ -struct ast_array_index +struct ast_array_index : ast_expression { - ast_expression expression; - ast_expression *array; - ast_expression *index; + static ast_array_index* make(lex_ctx_t ctx, ast_expression *array, ast_expression *index); + ~ast_array_index(); + ast_expression *m_array; + ast_expression *m_index; +private: + ast_array_index() = delete; + ast_array_index(lex_ctx_t ctx, ast_expression *array, ast_expression *index); }; -ast_array_index* ast_array_index_new(lex_ctx_t ctx, ast_expression *array, ast_expression *index); /* Vararg pipe node: * * copy all varargs starting from a specific index */ -struct ast_argpipe +struct ast_argpipe : ast_expression { - ast_expression expression; - ast_expression *index; + ast_argpipe() = delete; + ast_argpipe(lex_ctx_t ctx, ast_expression *index); + ~ast_argpipe(); + ast_expression *m_index; }; -ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index); /* Store * * Stores left<-right and returns left. * Specialized binary expression node */ -struct ast_store +struct ast_store : ast_expression { - ast_expression expression; - int op; - ast_expression *dest; - ast_expression *source; + ast_store() = delete; + ast_store(lex_ctx_t ctx, int op, ast_expression *d, ast_expression *s); + ~ast_store(); + int m_op; + ast_expression *m_dest; + ast_expression *m_source; }; -ast_store* ast_store_new(lex_ctx_t ctx, int op, - ast_expression *d, ast_expression *s); /* If * @@ -413,15 +426,16 @@ ast_store* ast_store_new(lex_ctx_t ctx, int op, * output field though. For ternary expressions an ast_ternary will be * added. */ -struct ast_ifthen +struct ast_ifthen : ast_expression { - ast_expression expression; - ast_expression *cond; + ast_ifthen() = delete; + ast_ifthen(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); + ~ast_ifthen(); + ast_expression *m_cond; /* It's all just 'expressions', since an ast_block is one too. */ - ast_expression *on_true; - ast_expression *on_false; + ast_expression *m_on_true; + ast_expression *m_on_false; }; -ast_ifthen* ast_ifthen_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); /* Ternary expressions... * @@ -436,15 +450,16 @@ ast_ifthen* ast_ifthen_new(lex_ctx_t ctx, ast_expression *cond, ast_expression * * This is the only ast_node beside ast_value which contains * an ir_value. Theoretically we don't need to remember it though. */ -struct ast_ternary +struct ast_ternary : ast_expression { - ast_expression expression; - ast_expression *cond; + ast_ternary() = delete; + ast_ternary(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); + ~ast_ternary(); + ast_expression *m_cond; /* It's all just 'expressions', since an ast_block is one too. */ - ast_expression *on_true; - ast_expression *on_false; + ast_expression *m_on_true; + ast_expression *m_on_false; }; -ast_ternary* ast_ternary_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); /* A general loop node * @@ -469,37 +484,37 @@ continue: // a 'continue' will jump here {inc}; } */ -struct ast_loop +struct ast_loop : ast_expression { - ast_expression expression; - ast_expression *initexpr; - ast_expression *precond; - ast_expression *postcond; - ast_expression *increment; - ast_expression *body; + ast_loop() = delete; + ast_loop(lex_ctx_t ctx, + ast_expression *initexpr, + ast_expression *precond, bool pre_not, + ast_expression *postcond, bool post_not, + ast_expression *increment, + ast_expression *body); + ~ast_loop(); + ast_expression *m_initexpr; + ast_expression *m_precond; + ast_expression *m_postcond; + ast_expression *m_increment; + ast_expression *m_body; /* For now we allow a seperate flag on whether or not the condition * is supposed to be true or false. * That way, the parser can generate a 'while not(!x)' for `while(x)` * if desired, which is useful for the new -f{true,false}-empty-strings * flag. */ - bool pre_not; - bool post_not; + bool m_pre_not; + bool m_post_not; }; -ast_loop* ast_loop_new(lex_ctx_t ctx, - ast_expression *initexpr, - ast_expression *precond, bool pre_not, - ast_expression *postcond, bool post_not, - ast_expression *increment, - ast_expression *body); /* Break/Continue */ -struct ast_breakcont +struct ast_breakcont : ast_expression { - ast_expression expression; - bool is_continue; - unsigned int levels; + bool m_is_continue; + unsigned int m_levels; }; ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels); @@ -514,15 +529,14 @@ ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels * TODO: Ticket #20 */ struct ast_switch_case { - ast_expression *value; /* #20 will replace this */ - ast_expression *code; + ast_expression *m_value; /* #20 will replace this */ + ast_expression *m_code; }; -struct ast_switch +struct ast_switch : ast_expression { - ast_expression expression; - ast_expression *operand; - std::vector cases; + ast_expression *m_operand; + std::vector m_cases; }; ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op); @@ -531,15 +545,14 @@ ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op); * * Introduce a label which can be used together with 'goto' */ -struct ast_label +struct ast_label : ast_expression { - ast_expression expression; - const char *name; - ir_block *irblock; - std::vector gotos; + const char *m_name; + ir_block *m_irblock; + std::vector m_gotos; /* means it has not yet been defined */ - bool undefined; + bool m_undefined; }; ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined); @@ -548,12 +561,11 @@ ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined); * * Go to a label, the label node is filled in at a later point! */ -struct ast_goto +struct ast_goto : ast_expression { - ast_expression expression; - const char *name; - ast_label *target; - ir_block *irblock_from; + const char *m_name; + ast_label *m_target; + ir_block *m_irblock_from; }; ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name); @@ -563,11 +575,10 @@ void ast_goto_set_label(ast_goto*, ast_label*); * * For frame/think state updates: void foo() [framenum, nextthink] {} */ -struct ast_state +struct ast_state : ast_expression { - ast_expression expression; - ast_expression *framenum; - ast_expression *nextthink; + ast_expression *m_framenum; + ast_expression *m_nextthink; }; ast_state* ast_state_new(lex_ctx_t ctx, ast_expression *frame, ast_expression *think); void ast_state_delete(ast_state*); @@ -582,12 +593,11 @@ void ast_state_delete(ast_state*); * Additionally it contains a list of ast_expressions as parameters. * Since calls can return values, an ast_call is also an ast_expression. */ -struct ast_call +struct ast_call : ast_expression { - ast_expression expression; - ast_expression *func; - std::vector params; - ast_expression *va_count; + ast_expression *m_func; + std::vector m_params; + ast_expression *m_va_count; }; ast_call* ast_call_new(lex_ctx_t ctx, ast_expression *funcexpr); @@ -596,13 +606,11 @@ bool ast_call_check_types(ast_call*, ast_expression *this_func_va_type); /* Blocks * */ -struct ast_block +struct ast_block : ast_expression { - ast_expression expression; - - std::vector locals; - std::vector exprs; - std::vector collect; + std::vector m_locals; + std::vector m_exprs; + std::vector m_collect; }; ast_block* ast_block_new(lex_ctx_t ctx); void ast_block_delete(ast_block*); @@ -621,39 +629,37 @@ bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*); * pointers could just work with a name. However, this way could be * more flexible, and adds no real complexity. */ -struct ast_function +struct ast_function : ast_node { - ast_node node; - - ast_value *vtype; - const char *name; + ast_value *m_function_type; + const char *m_name; - int builtin; + int m_builtin; /* list of used-up names for statics without the count suffix */ - std::vector static_names; + std::vector m_static_names; /* number of static variables, by convention this includes the * ones without the count-suffix - remember this when dealing * with savegames. uint instead of size_t as %zu in printf is * C99, so no windows support. */ - unsigned int static_count; + unsigned int m_static_count; - ir_function *ir_func; - ir_block *curblock; - std::vector breakblocks; - std::vector continueblocks; + ir_function *m_ir_func; + ir_block *m_curblock; + std::vector m_breakblocks; + std::vector m_continueblocks; - size_t labelcount; + size_t m_labelcount; /* in order for thread safety - for the optional * channel abesed multithreading... keeping a buffer * here to use in ast_function_label. */ - char labelbuf[64]; - std::vector blocks; - ast_value *varargs; - ast_value *argc; - ast_value *fixedparams; - ast_value *return_value; + char m_labelbuf[64]; + std::vector> m_blocks; + ast_value *m_varargs; + ast_value *m_argc; + ast_value *m_fixedparams; + ast_value *m_return_value; }; ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype); /* This will NOT delete the underlying ast_value */ diff --git a/code.cpp b/code.cpp index 2f55535..645ad25 100644 --- a/code.cpp +++ b/code.cpp @@ -106,35 +106,39 @@ void code_pop_statement(code_t *code) code->columnnums.pop_back(); } -code_t *code_init() { +void *code_t::operator new(std::size_t bytes) { + return mem_a(bytes); +} + +void code_t::operator delete(void *ptr) { + mem_d(ptr); +} + +code_t::code_t() +{ static lex_ctx_t empty_ctx = {0, 0, 0}; static prog_section_function_t empty_function = {0,0,0,0,0,0,0,{0,0,0,0,0,0,0,0}}; static prog_section_statement_t empty_statement = {0,{0},{0},{0}}; static prog_section_def_t empty_def = {0, 0, 0}; - code_t *code = (code_t*)mem_a(sizeof(code_t)); - int i = 0; + string_cache = util_htnew(OPTS_OPTIMIZATION(OPTIM_OVERLAP_STRINGS) ? 0x100 : 1024); - memset(code, 0, sizeof(code_t)); - code->entfields = 0; - code->string_cache = util_htnew(OPTS_OPTIMIZATION(OPTIM_OVERLAP_STRINGS) ? 0x100 : 1024); + // The way progs.dat is suppose to work is odd, there needs to be + // some null (empty) statements, functions, and 28 globals + globals.insert(globals.begin(), 28, 0); - /* - * The way progs.dat is suppose to work is odd, there needs to be - * some null (empty) statements, functions, and 28 globals - */ - for(; i < 28; i++) - code->globals.push_back(0); + chars.push_back('\0'); + functions.push_back(empty_function); - code->chars.push_back('\0'); - code->functions.push_back(empty_function); + code_push_statement(this, &empty_statement, empty_ctx); - code_push_statement(code, &empty_statement, empty_ctx); - - code->defs.push_back(empty_def); - code->fields.push_back(empty_def); + defs.push_back(empty_def); + fields.push_back(empty_def); +} - return code; +code_t::~code_t() +{ + util_htdel(string_cache); } void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin); @@ -342,8 +346,3 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) { code_stats(filename, lnofile, code, &code_header); return true; } - -void code_cleanup(code_t *code) { - util_htdel(code->string_cache); - mem_d(code); -} diff --git a/fold.cpp b/fold.cpp index dab7436..0f86117 100644 --- a/fold.cpp +++ b/fold.cpp @@ -535,10 +535,10 @@ static GMQCC_INLINE void sfloat_init(sfloat_state_t *state) { * This file is thus, split into two parts. */ -#define isfloat(X) (((ast_expression*)(X))->vtype == TYPE_FLOAT) -#define isvector(X) (((ast_expression*)(X))->vtype == TYPE_VECTOR) -#define isstring(X) (((ast_expression*)(X))->vtype == TYPE_STRING) -#define isarray(X) (((ast_expression*)(X))->vtype == TYPE_ARRAY) +#define isfloat(X) (((ast_expression*)(X))->m_vtype == TYPE_FLOAT) +#define isvector(X) (((ast_expression*)(X))->m_vtype == TYPE_VECTOR) +#define isstring(X) (((ast_expression*)(X))->m_vtype == TYPE_STRING) +#define isarray(X) (((ast_expression*)(X))->m_vtype == TYPE_ARRAY) #define isfloats(X,Y) (isfloat (X) && isfloat (Y)) /* @@ -858,15 +858,15 @@ end: } qcfloat_t fold::immvalue_float(ast_value *value) { - return value->constval.vfloat; + return value->m_constval.vfloat; } vec3_t fold::immvalue_vector(ast_value *value) { - return value->constval.vvec; + return value->m_constval.vvec; } const char *fold::immvalue_string(ast_value *value) { - return value->constval.vstring; + return value->m_constval.vstring; } lex_ctx_t fold::ctx() { @@ -878,32 +878,32 @@ lex_ctx_t fold::ctx() { } bool fold::immediate_true(ast_value *v) { - switch (v->expression.vtype) { + switch (v->m_vtype) { case TYPE_FLOAT: - return !!v->constval.vfloat; + return !!v->m_constval.vfloat; case TYPE_INTEGER: - return !!v->constval.vint; + return !!v->m_constval.vint; case TYPE_VECTOR: if (OPTS_FLAG(CORRECT_LOGIC)) - return vec3_pbool(v->constval.vvec); - return !!(v->constval.vvec.x); + return vec3_pbool(v->m_constval.vvec); + return !!(v->m_constval.vvec.x); case TYPE_STRING: - if (!v->constval.vstring) + if (!v->m_constval.vstring) return false; if (OPTS_FLAG(TRUE_EMPTY_STRINGS)) return true; - return !!v->constval.vstring[0]; + return !!v->m_constval.vstring[0]; default: compile_error(ctx(), "internal error: fold_immediate_true on invalid type"); break; } - return !!v->constval.vfunc; + return !!v->m_constval.vfunc; } /* Handy macros to determine if an ast_value can be constant folded. */ #define fold_can_1(X) \ - (ast_istype(((ast_expression*)(X)), ast_value) && (X)->hasvalue && ((X)->cvq == CV_CONST) && \ - ((ast_expression*)(X))->vtype != TYPE_FUNCTION) + (ast_istype(((ast_expression*)(X)), ast_value) && (X)->m_hasvalue && ((X)->m_cvq == CV_CONST) && \ + ((ast_expression*)(X))->m_vtype != TYPE_FUNCTION) #define fold_can_2(X, Y) (fold_can_1(X) && fold_can_1(Y)) @@ -938,8 +938,8 @@ bool fold::generate(ir_builder *ir) { if (!ast_global_codegen((cur = it), ir, false)) goto err; return true; err: - con_out("failed to generate global %s\n", cur->name); - ir_builder_delete(ir); + con_out("failed to generate global %s\n", cur->m_name); + delete ir; return false; } @@ -957,14 +957,14 @@ fold::~fold() { ast_expression *fold::constgen_float(qcfloat_t value, bool inexact) { for (auto &it : m_imm_float) - if (!memcmp(&it->constval.vfloat, &value, sizeof(qcfloat_t))) + if (!memcmp(&it->m_constval.vfloat, &value, sizeof(qcfloat_t))) return (ast_expression*)it; ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_FLOAT); - out->cvq = CV_CONST; - out->hasvalue = true; - out->inexact = inexact; - out->constval.vfloat = value; + out->m_cvq = CV_CONST; + out->m_hasvalue = true; + out->m_inexact = inexact; + out->m_constval.vfloat = value; m_imm_float.push_back(out); @@ -973,13 +973,13 @@ ast_expression *fold::constgen_float(qcfloat_t value, bool inexact) { ast_expression *fold::constgen_vector(vec3_t value) { for (auto &it : m_imm_vector) - if (vec3_cmp(it->constval.vvec, value)) + if (vec3_cmp(it->m_constval.vvec, value)) return (ast_expression*)it; ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_VECTOR); - out->cvq = CV_CONST; - out->hasvalue = true; - out->constval.vvec = value; + out->m_cvq = CV_CONST; + out->m_hasvalue = true; + out->m_constval.vvec = value; m_imm_vector.push_back(out); @@ -998,15 +998,15 @@ ast_expression *fold::constgen_string(const char *str, bool translate) { char name[32]; util_snprintf(name, sizeof(name), "dotranslate_%zu", m_parser->translated++); out = ast_value_new(ctx(), name, TYPE_STRING); - out->expression.flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */ + out->m_flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */ } else { out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_STRING); } - out->cvq = CV_CONST; - out->hasvalue = true; - out->isimm = true; - out->constval.vstring = parser_strdup(str); + out->m_cvq = CV_CONST; + out->m_hasvalue = true; + out->m_isimm = true; + out->m_constval.vstring = parser_strdup(str); m_imm_string.push_back(out); util_htseth(table, str, hash, out); @@ -1057,7 +1057,7 @@ inexact_possible: bool fold::check_inexact_float(ast_value *a, ast_value *b) { if (!OPTS_WARN(WARN_INEXACT_COMPARES)) return false; - if (!a->inexact && !b->inexact) + if (!a->m_inexact && !b->m_inexact) return false; return compile_warning(ctx(), WARN_INEXACT_COMPARES, "inexact value in comparison"); } @@ -1070,8 +1070,8 @@ ast_expression *fold::op_mul_vec(vec3_t vec, ast_value *sel, const char *set) { ast_expression *out; ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; out = (ast_expression*)ast_member_new(ctx(), (ast_expression*)sel, set[0]-'x', nullptr); - out->node.keep = false; - ((ast_member*)out)->rvalue = true; + out->m_keep_node = false; + ((ast_member*)out)->m_rvalue = true; if (x != -1.0f) return (ast_expression*)ast_binary_new(ctx(), INSTR_MUL_F, constgen_float(x, false), out); } @@ -1374,7 +1374,7 @@ ast_expression *fold::op_length(ast_value *a) { if (fold_can_1(a) && isstring(a)) return constgen_float(strlen(immvalue_string(a)), false); if (isarray(a)) - return constgen_float(a->initlist.size(), false); + return constgen_float(a->m_initlist.size(), false); return nullptr; } @@ -1526,18 +1526,18 @@ ast_expression *fold::intrinsic(const char *intrinsic, ast_expression **arg) { #undef fold_can_1 #undef fold_can_2 -#define isfloat(X) ((X)->vtype == TYPE_FLOAT) -/*#define isstring(X) ((X)->vtype == TYPE_STRING)*/ -/*#define isvector(X) ((X)->vtype == TYPE_VECTOR)*/ -#define fold_can_1(X) ((X)->hasvalue && (X)->cvq == CV_CONST) +#define isfloat(X) ((X)->m_vtype == TYPE_FLOAT) +/*#define isstring(X) ((X)->m_vtype == TYPE_STRING)*/ +/*#define isvector(X) ((X)->m_vtype == TYPE_VECTOR)*/ +#define fold_can_1(X) ((X)->m_hasvalue && (X)->m_cvq == CV_CONST) /*#define fold_can_2(X,Y) (fold_can_1(X) && fold_can_1(Y))*/ qcfloat_t fold::immvalue_float(ir_value *value) { - return value->constval.vfloat; + return value->m_constval.vfloat; } vec3_t fold::immvalue_vector(ir_value *value) { - return value->constval.vvec; + return value->m_constval.vvec; } ast_expression *fold::superfluous(ast_expression *left, ast_expression *right, int op) { @@ -1612,10 +1612,10 @@ int fold::cond(ir_value *condval, ast_function *func, ast_ifthen *branch) { ast_expression_codegen *cgen; ir_block *elide; ir_value *dummy; - bool istrue = (immvalue_float(condval) != 0.0f && branch->on_true); - bool isfalse = (immvalue_float(condval) == 0.0f && branch->on_false); - ast_expression *path = (istrue) ? branch->on_true : - (isfalse) ? branch->on_false : nullptr; + bool istrue = (immvalue_float(condval) != 0.0f && branch->m_on_true); + bool isfalse = (immvalue_float(condval) == 0.0f && branch->m_on_false); + ast_expression *path = (istrue) ? branch->m_on_true : + (isfalse) ? branch->m_on_false : nullptr; if (!path) { /* * no path to take implies that the evaluation is if(0) and there @@ -1625,17 +1625,17 @@ int fold::cond(ir_value *condval, ast_function *func, ast_ifthen *branch) { return true; } - if (!(elide = ir_function_create_block(ast_ctx(branch), func->ir_func, ast_function_label(func, ((istrue) ? "ontrue" : "onfalse"))))) + if (!(elide = ir_function_create_block(branch->m_context, func->m_ir_func, ast_function_label(func, ((istrue) ? "ontrue" : "onfalse"))))) return false; - if (!(*(cgen = path->codegen))((ast_expression*)path, func, false, &dummy)) + if (!(*(cgen = path->m_codegen))((ast_expression*)path, func, false, &dummy)) return false; - if (!ir_block_create_jump(func->curblock, ast_ctx(branch), elide)) + if (!ir_block_create_jump(func->m_curblock, branch->m_context, elide)) return false; /* * now the branch has been eliminated and the correct block for the constant evaluation * is expanded into the current block for the function. */ - func->curblock = elide; + func->m_curblock = elide; ++opts_optimizationcount[OPTIM_CONST_FOLD_DCE]; return true; } diff --git a/gmqcc.h b/gmqcc.h index 48570ff..88cf7ff 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -1,6 +1,10 @@ #ifndef GMQCC_HDR #define GMQCC_HDR #include +#include +#include +#include +using std::move; #include #include #include @@ -259,7 +263,7 @@ int util_getline(char **, size_t *, FILE *); /* code.c */ /* Note: if you change the order, fix type_sizeof in ir.c */ -enum { +enum qc_type { TYPE_VOID , TYPE_STRING , TYPE_FLOAT , @@ -498,6 +502,10 @@ typedef int32_t qcint_t; typedef uint32_t qcuint_t; struct code_t { + void* operator new(std::size_t); + void operator delete(void*); + code_t(); + ~code_t(); std::vector statements; std::vector linenums; std::vector columnnums; @@ -506,10 +514,10 @@ struct code_t { std::vector functions; std::vector globals; std::vector chars; - uint16_t crc; - uint32_t entfields; + uint16_t crc = 0; + uint32_t entfields = 0; ht string_cache; - qcint_t string_cached_empty; + qcint_t string_cached_empty = 0; }; /* @@ -589,7 +597,7 @@ void compile_show_werrors(void); /* ir.c */ /* TODO: cleanup */ -enum store_types { +enum store_type { store_global, store_local, /* local, assignable for now, should get promoted later */ store_param, /* parameters, they are locals with a fixed position */ diff --git a/intrin.cpp b/intrin.cpp index e55cf0f..cc6250b 100644 --- a/intrin.cpp +++ b/intrin.cpp @@ -8,7 +8,7 @@ lex_ctx_t intrin::ctx() const { return parser_ctx(m_parser); } -ast_function *intrin::value(ast_value **out, const char *name, qcint_t vtype) { +ast_function *intrin::value(ast_value **out, const char *name, qc_type vtype) { ast_value *value = nullptr; ast_function *func = nullptr; char buffer[1024]; @@ -18,10 +18,10 @@ ast_function *intrin::value(ast_value **out, const char *name, qcint_t vtype) { util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]); value = ast_value_new(ctx(), buffer, TYPE_FUNCTION); - value->intrinsic = true; - value->expression.next = (ast_expression*)ast_value_new(ctx(), stype, vtype); + value->m_intrinsic = true; + value->m_next = (ast_expression*)ast_value_new(ctx(), stype, vtype); func = ast_function_new(ctx(), buffer, value); - value->expression.flags |= AST_FLAG_ERASEABLE; + value->m_flags |= AST_FLAG_ERASEABLE; *out = value; return func; @@ -55,16 +55,16 @@ ast_expression *intrin::isfinite_() { ast_block *block = ast_block_new(ctx()); /* float x; */ - val->expression.params.push_back(x); + val->m_type_params.push_back(x); /* = isnan(x); */ - callisnan->params.push_back((ast_expression*)x); + callisnan->m_params.push_back((ast_expression*)x); /* = isinf(x); */ - callisinf->params.push_back((ast_expression*)x); + callisinf->m_params.push_back((ast_expression*)x); /* return (! || ); */ - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_unary_new( @@ -80,7 +80,7 @@ ast_expression *intrin::isfinite_() { ) ); - func->blocks.push_back(block); + func->m_blocks.emplace_back(block); reg(val, func); return (ast_expression*)val;; @@ -97,7 +97,7 @@ ast_expression *intrin::isinf_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "isinf", TYPE_FLOAT); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -124,8 +124,8 @@ ast_expression *intrin::isinf_() { ) ); - val->expression.params.push_back(x); - func->blocks.push_back(body); + val->m_type_params.push_back(x); + func->m_blocks.emplace_back(body); reg(val, func); @@ -147,8 +147,8 @@ ast_expression *intrin::isnan_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "isnan", TYPE_FLOAT); - body->locals.push_back(local); - body->exprs.push_back( + body->m_locals.push_back(local); + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -157,7 +157,7 @@ ast_expression *intrin::isnan_() { ) ); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -169,8 +169,8 @@ ast_expression *intrin::isnan_() { ) ); - val->expression.params.push_back(arg1); - func->blocks.push_back(body); + val->m_type_params.push_back(arg1); + func->m_blocks.emplace_back(body); reg(val, func); @@ -189,18 +189,18 @@ ast_expression *intrin::isnormal_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "isnormal", TYPE_FLOAT); - val->expression.params.push_back(x); - callisfinite->params.push_back((ast_expression*)x); + val->m_type_params.push_back(x); + callisfinite->m_params.push_back((ast_expression*)x); /* return */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)callisfinite ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -216,10 +216,10 @@ ast_expression *intrin::signbit_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "signbit", TYPE_FLOAT); - val->expression.params.push_back(x); + val->m_type_params.push_back(x); /* return (x < 0); */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_ternary_new( @@ -236,7 +236,7 @@ ast_expression *intrin::signbit_() { ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -254,10 +254,10 @@ ast_expression *intrin::acosh_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "acosh", TYPE_FLOAT); - val->expression.params.push_back(x); + val->m_type_params.push_back(x); /* = sqrt((x * x) - 1); */ - callsqrt->params.push_back( + callsqrt->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_SUB_F, @@ -272,7 +272,7 @@ ast_expression *intrin::acosh_() { ); /* = log(x + ); */ - calllog->params.push_back( + calllog->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_ADD_F, @@ -282,14 +282,14 @@ ast_expression *intrin::acosh_() { ); /* return ; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)calllog ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -307,10 +307,10 @@ ast_expression *intrin::asinh_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "asinh", TYPE_FLOAT); - val->expression.params.push_back(x); + val->m_type_params.push_back(x); /* = sqrt((x * x) + 1); */ - callsqrt->params.push_back( + callsqrt->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_ADD_F, @@ -325,7 +325,7 @@ ast_expression *intrin::asinh_() { ); /* = log(x + ); */ - calllog->params.push_back( + calllog->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_ADD_F, @@ -335,14 +335,14 @@ ast_expression *intrin::asinh_() { ); /* return ; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)calllog ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -359,10 +359,10 @@ ast_expression *intrin::atanh_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "atanh", TYPE_FLOAT); - val->expression.params.push_back(x); + val->m_type_params.push_back(x); /* = log((1 + x) / (1 - x)); */ - calllog->params.push_back( + calllog->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_DIV_F, @@ -382,7 +382,7 @@ ast_expression *intrin::atanh_() { ); /* return 0.5 * ; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_MUL_F, @@ -391,7 +391,7 @@ ast_expression *intrin::atanh_() { ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -416,14 +416,14 @@ ast_expression *intrin::exp_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "exp", TYPE_FLOAT); - val->expression.params.push_back(x); + val->m_type_params.push_back(x); - body->locals.push_back(sum); - body->locals.push_back(acc); - body->locals.push_back(i); + body->m_locals.push_back(sum); + body->m_locals.push_back(acc); + body->m_locals.push_back(i); /* sum = 1.0; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -433,7 +433,7 @@ ast_expression *intrin::exp_() { ); /* acc = 1.0; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -446,7 +446,7 @@ ast_expression *intrin::exp_() { * for (i = 1; i < 200; ++i) * sum += (acc *= x / i); */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_loop_new( ctx(), /* i = 1; */ @@ -497,14 +497,14 @@ ast_expression *intrin::exp_() { ); /* return sum; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)sum ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -521,20 +521,20 @@ ast_expression *intrin::exp2_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "exp2", TYPE_FLOAT); - val->expression.params.push_back(arg1); + val->m_type_params.push_back(arg1); - callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]); - callpow->params.push_back((ast_expression*)arg1); + callpow->m_params.push_back((ast_expression*)m_fold->m_imm_float[3]); + callpow->m_params.push_back((ast_expression*)arg1); /* return */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)callpow ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -551,13 +551,13 @@ ast_expression *intrin::expm1_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "expm1", TYPE_FLOAT); - val->expression.params.push_back(x); + val->m_type_params.push_back(x); /* = exp(x); */ - callexp->params.push_back((ast_expression*)x); + callexp->m_params.push_back((ast_expression*)x); /* return - 1; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -569,7 +569,7 @@ ast_expression *intrin::expm1_() { ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -652,21 +652,21 @@ ast_expression *intrin::pow_() { ast_value *square = ast_value_new(ctx(), "square", TYPE_FLOAT); ast_value *accumulate = ast_value_new(ctx(), "accumulate", TYPE_FLOAT); ast_value *mid = ast_value_new(ctx(), "mid", TYPE_FLOAT); - body->locals.push_back(result); - body->locals.push_back(low); - body->locals.push_back(high); - body->locals.push_back(square); - body->locals.push_back(accumulate); - body->locals.push_back(mid); + body->m_locals.push_back(result); + body->m_locals.push_back(low); + body->m_locals.push_back(high); + body->m_locals.push_back(square); + body->m_locals.push_back(accumulate); + body->m_locals.push_back(mid); - val->expression.params.push_back(base); - val->expression.params.push_back(exp); + val->m_type_params.push_back(base); + val->m_type_params.push_back(exp); /* * if (exp == 0.0) * return 1; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -687,7 +687,7 @@ ast_expression *intrin::pow_() { * if (exp == 1.0) * return base; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -705,8 +705,8 @@ ast_expression *intrin::pow_() { ); /* = pow(base, -exp) */ - callpow1->params.push_back((ast_expression*)base); - callpow1->params.push_back( + callpow1->m_params.push_back((ast_expression*)base); + callpow1->m_params.push_back( (ast_expression*)ast_unary_new( ctx(), VINSTR_NEG_F, @@ -718,7 +718,7 @@ ast_expression *intrin::pow_() { * if (exp < 0) * return 1.0 / ; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -741,8 +741,8 @@ ast_expression *intrin::pow_() { ); /* = pow(base, exp / 2) */ - callpow2->params.push_back((ast_expression*)base); - callpow2->params.push_back( + callpow2->m_params.push_back((ast_expression*)base); + callpow2->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_DIV_F, @@ -757,7 +757,7 @@ ast_expression *intrin::pow_() { * return result * result; * } */ - expgt1->exprs.push_back( + expgt1->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -765,7 +765,7 @@ ast_expression *intrin::pow_() { (ast_expression*)callpow2 ) ); - expgt1->exprs.push_back( + expgt1->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -782,7 +782,7 @@ ast_expression *intrin::pow_() { * * } */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -799,7 +799,7 @@ ast_expression *intrin::pow_() { /* * = sqrt(base) */ - callsqrt1->params.push_back((ast_expression*)base); + callsqrt1->m_params.push_back((ast_expression*)base); /* * low = 0.0f; @@ -808,14 +808,14 @@ ast_expression *intrin::pow_() { * accumulate = square; * mid = high / 2.0f; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new(ctx(), INSTR_STORE_F, (ast_expression*)low, (ast_expression*)m_fold->m_imm_float[0] ) ); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -824,7 +824,7 @@ ast_expression *intrin::pow_() { ) ); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -833,7 +833,7 @@ ast_expression *intrin::pow_() { ) ); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -841,7 +841,7 @@ ast_expression *intrin::pow_() { (ast_expression*)square ) ); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -861,7 +861,7 @@ ast_expression *intrin::pow_() { * accumulate *= square; * } */ - midltexp->exprs.push_back( + midltexp->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -869,7 +869,7 @@ ast_expression *intrin::pow_() { (ast_expression*)mid ) ); - midltexp->exprs.push_back( + midltexp->m_exprs.push_back( (ast_expression*)ast_binstore_new( ctx(), INSTR_STORE_F, @@ -885,7 +885,7 @@ ast_expression *intrin::pow_() { * accumulate *= (1.0 / square); * } */ - midltexpelse->exprs.push_back( + midltexpelse->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -893,7 +893,7 @@ ast_expression *intrin::pow_() { (ast_expression*)mid ) ); - midltexpelse->exprs.push_back( + midltexpelse->m_exprs.push_back( (ast_expression*)ast_binstore_new( ctx(), INSTR_STORE_F, @@ -911,7 +911,7 @@ ast_expression *intrin::pow_() { /* * = sqrt(square) */ - callsqrt2->params.push_back((ast_expression*)square); + callsqrt2->m_params.push_back((ast_expression*)square); /* * = { @@ -924,7 +924,7 @@ ast_expression *intrin::pow_() { * mid = (low + high) / 2; * } */ - whileblock->exprs.push_back( + whileblock->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -932,7 +932,7 @@ ast_expression *intrin::pow_() { (ast_expression*)callsqrt2 ) ); - whileblock->exprs.push_back( + whileblock->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -945,7 +945,7 @@ ast_expression *intrin::pow_() { (ast_expression*)midltexpelse ) ); - whileblock->exprs.push_back( + whileblock->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -967,7 +967,7 @@ ast_expression *intrin::pow_() { /* * = fabs(mid - exp) */ - callfabs->params.push_back( + callfabs->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_SUB_F, @@ -980,7 +980,7 @@ ast_expression *intrin::pow_() { * while ( > epsilon) * */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_loop_new( ctx(), /* init */ @@ -1006,7 +1006,7 @@ ast_expression *intrin::pow_() { ); /* return accumulate */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)accumulate @@ -1014,7 +1014,7 @@ ast_expression *intrin::pow_() { ); /* } */ - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1036,14 +1036,14 @@ ast_expression *intrin::mod_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "mod", TYPE_FLOAT); - val->expression.params.push_back(a); - val->expression.params.push_back(b); + val->m_type_params.push_back(a); + val->m_type_params.push_back(b); - body->locals.push_back(div); - body->locals.push_back(sign); + body->m_locals.push_back(div); + body->m_locals.push_back(sign); /* div = a / b; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1058,7 +1058,7 @@ ast_expression *intrin::mod_() { ); /* sign = (div < 0.0f) ? -1 : 1; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1078,7 +1078,7 @@ ast_expression *intrin::mod_() { ); /* floor(sign * div) */ - call->params.push_back( + call->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), INSTR_MUL_F, @@ -1088,7 +1088,7 @@ ast_expression *intrin::mod_() { ); /* return a - b * sign * */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -1110,7 +1110,7 @@ ast_expression *intrin::mod_() { ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1126,7 +1126,7 @@ ast_expression *intrin::fabs_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "fabs", TYPE_FLOAT); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_ternary_new( @@ -1147,9 +1147,9 @@ ast_expression *intrin::fabs_() { ) ); - val->expression.params.push_back(arg1); + val->m_type_params.push_back(arg1); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1167,10 +1167,10 @@ ast_expression *intrin::epsilon_() { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, "epsilon", TYPE_FLOAT); - body->locals.push_back(eps); + body->m_locals.push_back(eps); /* eps = 1.0f; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1179,7 +1179,7 @@ ast_expression *intrin::epsilon_() { ) ); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_loop_new( ctx(), nullptr, @@ -1214,14 +1214,14 @@ ast_expression *intrin::epsilon_() { ); /* return eps; */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)eps ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1238,9 +1238,9 @@ ast_expression *intrin::nan_() { ast_function *func = value(&val, "nan", TYPE_FLOAT); ast_block *block = ast_block_new(ctx()); - block->locals.push_back(x); + block->m_locals.push_back(x); - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1249,7 +1249,7 @@ ast_expression *intrin::nan_() { ) ); - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -1261,7 +1261,7 @@ ast_expression *intrin::nan_() { ) ); - func->blocks.push_back(block); + func->m_blocks.emplace_back(block); reg(val, func); return (ast_expression*)val; } @@ -1281,12 +1281,12 @@ ast_expression *intrin::inf_() { ast_block *block = ast_block_new(ctx()); size_t i; - block->locals.push_back(x); - block->locals.push_back(y); + block->m_locals.push_back(x); + block->m_locals.push_back(y); /* to keep code size down */ for (i = 0; i <= 1; i++) { - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1296,7 +1296,7 @@ ast_expression *intrin::inf_() { ); } - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -1308,7 +1308,7 @@ ast_expression *intrin::inf_() { ) ); - func->blocks.push_back(block); + func->m_blocks.emplace_back(block); reg(val, func); return (ast_expression*)val; } @@ -1406,20 +1406,20 @@ ast_expression *intrin::ln_() { ast_function *func = value(&val, "ln", TYPE_FLOAT); size_t i; - val->expression.params.push_back(power); - val->expression.params.push_back(base); + val->m_type_params.push_back(power); + val->m_type_params.push_back(base); - block->locals.push_back(whole); - block->locals.push_back(nth); - block->locals.push_back(sign); - block->locals.push_back(eps); - block->locals.push_back(A_i); - block->locals.push_back(B_i); - block->locals.push_back(A_iminus1); - block->locals.push_back(B_iminus1); + block->m_locals.push_back(whole); + block->m_locals.push_back(nth); + block->m_locals.push_back(sign); + block->m_locals.push_back(eps); + block->m_locals.push_back(A_i); + block->m_locals.push_back(B_i); + block->m_locals.push_back(A_iminus1); + block->m_locals.push_back(B_iminus1); /* sign = 1.0f; */ - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1429,7 +1429,7 @@ ast_expression *intrin::ln_() { ); /* eps = __builtin_epsilon(); */ - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1450,7 +1450,7 @@ ast_expression *intrin::ln_() { for (i = 0; i <= 1; i++) { int j; for (j = 1; j >= 0; j--) { - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1473,7 +1473,7 @@ ast_expression *intrin::ln_() { * } */ for (i = 0; i <= 1; i++) { - ((i) ? blt1 : plt1)->exprs.push_back( + ((i) ? blt1 : plt1)->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1486,7 +1486,7 @@ ast_expression *intrin::ln_() { ) ) ); - plt1->exprs.push_back( + plt1->m_exprs.push_back( (ast_expression*)ast_binstore_new( ctx(), INSTR_STORE_F, @@ -1507,7 +1507,7 @@ ast_expression *intrin::ln_() { * * } */ - plt1orblt1->exprs.push_back( + plt1orblt1->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -1538,7 +1538,7 @@ ast_expression *intrin::ln_() { ); for (i = 0; i <= 1; i++) { - plt1orblt1->exprs.push_back( + plt1orblt1->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -1553,11 +1553,11 @@ ast_expression *intrin::ln_() { ); } - block->exprs.push_back((ast_expression*)plt1orblt1); + block->m_exprs.push_back((ast_expression*)plt1orblt1); /* whole = power; */ - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1567,7 +1567,7 @@ ast_expression *intrin::ln_() { ); /* nth = 0.0f; */ - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1577,7 +1577,7 @@ ast_expression *intrin::ln_() { ); /* base2 = base; */ - whileloop->exprs.push_back( + whileloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1587,7 +1587,7 @@ ast_expression *intrin::ln_() { ); /* n2 = 1.0f; */ - whileloop->exprs.push_back( + whileloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1597,7 +1597,7 @@ ast_expression *intrin::ln_() { ); /* newbase2 = base2 * base2; */ - whileloop->exprs.push_back( + whileloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1612,12 +1612,12 @@ ast_expression *intrin::ln_() { ); /* while loop locals */ - whileloop->locals.push_back(base2); - whileloop->locals.push_back(n2); - whileloop->locals.push_back(newbase2); + whileloop->m_locals.push_back(base2); + whileloop->m_locals.push_back(n2); + whileloop->m_locals.push_back(newbase2); /* base2 = newbase2; */ - nestwhile->exprs.push_back( + nestwhile->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1627,7 +1627,7 @@ ast_expression *intrin::ln_() { ); /* n2 *= 2; */ - nestwhile->exprs.push_back( + nestwhile->m_exprs.push_back( (ast_expression*)ast_binstore_new( ctx(), INSTR_STORE_F, @@ -1638,7 +1638,7 @@ ast_expression *intrin::ln_() { ); /* newbase2 *= newbase2; */ - nestwhile->exprs.push_back( + nestwhile->m_exprs.push_back( (ast_expression*)ast_binstore_new( ctx(), INSTR_STORE_F, @@ -1649,7 +1649,7 @@ ast_expression *intrin::ln_() { ); /* while (whole >= newbase2) */ - whileloop->exprs.push_back( + whileloop->m_exprs.push_back( (ast_expression*)ast_loop_new( ctx(), nullptr, @@ -1668,7 +1668,7 @@ ast_expression *intrin::ln_() { ); /* whole /= base2; */ - whileloop->exprs.push_back( + whileloop->m_exprs.push_back( (ast_expression*)ast_binstore_new( ctx(), INSTR_STORE_F, @@ -1679,7 +1679,7 @@ ast_expression *intrin::ln_() { ); /* nth += n2; */ - whileloop->exprs.push_back( + whileloop->m_exprs.push_back( (ast_expression*)ast_binstore_new( ctx(), INSTR_STORE_F, @@ -1690,7 +1690,7 @@ ast_expression *intrin::ln_() { ); /* while (whole >= base) */ - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_loop_new( ctx(), nullptr, @@ -1708,12 +1708,12 @@ ast_expression *intrin::ln_() { ) ); - forloop->locals.push_back(b_iplus1); - forloop->locals.push_back(A_iplus1); - forloop->locals.push_back(B_iplus1); + forloop->m_locals.push_back(b_iplus1); + forloop->m_locals.push_back(A_iplus1); + forloop->m_locals.push_back(B_iplus1); /* b_iplus1 = nth; */ - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1727,7 +1727,7 @@ ast_expression *intrin::ln_() { * B_iplus1 = b_iplus1 * B_i + B_iminus1; */ for (i = 0; i <= 1; i++) { - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1752,7 +1752,7 @@ ast_expression *intrin::ln_() { * B_iminus1 = B_i; */ for (i = 0; i <= 1; i++) { - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1767,7 +1767,7 @@ ast_expression *intrin::ln_() { * B_i = B_iplus1; */ for (i = 0; i <= 1; i++) { - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1781,7 +1781,7 @@ ast_expression *intrin::ln_() { * if (whole <= 1.0f + eps) * break; */ - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_ifthen_new( ctx(), (ast_expression*)ast_binary_new( @@ -1809,7 +1809,7 @@ ast_expression *intrin::ln_() { * base = whole; */ for (i = 0; i <= 1; i++) { - forloop->exprs.push_back( + forloop->m_exprs.push_back( (ast_expression*)ast_store_new( ctx(), INSTR_STORE_F, @@ -1820,7 +1820,7 @@ ast_expression *intrin::ln_() { } /* add the for loop block */ - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_loop_new( ctx(), nullptr, @@ -1835,7 +1835,7 @@ ast_expression *intrin::ln_() { ); /* return sign * A_i / B_il */ - block->exprs.push_back( + block->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( @@ -1852,7 +1852,7 @@ ast_expression *intrin::ln_() { ) ); - func->blocks.push_back(block); + func->m_blocks.emplace_back(block); reg(val, func); return (ast_expression*)val; } @@ -1864,19 +1864,19 @@ ast_expression *intrin::log_variant(const char *name, float base) { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, name, TYPE_FLOAT); - val->expression.params.push_back(arg1); + val->m_type_params.push_back(arg1); - callln->params.push_back((ast_expression*)arg1); - callln->params.push_back((ast_expression*)m_fold->constgen_float(base, false)); + callln->m_params.push_back((ast_expression*)arg1); + callln->m_params.push_back((ast_expression*)m_fold->constgen_float(base, false)); - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)callln ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1908,15 +1908,15 @@ ast_expression *intrin::shift_variant(const char *name, size_t instr) { ast_block *body = ast_block_new(ctx()); ast_function *func = value(&val, name, TYPE_FLOAT); - val->expression.params.push_back(a); - val->expression.params.push_back(b); + val->m_type_params.push_back(a); + val->m_type_params.push_back(b); /* = pow(2, b) */ - callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]); - callpow->params.push_back((ast_expression*)b); + callpow->m_params.push_back((ast_expression*)m_fold->m_imm_float[3]); + callpow->m_params.push_back((ast_expression*)b); /* = floor(a [instr] ) */ - callfloor->params.push_back( + callfloor->m_params.push_back( (ast_expression*)ast_binary_new( ctx(), instr, @@ -1926,14 +1926,14 @@ ast_expression *intrin::shift_variant(const char *name, size_t instr) { ); /* return */ - body->exprs.push_back( + body->m_exprs.push_back( (ast_expression*)ast_return_new( ctx(), (ast_expression*)callfloor ) ); - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1998,14 +1998,14 @@ intrin::intrin(parser_t *parser) } ast_expression *intrin::do_fold(ast_value *val, ast_expression **exprs) { - if (!val || !val->name) + if (!val || !val->m_name) return nullptr; static constexpr size_t kPrefixLength = 10; // "__builtin_" for (auto &it : m_intrinsics) { - if (!strcmp(val->name, it.name)) + if (!strcmp(val->m_name, it.name)) return (vec_size(exprs) != it.args) ? nullptr - : m_fold->intrinsic(val->name + kPrefixLength, exprs); + : m_fold->intrinsic(val->m_name + kPrefixLength, exprs); } return nullptr; } @@ -2025,9 +2025,9 @@ ast_expression *intrin::func_try(size_t offset, const char *compare) { ast_expression *intrin::func_self(const char *name, const char *from) { ast_expression *find; /* try current first */ - if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION) + if ((find = parser_find_global(m_parser, name)) && ((ast_value*)find)->m_vtype == TYPE_FUNCTION) for (auto &it : m_parser->functions) - if (((ast_value*)find)->name && !strcmp(it->name, ((ast_value*)find)->name) && it->builtin < 0) + if (((ast_value*)find)->m_name && !strcmp(it->m_name, ((ast_value*)find)->m_name) && it->m_builtin < 0) return find; /* try name second */ if ((find = func_try(offsetof(intrin_func_t, name), name))) diff --git a/intrin.h b/intrin.h index e0151d8..fe9ee78 100644 --- a/intrin.h +++ b/intrin.h @@ -30,7 +30,7 @@ struct intrin { protected: lex_ctx_t ctx() const; - ast_function *value(ast_value **out, const char *name, qcint_t vtype); + ast_function *value(ast_value **out, const char *name, qc_type vtype); void reg(ast_value *const value, ast_function *const func); ast_expression *nullfunc(); diff --git a/ir.cpp b/ir.cpp index 92cd11d..ba4ed64 100644 --- a/ir.cpp +++ b/ir.cpp @@ -190,30 +190,19 @@ const uint16_t type_not_instr[TYPE_COUNT] = { }; /* protos */ -static ir_value* ir_value_var(const char *name, int st, int vtype); -static bool ir_value_set_name(ir_value*, const char *name); static void ir_value_dump(ir_value*, int (*oprintf)(const char*,...)); static ir_value* ir_gen_extparam_proto(ir_builder *ir); static void ir_gen_extparam (ir_builder *ir); -static bool ir_builder_set_name(ir_builder *self, const char *name); - -static ir_function* ir_function_new(ir_builder *owner, int returntype); -static bool ir_function_set_name(ir_function*, const char *name); -static void ir_function_delete(ir_function*); static void ir_function_dump(ir_function*, char *ind, int (*oprintf)(const char*,...)); static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t, const char *label, - int op, ir_value *a, ir_value *b, int outype); -static void ir_block_delete(ir_block*); -static ir_block* ir_block_new(ir_function *owner, const char *label); + int op, ir_value *a, ir_value *b, qc_type outype); static bool GMQCC_WARN ir_block_create_store(ir_block*, lex_ctx_t, ir_value *target, ir_value *what); -static bool ir_block_set_label(ir_block*, const char *label); static void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...)); static bool ir_instr_op(ir_instr*, int op, ir_value *value, bool writing); -static void ir_instr_delete(ir_instr*); static void ir_instr_dump(ir_instr* in, char *ind, int (*oprintf)(const char*,...)); /* error functions */ @@ -284,184 +273,124 @@ static void ir_block_delete_quick(ir_block* self); static void ir_instr_delete_quick(ir_instr *self); static void ir_function_delete_quick(ir_function *self); -ir_builder* ir_builder_new(const char *modulename) +ir_builder::ir_builder(const std::string& modulename) +: m_name(modulename), + m_code(new code_t) { - ir_builder* self; - size_t i; - - self = (ir_builder*)mem_a(sizeof(*self)); - if (!self) - return nullptr; - - self->functions = nullptr; - self->globals = nullptr; - self->fields = nullptr; - self->filenames = nullptr; - self->filestrings = nullptr; - self->htglobals = util_htnew(IR_HT_SIZE); - self->htfields = util_htnew(IR_HT_SIZE); - self->htfunctions = util_htnew(IR_HT_SIZE); - - self->extparams = nullptr; - self->extparam_protos = nullptr; - - self->first_common_globaltemp = 0; - self->max_globaltemps = 0; - self->first_common_local = 0; - self->max_locals = 0; - - self->str_immediate = 0; - self->name = nullptr; - if (!ir_builder_set_name(self, modulename)) { - mem_d(self); - return nullptr; - } + m_htglobals = util_htnew(IR_HT_SIZE); + m_htfields = util_htnew(IR_HT_SIZE); + m_htfunctions = util_htnew(IR_HT_SIZE); - self->nil = ir_value_var("nil", store_value, TYPE_NIL); - self->nil->cvq = CV_CONST; + m_nil = new ir_value("nil", store_value, TYPE_NIL); + m_nil->m_cvq = CV_CONST; - for (i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { + for (size_t i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { /* we write to them, but they're not supposed to be used outside the IR, so * let's not allow the generation of ir_instrs which use these. * So it's a constant noexpr. */ - self->vinstr_temp[i] = ir_value_var("vinstr_temp", store_value, TYPE_NOEXPR); - self->vinstr_temp[i]->cvq = CV_CONST; + m_vinstr_temp[i] = new ir_value("vinstr_temp", store_value, TYPE_NOEXPR); + m_vinstr_temp[i]->m_cvq = CV_CONST; } - - self->reserved_va_count = nullptr; - self->coverage_func = nullptr; - - self->code = code_init(); - - return self; } -void ir_builder_delete(ir_builder* self) +ir_builder::~ir_builder() { - size_t i; - util_htdel(self->htglobals); - util_htdel(self->htfields); - util_htdel(self->htfunctions); - mem_d((void*)self->name); - for (i = 0; i != vec_size(self->functions); ++i) { - ir_function_delete_quick(self->functions[i]); - } - vec_free(self->functions); - for (i = 0; i != vec_size(self->extparams); ++i) { - ir_value_delete(self->extparams[i]); - } - vec_free(self->extparams); - vec_free(self->extparam_protos); - for (i = 0; i != vec_size(self->globals); ++i) { - ir_value_delete(self->globals[i]); - } - vec_free(self->globals); - for (i = 0; i != vec_size(self->fields); ++i) { - ir_value_delete(self->fields[i]); - } - ir_value_delete(self->nil); - for (i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { - ir_value_delete(self->vinstr_temp[i]); - } - vec_free(self->fields); - vec_free(self->filenames); - vec_free(self->filestrings); - - code_cleanup(self->code); - mem_d(self); -} + util_htdel(m_htglobals); + util_htdel(m_htfields); + util_htdel(m_htfunctions); + for (auto& f : m_functions) + ir_function_delete_quick(f.release()); + m_functions.clear(); // delete them now before deleting the rest: -bool ir_builder_set_name(ir_builder *self, const char *name) -{ - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; + delete m_nil; + + for (size_t i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { + delete m_vinstr_temp[i]; + } + + m_extparams.clear(); + m_extparam_protos.clear(); } static ir_function* ir_builder_get_function(ir_builder *self, const char *name) { - return (ir_function*)util_htget(self->htfunctions, name); + return (ir_function*)util_htget(self->m_htfunctions, name); } -ir_function* ir_builder_create_function(ir_builder *self, const char *name, int outtype) +ir_function* ir_builder_create_function(ir_builder *self, const std::string& name, qc_type outtype) { - ir_function *fn = ir_builder_get_function(self, name); + ir_function *fn = ir_builder_get_function(self, name.c_str()); if (fn) { return nullptr; } - fn = ir_function_new(self, outtype); - if (!ir_function_set_name(fn, name)) - { - ir_function_delete(fn); - return nullptr; - } - vec_push(self->functions, fn); - util_htset(self->htfunctions, name, fn); + fn = new ir_function(self, outtype); + fn->m_name = name; + self->m_functions.emplace_back(fn); + util_htset(self->m_htfunctions, name.c_str(), fn); - fn->value = ir_builder_create_global(self, fn->name, TYPE_FUNCTION); - if (!fn->value) { - ir_function_delete(fn); + fn->m_value = ir_builder_create_global(self, fn->m_name, TYPE_FUNCTION); + if (!fn->m_value) { + delete fn; return nullptr; } - fn->value->hasvalue = true; - fn->value->outtype = outtype; - fn->value->constval.vfunc = fn; - fn->value->context = fn->context; + fn->m_value->m_hasvalue = true; + fn->m_value->m_outtype = outtype; + fn->m_value->m_constval.vfunc = fn; + fn->m_value->m_context = fn->m_context; return fn; } static ir_value* ir_builder_get_global(ir_builder *self, const char *name) { - return (ir_value*)util_htget(self->htglobals, name); + return (ir_value*)util_htget(self->m_htglobals, name); } -ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype) +ir_value* ir_builder_create_global(ir_builder *self, const std::string& name, qc_type vtype) { ir_value *ve; if (name[0] != '#') { - ve = ir_builder_get_global(self, name); + ve = ir_builder_get_global(self, name.c_str()); if (ve) { return nullptr; } } - ve = ir_value_var(name, store_global, vtype); - vec_push(self->globals, ve); - util_htset(self->htglobals, name, ve); + ve = new ir_value(std::string(name), store_global, vtype); + self->m_globals.emplace_back(ve); + util_htset(self->m_htglobals, name.c_str(), ve); return ve; } ir_value* ir_builder_get_va_count(ir_builder *self) { - if (self->reserved_va_count) - return self->reserved_va_count; - return (self->reserved_va_count = ir_builder_create_global(self, "reserved:va_count", TYPE_FLOAT)); + if (self->m_reserved_va_count) + return self->m_reserved_va_count; + return (self->m_reserved_va_count = ir_builder_create_global(self, "reserved:va_count", TYPE_FLOAT)); } static ir_value* ir_builder_get_field(ir_builder *self, const char *name) { - return (ir_value*)util_htget(self->htfields, name); + return (ir_value*)util_htget(self->m_htfields, name); } -ir_value* ir_builder_create_field(ir_builder *self, const char *name, int vtype) +ir_value* ir_builder_create_field(ir_builder *self, const std::string& name, qc_type vtype) { - ir_value *ve = ir_builder_get_field(self, name); + ir_value *ve = ir_builder_get_field(self, name.c_str()); if (ve) { return nullptr; } - ve = ir_value_var(name, store_global, TYPE_FIELD); - ve->fieldtype = vtype; - vec_push(self->fields, ve); - util_htset(self->htfields, name, ve); + ve = new ir_value(std::string(name), store_global, TYPE_FIELD); + ve->m_fieldtype = vtype; + self->m_fields.emplace_back(ve); + util_htset(self->m_htfields, name.c_str(), ve); return ve; } @@ -474,114 +403,39 @@ static void ir_function_enumerate(ir_function*); static bool ir_function_calculate_liferanges(ir_function*); static bool ir_function_allocate_locals(ir_function*); -ir_function* ir_function_new(ir_builder* owner, int outtype) +ir_function::ir_function(ir_builder* owner_, qc_type outtype_) +: m_owner(owner_), + m_name("<@unnamed>"), + m_outtype(outtype_) { - ir_function *self; - self = (ir_function*)mem_a(sizeof(*self)); - - if (!self) - return nullptr; - - memset(self, 0, sizeof(*self)); - - self->name = nullptr; - if (!ir_function_set_name(self, "<@unnamed>")) { - mem_d(self); - return nullptr; - } - self->flags = 0; - - self->owner = owner; - self->context.file = "<@no context>"; - self->context.line = 0; - self->outtype = outtype; - self->value = nullptr; - self->builtin = 0; - - self->params = nullptr; - self->blocks = nullptr; - self->values = nullptr; - self->locals = nullptr; - - self->max_varargs = 0; - - self->code_function_def = -1; - self->allocated_locals = 0; - self->globaltemps = 0; - - self->run_id = 0; - return self; + m_context.file = "<@no context>"; + m_context.line = 0; } -bool ir_function_set_name(ir_function *self, const char *name) +ir_function::~ir_function() { - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; } static void ir_function_delete_quick(ir_function *self) { - size_t i; - mem_d((void*)self->name); - - for (i = 0; i != vec_size(self->blocks); ++i) - ir_block_delete_quick(self->blocks[i]); - vec_free(self->blocks); - - vec_free(self->params); - - for (i = 0; i != vec_size(self->values); ++i) - ir_value_delete(self->values[i]); - vec_free(self->values); - - for (i = 0; i != vec_size(self->locals); ++i) - ir_value_delete(self->locals[i]); - vec_free(self->locals); - - /* self->value is deleted by the builder */ - - mem_d(self); -} - -void ir_function_delete(ir_function *self) -{ - size_t i; - mem_d((void*)self->name); - - for (i = 0; i != vec_size(self->blocks); ++i) - ir_block_delete(self->blocks[i]); - vec_free(self->blocks); - - vec_free(self->params); - - for (i = 0; i != vec_size(self->values); ++i) - ir_value_delete(self->values[i]); - vec_free(self->values); - - for (i = 0; i != vec_size(self->locals); ++i) - ir_value_delete(self->locals[i]); - vec_free(self->locals); - - /* self->value is deleted by the builder */ - - mem_d(self); + for (auto& b : self->m_blocks) + ir_block_delete_quick(b.release()); + delete self; } static void ir_function_collect_value(ir_function *self, ir_value *v) { - vec_push(self->values, v); + self->m_values.emplace_back(v); } ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function *self, const char *label) { - ir_block* bn = ir_block_new(self, label); - bn->context = ctx; - vec_push(self->blocks, bn); + ir_block* bn = new ir_block(self, label ? std::string(label) : std::string()); + bn->m_context = ctx; + self->m_blocks.emplace_back(bn); - if ((self->flags & IR_FLAG_BLOCK_COVERAGE) && self->owner->coverage_func) - (void)ir_block_create_call(bn, ctx, nullptr, self->owner->coverage_func, false); + if ((self->m_flags & IR_FLAG_BLOCK_COVERAGE) && self->m_owner->m_coverage_func) + (void)ir_block_create_call(bn, ctx, nullptr, self->m_owner->m_coverage_func, false); return bn; } @@ -599,19 +453,15 @@ static bool instr_is_operation(uint16_t op) static bool ir_function_pass_peephole(ir_function *self) { - size_t b; - - for (b = 0; b < vec_size(self->blocks); ++b) { - size_t i; - ir_block *block = self->blocks[b]; - - for (i = 0; i < vec_size(block->instr); ++i) { + for (auto& bp : self->m_blocks) { + ir_block *block = bp.get(); + for (size_t i = 0; i < vec_size(block->m_instr); ++i) { ir_instr *inst; - inst = block->instr[i]; + inst = block->m_instr[i]; if (i >= 1 && - (inst->opcode >= INSTR_STORE_F && - inst->opcode <= INSTR_STORE_FNC)) + (inst->m_opcode >= INSTR_STORE_F && + inst->m_opcode <= INSTR_STORE_FNC)) { ir_instr *store; ir_instr *oper; @@ -619,44 +469,44 @@ static bool ir_function_pass_peephole(ir_function *self) store = inst; - oper = block->instr[i-1]; - if (!instr_is_operation(oper->opcode)) + oper = block->m_instr[i-1]; + if (!instr_is_operation(oper->m_opcode)) continue; /* Don't change semantics of MUL_VF in engines where these may not alias. */ if (OPTS_FLAG(LEGACY_VECTOR_MATHS)) { - if (oper->opcode == INSTR_MUL_VF && oper->_ops[2]->memberof == oper->_ops[1]) + if (oper->m_opcode == INSTR_MUL_VF && oper->_m_ops[2]->m_memberof == oper->_m_ops[1]) continue; - if (oper->opcode == INSTR_MUL_FV && oper->_ops[1]->memberof == oper->_ops[2]) + if (oper->m_opcode == INSTR_MUL_FV && oper->_m_ops[1]->m_memberof == oper->_m_ops[2]) continue; } - value = oper->_ops[0]; + value = oper->_m_ops[0]; /* only do it for SSA values */ - if (value->store != store_value) + if (value->m_store != store_value) continue; /* don't optimize out the temp if it's used later again */ - if (value->reads.size() != 1) + if (value->m_reads.size() != 1) continue; /* The very next store must use this value */ - if (value->reads[0] != store) + if (value->m_reads[0] != store) continue; /* And of course the store must _read_ from it, so it's in * OP 1 */ - if (store->_ops[1] != value) + if (store->_m_ops[1] != value) continue; ++opts_optimizationcount[OPTIM_PEEPHOLE]; - (void)!ir_instr_op(oper, 0, store->_ops[0], true); + (void)!ir_instr_op(oper, 0, store->_m_ops[0], true); - vec_remove(block->instr, i, 1); - ir_instr_delete(store); + vec_remove(block->m_instr, i, 1); + delete store; } - else if (inst->opcode == VINSTR_COND) + else if (inst->m_opcode == VINSTR_COND) { /* COND on a value resulting from a NOT could * remove the NOT and swap its operands @@ -666,17 +516,17 @@ static bool ir_function_pass_peephole(ir_function *self) size_t inotid; ir_instr *inot; ir_value *value; - value = inst->_ops[0]; + value = inst->_m_ops[0]; - if (value->store != store_value || value->reads.size() != 1 || value->reads[0] != inst) + if (value->m_store != store_value || value->m_reads.size() != 1 || value->m_reads[0] != inst) break; - inot = value->writes[0]; - if (inot->_ops[0] != value || - inot->opcode < INSTR_NOT_F || - inot->opcode > INSTR_NOT_FNC || - inot->opcode == INSTR_NOT_V || /* can't do these */ - inot->opcode == INSTR_NOT_S) + inot = value->m_writes[0]; + if (inot->_m_ops[0] != value || + inot->m_opcode < INSTR_NOT_F || + inot->m_opcode > INSTR_NOT_FNC || + inot->m_opcode == INSTR_NOT_V || /* can't do these */ + inot->m_opcode == INSTR_NOT_S) { break; } @@ -684,23 +534,23 @@ static bool ir_function_pass_peephole(ir_function *self) /* count */ ++opts_optimizationcount[OPTIM_PEEPHOLE]; /* change operand */ - (void)!ir_instr_op(inst, 0, inot->_ops[1], false); + (void)!ir_instr_op(inst, 0, inot->_m_ops[1], false); /* remove NOT */ - tmp = inot->owner; - for (inotid = 0; inotid < vec_size(tmp->instr); ++inotid) { - if (tmp->instr[inotid] == inot) + tmp = inot->m_owner; + for (inotid = 0; inotid < vec_size(tmp->m_instr); ++inotid) { + if (tmp->m_instr[inotid] == inot) break; } - if (inotid >= vec_size(tmp->instr)) { - compile_error(inst->context, "sanity-check failed: failed to find instruction to optimize out"); + if (inotid >= vec_size(tmp->m_instr)) { + compile_error(inst->m_context, "sanity-check failed: failed to find instruction to optimize out"); return false; } - vec_remove(tmp->instr, inotid, 1); - ir_instr_delete(inot); + vec_remove(tmp->m_instr, inotid, 1); + delete inot; /* swap ontrue/onfalse */ - tmp = inst->bops[0]; - inst->bops[0] = inst->bops[1]; - inst->bops[1] = tmp; + tmp = inst->m_bops[0]; + inst->m_bops[0] = inst->m_bops[1]; + inst->m_bops[1] = tmp; } continue; } @@ -712,86 +562,87 @@ static bool ir_function_pass_peephole(ir_function *self) static bool ir_function_pass_tailrecursion(ir_function *self) { - size_t b, p; + size_t p; + + for (auto& bp : self->m_blocks) { + ir_block *block = bp.get(); - for (b = 0; b < vec_size(self->blocks); ++b) { ir_value *funcval; ir_instr *ret, *call, *store = nullptr; - ir_block *block = self->blocks[b]; - if (!block->final || vec_size(block->instr) < 2) + if (!block->m_final || vec_size(block->m_instr) < 2) continue; - ret = block->instr[vec_size(block->instr)-1]; - if (ret->opcode != INSTR_DONE && ret->opcode != INSTR_RETURN) + ret = block->m_instr[vec_size(block->m_instr)-1]; + if (ret->m_opcode != INSTR_DONE && ret->m_opcode != INSTR_RETURN) continue; - call = block->instr[vec_size(block->instr)-2]; - if (call->opcode >= INSTR_STORE_F && call->opcode <= INSTR_STORE_FNC) { + call = block->m_instr[vec_size(block->m_instr)-2]; + if (call->m_opcode >= INSTR_STORE_F && call->m_opcode <= INSTR_STORE_FNC) { /* account for the unoptimized * CALL * STORE %return, %tmp * RETURN %tmp * version */ - if (vec_size(block->instr) < 3) + if (vec_size(block->m_instr) < 3) continue; store = call; - call = block->instr[vec_size(block->instr)-3]; + call = block->m_instr[vec_size(block->m_instr)-3]; } - if (call->opcode < INSTR_CALL0 || call->opcode > INSTR_CALL8) + if (call->m_opcode < INSTR_CALL0 || call->m_opcode > INSTR_CALL8) continue; if (store) { /* optimize out the STORE */ - if (ret->_ops[0] && - ret->_ops[0] == store->_ops[0] && - store->_ops[1] == call->_ops[0]) + if (ret->_m_ops[0] && + ret->_m_ops[0] == store->_m_ops[0] && + store->_m_ops[1] == call->_m_ops[0]) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; - call->_ops[0] = store->_ops[0]; - vec_remove(block->instr, vec_size(block->instr) - 2, 1); - ir_instr_delete(store); + call->_m_ops[0] = store->_m_ops[0]; + vec_remove(block->m_instr, vec_size(block->m_instr) - 2, 1); + delete store; } else continue; } - if (!call->_ops[0]) + if (!call->_m_ops[0]) continue; - funcval = call->_ops[1]; + funcval = call->_m_ops[1]; if (!funcval) continue; - if (funcval->vtype != TYPE_FUNCTION || funcval->constval.vfunc != self) + if (funcval->m_vtype != TYPE_FUNCTION || funcval->m_constval.vfunc != self) continue; /* now we have a CALL and a RET, check if it's a tailcall */ - if (ret->_ops[0] && call->_ops[0] != ret->_ops[0]) + if (ret->_m_ops[0] && call->_m_ops[0] != ret->_m_ops[0]) continue; ++opts_optimizationcount[OPTIM_TAIL_RECURSION]; - vec_shrinkby(block->instr, 2); + vec_shrinkby(block->m_instr, 2); - block->final = false; /* open it back up */ + block->m_final = false; /* open it back up */ /* emite parameter-stores */ - for (p = 0; p < call->params.size(); ++p) { + for (p = 0; p < call->m_params.size(); ++p) { /* assert(call->params_count <= self->locals_count); */ - if (!ir_block_create_store(block, call->context, self->locals[p], call->params[p])) { - irerror(call->context, "failed to create tailcall store instruction for parameter %i", (int)p); + if (!ir_block_create_store(block, call->m_context, self->m_locals[p].get(), call->m_params[p])) { + irerror(call->m_context, "failed to create tailcall store instruction for parameter %i", (int)p); return false; } } - if (!ir_block_create_jump(block, call->context, self->blocks[0])) { - irerror(call->context, "failed to create tailcall jump"); + if (!ir_block_create_jump(block, call->m_context, self->m_blocks[0].get())) { + irerror(call->m_context, "failed to create tailcall jump"); return false; } - ir_instr_delete(call); - ir_instr_delete(ret); + delete call; + delete ret; } return true; @@ -799,44 +650,42 @@ static bool ir_function_pass_tailrecursion(ir_function *self) bool ir_function_finalize(ir_function *self) { - size_t i; - - if (self->builtin) + if (self->m_builtin) return true; if (OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { if (!ir_function_pass_peephole(self)) { - irerror(self->context, "generic optimization pass broke something in `%s`", self->name); + irerror(self->m_context, "generic optimization pass broke something in `%s`", self->m_name.c_str()); return false; } } if (OPTS_OPTIMIZATION(OPTIM_TAIL_RECURSION)) { if (!ir_function_pass_tailrecursion(self)) { - irerror(self->context, "tail-recursion optimization pass broke something in `%s`", self->name); + irerror(self->m_context, "tail-recursion optimization pass broke something in `%s`", self->m_name.c_str()); return false; } } if (!ir_function_naive_phi(self)) { - irerror(self->context, "internal error: ir_function_naive_phi failed"); + irerror(self->m_context, "internal error: ir_function_naive_phi failed"); return false; } - for (i = 0; i < vec_size(self->locals); ++i) { - ir_value *v = self->locals[i]; - if (v->vtype == TYPE_VECTOR || - (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR)) + for (auto& lp : self->m_locals) { + ir_value *v = lp.get(); + if (v->m_vtype == TYPE_VECTOR || + (v->m_vtype == TYPE_FIELD && v->m_outtype == TYPE_VECTOR)) { ir_value_vector_member(v, 0); ir_value_vector_member(v, 1); ir_value_vector_member(v, 2); } } - for (i = 0; i < vec_size(self->values); ++i) { - ir_value *v = self->values[i]; - if (v->vtype == TYPE_VECTOR || - (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR)) + for (auto& vp : self->m_values) { + ir_value *v = vp.get(); + if (v->m_vtype == TYPE_VECTOR || + (v->m_vtype == TYPE_FIELD && v->m_outtype == TYPE_VECTOR)) { ir_value_vector_member(v, 0); ir_value_vector_member(v, 1); @@ -853,21 +702,22 @@ bool ir_function_finalize(ir_function *self) return true; } -ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param) +ir_value* ir_function_create_local(ir_function *self, const std::string& name, qc_type vtype, bool param) { ir_value *ve; if (param && - vec_size(self->locals) && - self->locals[vec_size(self->locals)-1]->store != store_param) { - irerror(self->context, "cannot add parameters after adding locals"); + !self->m_locals.empty() && + self->m_locals.back()->m_store != store_param) + { + irerror(self->m_context, "cannot add parameters after adding locals"); return nullptr; } - ve = ir_value_var(name, (param ? store_param : store_local), vtype); + ve = new ir_value(std::string(name), (param ? store_param : store_local), vtype); if (param) - ve->locked = true; - vec_push(self->locals, ve); + ve->m_locked = true; + self->m_locals.emplace_back(ve); return ve; } @@ -875,138 +725,97 @@ ir_value* ir_function_create_local(ir_function *self, const char *name, int vtyp *IR Block */ -ir_block* ir_block_new(ir_function* owner, const char *name) +ir_block::ir_block(ir_function* owner, const std::string& name) +: m_owner(owner), + m_label(name) { - ir_block *self = new ir_block; - memset(self, 0, sizeof(*self)); - - self->label = nullptr; - if (name && !ir_block_set_label(self, name)) { - mem_d(self); - return nullptr; - } - self->owner = owner; - self->context.file = "<@no context>"; - self->context.line = 0; - self->final = false; - - self->instr = nullptr; - self->entries = nullptr; - self->exits = nullptr; - - self->eid = 0; - self->is_return = false; - self->generated = false; - - return self; + m_context.file = "<@no context>"; + m_context.line = 0; } -static void ir_block_delete_quick(ir_block* self) +ir_block::~ir_block() { - size_t i; - if (self->label) mem_d(self->label); - for (i = 0; i != vec_size(self->instr); ++i) - ir_instr_delete_quick(self->instr[i]); - vec_free(self->instr); - vec_free(self->entries); - vec_free(self->exits); - delete self; + for (size_t i = 0; i != vec_size(m_instr); ++i) + delete m_instr[i]; + vec_free(m_instr); + vec_free(m_entries); + vec_free(m_exits); } -void ir_block_delete(ir_block* self) +static void ir_block_delete_quick(ir_block* self) { size_t i; - if (self->label) mem_d(self->label); - for (i = 0; i != vec_size(self->instr); ++i) - ir_instr_delete(self->instr[i]); - vec_free(self->instr); - vec_free(self->entries); - vec_free(self->exits); + for (i = 0; i != vec_size(self->m_instr); ++i) + ir_instr_delete_quick(self->m_instr[i]); + vec_free(self->m_instr); delete self; } -bool ir_block_set_label(ir_block *self, const char *name) -{ - if (self->label) - mem_d((void*)self->label); - self->label = util_strdup(name); - return !!self->label; -} - /*********************************************************************** *IR Instructions */ -static ir_instr* ir_instr_new(lex_ctx_t ctx, ir_block* owner, int op) +ir_instr::ir_instr(lex_ctx_t ctx, ir_block* owner_, int op) +: m_opcode(op), + m_context(ctx), + m_owner(owner_) { - ir_instr *self = new ir_instr; - self->owner = owner; - self->context = ctx; - self->opcode = op; - self->_ops[0] = nullptr; - self->_ops[1] = nullptr; - self->_ops[2] = nullptr; - self->bops[0] = nullptr; - self->bops[1] = nullptr; - self->eid = 0; - self->likely = true; - return self; } -static void ir_instr_delete_quick(ir_instr *self) +ir_instr::~ir_instr() { - delete self; -} - -static void ir_instr_delete(ir_instr *self) -{ - /* The following calls can only delete from - * vectors, we still want to delete this instruction - * so ignore the return value. Since with the warn_unused_result attribute - * gcc doesn't care about an explicit: (void)foo(); to ignore the result, - * I have to improvise here and use if(foo()); - */ - for (auto &it : self->phi) { + // The following calls can only delete from + // vectors, we still want to delete this instruction + // so ignore the return value. Since with the warn_unused_result attribute + // gcc doesn't care about an explicit: (void)foo(); to ignore the result, + // I have to improvise here and use if(foo()); + for (auto &it : m_phi) { size_t idx; - if (vec_ir_instr_find(it.value->writes, self, &idx)) - it.value->writes.erase(it.value->writes.begin() + idx); - if (vec_ir_instr_find(it.value->reads, self, &idx)) - it.value->reads.erase(it.value->reads.begin() + idx); + if (vec_ir_instr_find(it.value->m_writes, this, &idx)) + it.value->m_writes.erase(it.value->m_writes.begin() + idx); + if (vec_ir_instr_find(it.value->m_reads, this, &idx)) + it.value->m_reads.erase(it.value->m_reads.begin() + idx); } - for (auto &it : self->params) { + for (auto &it : m_params) { size_t idx; - if (vec_ir_instr_find(it->writes, self, &idx)) - it->writes.erase(it->writes.begin() + idx); - if (vec_ir_instr_find(it->reads, self, &idx)) - it->reads.erase(it->reads.begin() + idx); - } - (void)!ir_instr_op(self, 0, nullptr, false); - (void)!ir_instr_op(self, 1, nullptr, false); - (void)!ir_instr_op(self, 2, nullptr, false); - mem_d(self); + if (vec_ir_instr_find(it->m_writes, this, &idx)) + it->m_writes.erase(it->m_writes.begin() + idx); + if (vec_ir_instr_find(it->m_reads, this, &idx)) + it->m_reads.erase(it->m_reads.begin() + idx); + } + (void)!ir_instr_op(this, 0, nullptr, false); + (void)!ir_instr_op(this, 1, nullptr, false); + (void)!ir_instr_op(this, 2, nullptr, false); +} + +static void ir_instr_delete_quick(ir_instr *self) +{ + self->m_phi.clear(); + self->m_params.clear(); + delete self; } static bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing) { - if (v && v->vtype == TYPE_NOEXPR) { - irerror(self->context, "tried to use a NOEXPR value"); + if (v && v->m_vtype == TYPE_NOEXPR) { + irerror(self->m_context, "tried to use a NOEXPR value"); return false; } - if (self->_ops[op]) { + if (self->_m_ops[op]) { size_t idx; - if (writing && vec_ir_instr_find(self->_ops[op]->writes, self, &idx)) - self->_ops[op]->writes.erase(self->_ops[op]->writes.begin() + idx); - else if (vec_ir_instr_find(self->_ops[op]->reads, self, &idx)) - self->_ops[op]->reads.erase(self->_ops[op]->reads.begin() + idx); + if (writing && vec_ir_instr_find(self->_m_ops[op]->m_writes, self, &idx)) + self->_m_ops[op]->m_writes.erase(self->_m_ops[op]->m_writes.begin() + idx); + else if (vec_ir_instr_find(self->_m_ops[op]->m_reads, self, &idx)) + self->_m_ops[op]->m_reads.erase(self->_m_ops[op]->m_reads.begin() + idx); } if (v) { if (writing) - v->writes.push_back(self); + v->m_writes.push_back(self); else - v->reads.push_back(self); + v->m_reads.push_back(self); } - self->_ops[op] = v; + self->_m_ops[op] = v; return true; } @@ -1016,239 +825,202 @@ static bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing) static void ir_value_code_setaddr(ir_value *self, int32_t gaddr) { - self->code.globaladdr = gaddr; - if (self->members[0]) self->members[0]->code.globaladdr = gaddr; - if (self->members[1]) self->members[1]->code.globaladdr = gaddr; - if (self->members[2]) self->members[2]->code.globaladdr = gaddr; + self->m_code.globaladdr = gaddr; + if (self->m_members[0]) self->m_members[0]->m_code.globaladdr = gaddr; + if (self->m_members[1]) self->m_members[1]->m_code.globaladdr = gaddr; + if (self->m_members[2]) self->m_members[2]->m_code.globaladdr = gaddr; } static int32_t ir_value_code_addr(const ir_value *self) { - if (self->store == store_return) - return OFS_RETURN + self->code.addroffset; - return self->code.globaladdr + self->code.addroffset; + if (self->m_store == store_return) + return OFS_RETURN + self->m_code.addroffset; + return self->m_code.globaladdr + self->m_code.addroffset; } -ir_value* ir_value_var(const char *name, int storetype, int vtype) +ir_value::ir_value(std::string&& name_, store_type store_, qc_type vtype_) +: m_name(move(name_)), + m_vtype(vtype_), + m_store(store_) { - ir_value *self; - self = (ir_value*)mem_a(sizeof(*self)); - new (self) ir_value(); - self->vtype = vtype; - self->fieldtype = TYPE_VOID; - self->outtype = TYPE_VOID; - self->store = storetype; - self->flags = 0; - - self->cvq = CV_NONE; - self->hasvalue = false; - self->context.file = "<@no context>"; - self->context.line = 0; - self->name = nullptr; - if (name && !ir_value_set_name(self, name)) { - irerror(self->context, "out of memory"); - mem_d(self); - return nullptr; - } - - memset(&self->constval, 0, sizeof(self->constval)); - memset(&self->code, 0, sizeof(self->code)); - - self->members[0] = nullptr; - self->members[1] = nullptr; - self->members[2] = nullptr; - self->memberof = nullptr; - - self->unique_life = false; - self->locked = false; - self->callparam = false; + m_fieldtype = TYPE_VOID; + m_outtype = TYPE_VOID; + m_flags = 0; + + m_cvq = CV_NONE; + m_hasvalue = false; + m_context.file = "<@no context>"; + m_context.line = 0; + + memset(&m_constval, 0, sizeof(m_constval)); + memset(&m_code, 0, sizeof(m_code)); + + m_members[0] = nullptr; + m_members[1] = nullptr; + m_members[2] = nullptr; + m_memberof = nullptr; + + m_unique_life = false; + m_locked = false; + m_callparam = false; +} - self->life = nullptr; - return self; +ir_value::~ir_value() +{ + size_t i; + if (m_hasvalue) { + if (m_vtype == TYPE_STRING) + mem_d((void*)m_constval.vstring); + } + if (!(m_flags & IR_FLAG_SPLIT_VECTOR)) { + for (i = 0; i < 3; ++i) { + if (m_members[i]) + delete m_members[i]; + } + } } + /* helper function */ static ir_value* ir_builder_imm_float(ir_builder *self, float value, bool add_to_list) { - ir_value *v = ir_value_var("#IMMEDIATE", store_global, TYPE_FLOAT); - v->flags |= IR_FLAG_ERASABLE; - v->hasvalue = true; - v->cvq = CV_CONST; - v->constval.vfloat = value; + ir_value *v = new ir_value("#IMMEDIATE", store_global, TYPE_FLOAT); + v->m_flags |= IR_FLAG_ERASABLE; + v->m_hasvalue = true; + v->m_cvq = CV_CONST; + v->m_constval.vfloat = value; - vec_push(self->globals, v); + self->m_globals.emplace_back(v); if (add_to_list) - vec_push(self->const_floats, v); + self->m_const_floats.emplace_back(v); return v; } ir_value* ir_value_vector_member(ir_value *self, unsigned int member) { - char *name; - size_t len; + std::string name; ir_value *m; if (member >= 3) return nullptr; - if (self->members[member]) - return self->members[member]; + if (self->m_members[member]) + return self->m_members[member]; - if (self->name) { - len = strlen(self->name); - name = (char*)mem_a(len + 3); - memcpy(name, self->name, len); - name[len+0] = '_'; - name[len+1] = 'x' + member; - name[len+2] = '\0'; + if (!self->m_name.empty()) { + char member_name[3] = { '_', char('x' + member), 0 }; + name = self->m_name + member_name; } - else - name = nullptr; - if (self->vtype == TYPE_VECTOR) + if (self->m_vtype == TYPE_VECTOR) { - m = ir_value_var(name, self->store, TYPE_FLOAT); - if (name) - mem_d(name); + m = new ir_value(move(name), self->m_store, TYPE_FLOAT); if (!m) return nullptr; - m->context = self->context; + m->m_context = self->m_context; - self->members[member] = m; - m->code.addroffset = member; + self->m_members[member] = m; + m->m_code.addroffset = member; } - else if (self->vtype == TYPE_FIELD) + else if (self->m_vtype == TYPE_FIELD) { - if (self->fieldtype != TYPE_VECTOR) + if (self->m_fieldtype != TYPE_VECTOR) return nullptr; - m = ir_value_var(name, self->store, TYPE_FIELD); - if (name) - mem_d(name); + m = new ir_value(move(name), self->m_store, TYPE_FIELD); if (!m) return nullptr; - m->fieldtype = TYPE_FLOAT; - m->context = self->context; + m->m_fieldtype = TYPE_FLOAT; + m->m_context = self->m_context; - self->members[member] = m; - m->code.addroffset = member; + self->m_members[member] = m; + m->m_code.addroffset = member; } else { - irerror(self->context, "invalid member access on %s", self->name); + irerror(self->m_context, "invalid member access on %s", self->m_name.c_str()); return nullptr; } - m->memberof = self; + m->m_memberof = self; return m; } static GMQCC_INLINE size_t ir_value_sizeof(const ir_value *self) { - if (self->vtype == TYPE_FIELD && self->fieldtype == TYPE_VECTOR) + if (self->m_vtype == TYPE_FIELD && self->m_fieldtype == TYPE_VECTOR) return type_sizeof_[TYPE_VECTOR]; - return type_sizeof_[self->vtype]; + return type_sizeof_[self->m_vtype]; } -static ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int vtype) +static ir_value* ir_value_out(ir_function *owner, const char *name, store_type storetype, qc_type vtype) { - ir_value *v = ir_value_var(name, storetype, vtype); + ir_value *v = new ir_value(name ? std::string(name) : std::string(), storetype, vtype); if (!v) return nullptr; ir_function_collect_value(owner, v); return v; } -void ir_value_delete(ir_value* self) -{ - size_t i; - if (self->name) - mem_d((void*)self->name); - if (self->hasvalue) - { - if (self->vtype == TYPE_STRING) - mem_d((void*)self->constval.vstring); - } - if (!(self->flags & IR_FLAG_SPLIT_VECTOR)) { - for (i = 0; i < 3; ++i) { - if (self->members[i]) - ir_value_delete(self->members[i]); - } - } - vec_free(self->life); - mem_d(self); -} - -bool ir_value_set_name(ir_value *self, const char *name) -{ - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; -} - bool ir_value_set_float(ir_value *self, float f) { - if (self->vtype != TYPE_FLOAT) + if (self->m_vtype != TYPE_FLOAT) return false; - self->constval.vfloat = f; - self->hasvalue = true; + self->m_constval.vfloat = f; + self->m_hasvalue = true; return true; } bool ir_value_set_func(ir_value *self, int f) { - if (self->vtype != TYPE_FUNCTION) + if (self->m_vtype != TYPE_FUNCTION) return false; - self->constval.vint = f; - self->hasvalue = true; + self->m_constval.vint = f; + self->m_hasvalue = true; return true; } bool ir_value_set_vector(ir_value *self, vec3_t v) { - if (self->vtype != TYPE_VECTOR) + if (self->m_vtype != TYPE_VECTOR) return false; - self->constval.vvec = v; - self->hasvalue = true; + self->m_constval.vvec = v; + self->m_hasvalue = true; return true; } bool ir_value_set_field(ir_value *self, ir_value *fld) { - if (self->vtype != TYPE_FIELD) + if (self->m_vtype != TYPE_FIELD) return false; - self->constval.vpointer = fld; - self->hasvalue = true; + self->m_constval.vpointer = fld; + self->m_hasvalue = true; return true; } bool ir_value_set_string(ir_value *self, const char *str) { - if (self->vtype != TYPE_STRING) + if (self->m_vtype != TYPE_STRING) return false; - self->constval.vstring = util_strdupe(str); - self->hasvalue = true; + self->m_constval.vstring = util_strdupe(str); + self->m_hasvalue = true; return true; } #if 0 bool ir_value_set_int(ir_value *self, int i) { - if (self->vtype != TYPE_INTEGER) + if (self->m_vtype != TYPE_INTEGER) return false; - self->constval.vint = i; - self->hasvalue = true; + self->m_constval.vint = i; + self->m_hasvalue = true; return true; } #endif bool ir_value_lives(ir_value *self, size_t at) { - size_t i; - for (i = 0; i < vec_size(self->life); ++i) - { - ir_life_entry_t *life = &self->life[i]; - if (life->start <= at && at <= life->end) + for (auto& l : self->m_life) { + if (l.start <= at && at <= l.end) return true; - if (life->start > at) /* since it's ordered */ + if (l.start > at) /* since it's ordered */ return false; } return false; @@ -1256,54 +1028,50 @@ bool ir_value_lives(ir_value *self, size_t at) static bool ir_value_life_insert(ir_value *self, size_t idx, ir_life_entry_t e) { - size_t k; - vec_push(self->life, e); - for (k = vec_size(self->life)-1; k > idx; --k) - self->life[k] = self->life[k-1]; - self->life[idx] = e; + self->m_life.insert(self->m_life.begin() + idx, e); return true; } static bool ir_value_life_merge(ir_value *self, size_t s) { size_t i; - const size_t vs = vec_size(self->life); - ir_life_entry_t *life = nullptr; + const size_t vs = self->m_life.size(); + ir_life_entry_t *life_found = nullptr; ir_life_entry_t *before = nullptr; ir_life_entry_t new_entry; /* Find the first range >= s */ for (i = 0; i < vs; ++i) { - before = life; - life = &self->life[i]; - if (life->start > s) + before = life_found; + life_found = &self->m_life[i]; + if (life_found->start > s) break; } /* nothing found? append */ if (i == vs) { ir_life_entry_t e; - if (life && life->end+1 == s) + if (life_found && life_found->end+1 == s) { /* previous life range can be merged in */ - life->end++; + life_found->end++; return true; } - if (life && life->end >= s) + if (life_found && life_found->end >= s) return false; e.start = e.end = s; - vec_push(self->life, e); + self->m_life.emplace_back(e); return true; } /* found */ if (before) { if (before->end + 1 == s && - life->start - 1 == s) + life_found->start - 1 == s) { /* merge */ - before->end = life->end; - vec_remove(self->life, i, 1); + before->end = life_found->end; + self->m_life.erase(self->m_life.begin()+i); return true; } if (before->end + 1 == s) @@ -1317,9 +1085,9 @@ static bool ir_value_life_merge(ir_value *self, size_t s) return false; } /* extend */ - if (life->start - 1 == s) + if (life_found->start - 1 == s) { - life->start--; + life_found->start--; return true; } /* insert a new entry */ @@ -1331,65 +1099,63 @@ static bool ir_value_life_merge_into(ir_value *self, const ir_value *other) { size_t i, myi; - if (!vec_size(other->life)) + if (other->m_life.empty()) return true; - if (!vec_size(self->life)) { - size_t count = vec_size(other->life); - ir_life_entry_t *life = vec_add(self->life, count); - memcpy(life, other->life, count * sizeof(*life)); + if (self->m_life.empty()) { + self->m_life = other->m_life; return true; } myi = 0; - for (i = 0; i < vec_size(other->life); ++i) + for (i = 0; i < other->m_life.size(); ++i) { - const ir_life_entry_t *life = &other->life[i]; + const ir_life_entry_t &otherlife = other->m_life[i]; while (true) { - ir_life_entry_t *entry = &self->life[myi]; + ir_life_entry_t *entry = &self->m_life[myi]; - if (life->end+1 < entry->start) + if (otherlife.end+1 < entry->start) { /* adding an interval before entry */ - if (!ir_value_life_insert(self, myi, *life)) + if (!ir_value_life_insert(self, myi, otherlife)) return false; ++myi; break; } - if (life->start < entry->start && - life->end+1 >= entry->start) + if (otherlife.start < entry->start && + otherlife.end+1 >= entry->start) { /* starts earlier and overlaps */ - entry->start = life->start; + entry->start = otherlife.start; } - if (life->end > entry->end && - life->start <= entry->end+1) + if (otherlife.end > entry->end && + otherlife.start <= entry->end+1) { /* ends later and overlaps */ - entry->end = life->end; + entry->end = otherlife.end; } /* see if our change combines it with the next ranges */ - while (myi+1 < vec_size(self->life) && - entry->end+1 >= self->life[1+myi].start) + while (myi+1 < self->m_life.size() && + entry->end+1 >= self->m_life[1+myi].start) { /* overlaps with (myi+1) */ - if (entry->end < self->life[1+myi].end) - entry->end = self->life[1+myi].end; - vec_remove(self->life, myi+1, 1); - entry = &self->life[myi]; + if (entry->end < self->m_life[1+myi].end) + entry->end = self->m_life[1+myi].end; + self->m_life.erase(self->m_life.begin() + (myi + 1)); + entry = &self->m_life[myi]; } /* see if we're after the entry */ - if (life->start > entry->end) + if (otherlife.start > entry->end) { ++myi; /* append if we're at the end */ - if (myi >= vec_size(self->life)) { - vec_push(self->life, *life); + if (myi >= self->m_life.size()) { + self->m_life.emplace_back(otherlife); break; } /* otherweise check the next range */ @@ -1410,16 +1176,16 @@ static bool ir_values_overlap(const ir_value *a, const ir_value *b) * statement above. */ - ir_life_entry_t *la, *lb, *enda, *endb; + const ir_life_entry_t *la, *lb, *enda, *endb; /* first of all, if either has no life range, they cannot clash */ - if (!vec_size(a->life) || !vec_size(b->life)) + if (a->m_life.empty() || b->m_life.empty()) return false; - la = a->life; - lb = b->life; - enda = la + vec_size(a->life); - endb = lb + vec_size(b->life); + la = &a->m_life.front(); + lb = &b->m_life.front(); + enda = &a->m_life.back() + 1; + endb = &b->m_life.back() + 1; while (true) { /* check if the entries overlap, for that, @@ -1462,9 +1228,9 @@ static bool ir_values_overlap(const ir_value *a, const ir_value *b) static bool ir_check_unreachable(ir_block *self) { /* The IR should never have to deal with unreachable code */ - if (!self->final/* || OPTS_FLAG(ALLOW_UNREACHABLE_CODE)*/) + if (!self->m_final/* || OPTS_FLAG(ALLOW_UNREACHABLE_CODE)*/) return true; - irerror(self->context, "unreachable statement (%s)", self->label); + irerror(self->m_context, "unreachable statement (%s)", self->m_label.c_str()); return false; } @@ -1474,26 +1240,26 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx_t ctx, int op, ir_value *t if (!ir_check_unreachable(self)) return false; - if (target->store == store_value && + if (target->m_store == store_value && (op < INSTR_STOREP_F || op > INSTR_STOREP_FNC)) { - irerror(self->context, "cannot store to an SSA value"); - irerror(self->context, "trying to store: %s <- %s", target->name, what->name); - irerror(self->context, "instruction: %s", util_instr_str[op]); + irerror(self->m_context, "cannot store to an SSA value"); + irerror(self->m_context, "trying to store: %s <- %s", target->m_name.c_str(), what->m_name.c_str()); + irerror(self->m_context, "instruction: %s", util_instr_str[op]); return false; } - in = ir_instr_new(ctx, self, op); + in = new ir_instr(ctx, self, op); if (!in) return false; if (!ir_instr_op(in, 0, target, (op < INSTR_STOREP_F || op > INSTR_STOREP_FNC)) || !ir_instr_op(in, 1, what, false)) { - ir_instr_delete(in); + delete in; return false; } - vec_push(self->instr, in); + vec_push(self->m_instr, in); return true; } @@ -1503,39 +1269,39 @@ bool ir_block_create_state_op(ir_block *self, lex_ctx_t ctx, ir_value *frame, ir if (!ir_check_unreachable(self)) return false; - in = ir_instr_new(ctx, self, INSTR_STATE); + in = new ir_instr(ctx, self, INSTR_STATE); if (!in) return false; if (!ir_instr_op(in, 0, frame, false) || !ir_instr_op(in, 1, think, false)) { - ir_instr_delete(in); + delete in; return false; } - vec_push(self->instr, in); + vec_push(self->m_instr, in); return true; } static bool ir_block_create_store(ir_block *self, lex_ctx_t ctx, ir_value *target, ir_value *what) { int op = 0; - int vtype; - if (target->vtype == TYPE_VARIANT) - vtype = what->vtype; + qc_type vtype; + if (target->m_vtype == TYPE_VARIANT) + vtype = what->m_vtype; else - vtype = target->vtype; + vtype = target->m_vtype; #if 0 - if (vtype == TYPE_FLOAT && what->vtype == TYPE_INTEGER) + if (vtype == TYPE_FLOAT && what->m_vtype == TYPE_INTEGER) op = INSTR_CONV_ITOF; - else if (vtype == TYPE_INTEGER && what->vtype == TYPE_FLOAT) + else if (vtype == TYPE_INTEGER && what->m_vtype == TYPE_FLOAT) op = INSTR_CONV_FTOI; #endif op = type_store_instr[vtype]; if (OPTS_FLAG(ADJUST_VECTOR_FIELDS)) { - if (op == INSTR_STORE_FLD && what->fieldtype == TYPE_VECTOR) + if (op == INSTR_STORE_FLD && what->m_fieldtype == TYPE_VECTOR) op = INSTR_STORE_V; } @@ -1545,19 +1311,19 @@ static bool ir_block_create_store(ir_block *self, lex_ctx_t ctx, ir_value *targe bool ir_block_create_storep(ir_block *self, lex_ctx_t ctx, ir_value *target, ir_value *what) { int op = 0; - int vtype; + qc_type vtype; - if (target->vtype != TYPE_POINTER) + if (target->m_vtype != TYPE_POINTER) return false; /* storing using pointer - target is a pointer, type must be * inferred from source */ - vtype = what->vtype; + vtype = what->m_vtype; op = type_storep_instr[vtype]; if (OPTS_FLAG(ADJUST_VECTOR_FIELDS)) { - if (op == INSTR_STOREP_FLD && what->fieldtype == TYPE_VECTOR) + if (op == INSTR_STOREP_FLD && what->m_fieldtype == TYPE_VECTOR) op = INSTR_STOREP_V; } @@ -1570,19 +1336,19 @@ bool ir_block_create_return(ir_block *self, lex_ctx_t ctx, ir_value *v) if (!ir_check_unreachable(self)) return false; - self->final = true; + self->m_final = true; - self->is_return = true; - in = ir_instr_new(ctx, self, INSTR_RETURN); + self->m_is_return = true; + in = new ir_instr(ctx, self, INSTR_RETURN); if (!in) return false; if (v && !ir_instr_op(in, 0, v, false)) { - ir_instr_delete(in); + delete in; return false; } - vec_push(self->instr, in); + vec_push(self->m_instr, in); return true; } @@ -1592,26 +1358,26 @@ bool ir_block_create_if(ir_block *self, lex_ctx_t ctx, ir_value *v, ir_instr *in; if (!ir_check_unreachable(self)) return false; - self->final = true; - /*in = ir_instr_new(ctx, self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/ - in = ir_instr_new(ctx, self, VINSTR_COND); + self->m_final = true; + /*in = new ir_instr(ctx, self, (v->m_vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/ + in = new ir_instr(ctx, self, VINSTR_COND); if (!in) return false; if (!ir_instr_op(in, 0, v, false)) { - ir_instr_delete(in); + delete in; return false; } - in->bops[0] = ontrue; - in->bops[1] = onfalse; + in->m_bops[0] = ontrue; + in->m_bops[1] = onfalse; - vec_push(self->instr, in); + vec_push(self->m_instr, in); - vec_push(self->exits, ontrue); - vec_push(self->exits, onfalse); - vec_push(ontrue->entries, self); - vec_push(onfalse->entries, self); + vec_push(self->m_exits, ontrue); + vec_push(self->m_exits, onfalse); + vec_push(ontrue->m_entries, self); + vec_push(onfalse->m_entries, self); return true; } @@ -1620,69 +1386,67 @@ bool ir_block_create_jump(ir_block *self, lex_ctx_t ctx, ir_block *to) ir_instr *in; if (!ir_check_unreachable(self)) return false; - self->final = true; - in = ir_instr_new(ctx, self, VINSTR_JUMP); + self->m_final = true; + in = new ir_instr(ctx, self, VINSTR_JUMP); if (!in) return false; - in->bops[0] = to; - vec_push(self->instr, in); + in->m_bops[0] = to; + vec_push(self->m_instr, in); - vec_push(self->exits, to); - vec_push(to->entries, self); + vec_push(self->m_exits, to); + vec_push(to->m_entries, self); return true; } bool ir_block_create_goto(ir_block *self, lex_ctx_t ctx, ir_block *to) { - self->owner->flags |= IR_FLAG_HAS_GOTO; + self->m_owner->m_flags |= IR_FLAG_HAS_GOTO; return ir_block_create_jump(self, ctx, to); } -ir_instr* ir_block_create_phi(ir_block *self, lex_ctx_t ctx, const char *label, int ot) +ir_instr* ir_block_create_phi(ir_block *self, lex_ctx_t ctx, const char *label, qc_type ot) { ir_value *out; ir_instr *in; if (!ir_check_unreachable(self)) return nullptr; - in = ir_instr_new(ctx, self, VINSTR_PHI); + in = new ir_instr(ctx, self, VINSTR_PHI); if (!in) return nullptr; - out = ir_value_out(self->owner, label, store_value, ot); + out = ir_value_out(self->m_owner, label, store_value, ot); if (!out) { - ir_instr_delete(in); + delete in; return nullptr; } if (!ir_instr_op(in, 0, out, true)) { - ir_instr_delete(in); - ir_value_delete(out); + delete in; return nullptr; } - vec_push(self->instr, in); + vec_push(self->m_instr, in); return in; } ir_value* ir_phi_value(ir_instr *self) { - return self->_ops[0]; + return self->_m_ops[0]; } void ir_phi_add(ir_instr* self, ir_block *b, ir_value *v) { ir_phi_entry_t pe; - if (!vec_ir_block_find(self->owner->entries, b, nullptr)) { - /* Must not be possible to cause this, otherwise the AST - * is doing something wrong. - */ - irerror(self->context, "Invalid entry block for PHI"); + if (!vec_ir_block_find(self->m_owner->m_entries, b, nullptr)) { + // Must not be possible to cause this, otherwise the AST + // is doing something wrong. + irerror(self->m_context, "Invalid entry block for PHI"); exit(EXIT_FAILURE); } pe.value = v; pe.from = b; - v->reads.push_back(self); - self->phi.push_back(pe); + v->m_reads.push_back(self); + self->m_phi.push_back(pe); } /* call related code */ @@ -1692,31 +1456,30 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, ir_instr *in; if (!ir_check_unreachable(self)) return nullptr; - in = ir_instr_new(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0)); + in = new ir_instr(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0)); if (!in) return nullptr; if (noreturn) { - self->final = true; - self->is_return = true; + self->m_final = true; + self->m_is_return = true; } - out = ir_value_out(self->owner, label, (func->outtype == TYPE_VOID) ? store_return : store_value, func->outtype); + out = ir_value_out(self->m_owner, label, (func->m_outtype == TYPE_VOID) ? store_return : store_value, func->m_outtype); if (!out) { - ir_instr_delete(in); + delete in; return nullptr; } if (!ir_instr_op(in, 0, out, true) || !ir_instr_op(in, 1, func, false)) { - ir_instr_delete(in); - ir_value_delete(out); + delete in; return nullptr; } - vec_push(self->instr, in); + vec_push(self->m_instr, in); /* if (noreturn) { if (!ir_block_create_return(self, ctx, nullptr)) { compile_error(ctx, "internal error: failed to generate dummy-return instruction"); - ir_instr_delete(in); + delete in; return nullptr; } } @@ -1726,13 +1489,13 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, ir_value* ir_call_value(ir_instr *self) { - return self->_ops[0]; + return self->_m_ops[0]; } void ir_call_param(ir_instr* self, ir_value *v) { - self->params.push_back(v); - v->reads.push_back(self); + self->m_params.push_back(v); + v->m_reads.push_back(self); } /* binary op related code */ @@ -1741,7 +1504,7 @@ ir_value* ir_block_create_binop(ir_block *self, lex_ctx_t ctx, const char *label, int opcode, ir_value *left, ir_value *right) { - int ot = TYPE_VOID; + qc_type ot = TYPE_VOID; switch (opcode) { case INSTR_ADD_F: case INSTR_SUB_F: @@ -1860,7 +1623,7 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, const char *label, int opcode, ir_value *operand) { - int ot = TYPE_FLOAT; + qc_type ot = TYPE_FLOAT; switch (opcode) { case INSTR_NOT_F: case INSTR_NOT_V: @@ -1881,7 +1644,7 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, nullptr, operand, TYPE_VECTOR); default: - ot = operand->vtype; + ot = operand->m_vtype; break; }; if (ot == TYPE_VOID) { @@ -1894,18 +1657,17 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, } static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t ctx, const char *label, - int op, ir_value *a, ir_value *b, int outype) + int op, ir_value *a, ir_value *b, qc_type outype) { ir_instr *instr; ir_value *out; - out = ir_value_out(self->owner, label, store_value, outype); + out = ir_value_out(self->m_owner, label, store_value, outype); if (!out) return nullptr; - instr = ir_instr_new(ctx, self, op); + instr = new ir_instr(ctx, self, op); if (!instr) { - ir_value_delete(out); return nullptr; } @@ -1916,12 +1678,11 @@ static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t ctx, co goto on_error; } - vec_push(self->instr, instr); + vec_push(self->m_instr, instr); return out; on_error: - ir_instr_delete(instr); - ir_value_delete(out); + delete instr; return nullptr; } @@ -1930,25 +1691,25 @@ ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx_t ctx, const char ir_value *v; /* Support for various pointer types todo if so desired */ - if (ent->vtype != TYPE_ENTITY) + if (ent->m_vtype != TYPE_ENTITY) return nullptr; - if (field->vtype != TYPE_FIELD) + if (field->m_vtype != TYPE_FIELD) return nullptr; v = ir_block_create_general_instr(self, ctx, label, INSTR_ADDRESS, ent, field, TYPE_POINTER); - v->fieldtype = field->fieldtype; + v->m_fieldtype = field->m_fieldtype; return v; } -ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *ent, ir_value *field, int outype) +ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *ent, ir_value *field, qc_type outype) { int op; - if (ent->vtype != TYPE_ENTITY) + if (ent->m_vtype != TYPE_ENTITY) return nullptr; /* at some point we could redirect for TYPE_POINTER... but that could lead to carelessness */ - if (field->vtype != TYPE_FIELD) + if (field->m_vtype != TYPE_FIELD) return nullptr; switch (outype) @@ -1964,7 +1725,7 @@ ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const cha 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]); + irerror(self->m_context, "invalid type for ir_block_create_load_from_ent: %s", type_name[outype]); return nullptr; } @@ -1978,13 +1739,9 @@ ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const cha static bool ir_block_naive_phi(ir_block *self); bool ir_function_naive_phi(ir_function *self) { - size_t i; - - for (i = 0; i < vec_size(self->blocks); ++i) - { - if (!ir_block_naive_phi(self->blocks[i])) + for (auto& b : self->m_blocks) + if (!ir_block_naive_phi(b.get())) return false; - } return true; } @@ -1995,36 +1752,36 @@ static bool ir_block_naive_phi(ir_block *self) * to a list so we don't need to loop through blocks * - anyway: "don't optimize YET" */ - for (i = 0; i < vec_size(self->instr); ++i) + for (i = 0; i < vec_size(self->m_instr); ++i) { - ir_instr *instr = self->instr[i]; - if (instr->opcode != VINSTR_PHI) + ir_instr *instr = self->m_instr[i]; + if (instr->m_opcode != VINSTR_PHI) continue; - vec_remove(self->instr, i, 1); + vec_remove(self->m_instr, i, 1); --i; /* NOTE: i+1 below */ - for (auto &it : instr->phi) { + for (auto &it : instr->m_phi) { ir_value *v = it.value; ir_block *b = it.from; - if (v->store == store_value && v->reads.size() == 1 && v->writes.size() == 1) { + if (v->m_store == store_value && v->m_reads.size() == 1 && v->m_writes.size() == 1) { /* replace the value */ - if (!ir_instr_op(v->writes[0], 0, instr->_ops[0], true)) + if (!ir_instr_op(v->m_writes[0], 0, instr->_m_ops[0], true)) return false; } else { /* force a move instruction */ - ir_instr *prevjump = vec_last(b->instr); - vec_pop(b->instr); - b->final = false; - instr->_ops[0]->store = store_global; - if (!ir_block_create_store(b, instr->context, instr->_ops[0], v)) + ir_instr *prevjump = vec_last(b->m_instr); + vec_pop(b->m_instr); + b->m_final = false; + instr->_m_ops[0]->m_store = store_global; + if (!ir_block_create_store(b, instr->m_context, instr->_m_ops[0], v)) return false; - instr->_ops[0]->store = store_value; - vec_push(b->instr, prevjump); - b->final = true; + instr->_m_ops[0]->m_store = store_value; + vec_push(b->m_instr, prevjump); + b->m_final = true; } } - ir_instr_delete(instr); + delete instr; } return true; } @@ -2044,9 +1801,9 @@ static void ir_block_enumerate(ir_block *self, size_t *_eid) { size_t i; size_t eid = *_eid; - for (i = 0; i < vec_size(self->instr); ++i) + for (i = 0; i < vec_size(self->m_instr); ++i) { - self->instr[i]->eid = eid++; + self->m_instr[i]->m_eid = eid++; } *_eid = eid; } @@ -2058,18 +1815,19 @@ static void ir_block_enumerate(ir_block *self, size_t *_eid) */ void ir_function_enumerate(ir_function *self) { - size_t i; size_t instruction_id = 0; - for (i = 0; i < vec_size(self->blocks); ++i) + size_t block_eid = 0; + for (auto& block : self->m_blocks) { /* each block now gets an additional "entry" instruction id * we can use to avoid point-life issues */ - self->blocks[i]->entry_id = instruction_id; + block->m_entry_id = instruction_id; + block->m_eid = block_eid; ++instruction_id; + ++block_eid; - self->blocks[i]->eid = i; - ir_block_enumerate(self->blocks[i], &instruction_id); + ir_block_enumerate(block.get(), &instruction_id); } } @@ -2090,9 +1848,9 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) ir_value *slot; size_t vsize = ir_value_sizeof(var); - var->code.local = vec_size(alloc->locals); + var->m_code.local = vec_size(alloc->locals); - slot = ir_value_var("reg", store_global, var->vtype); + slot = new ir_value("reg", store_global, var->m_vtype); if (!slot) return false; @@ -2101,12 +1859,12 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) vec_push(alloc->locals, slot); vec_push(alloc->sizes, vsize); - vec_push(alloc->unique, var->unique_life); + vec_push(alloc->unique, var->m_unique_life); return true; localerror: - ir_value_delete(slot); + delete slot; return false; } @@ -2115,7 +1873,7 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * size_t a; ir_value *slot; - if (v->unique_life) + if (v->m_unique_life) return function_allocator_alloc(alloc, v); for (a = 0; a < vec_size(alloc->locals); ++a) @@ -2129,7 +1887,7 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * /* never resize parameters * will be required later when overlapping temps + locals */ - if (a < vec_size(self->params) && + if (a < vec_size(self->m_params) && alloc->sizes[a] < ir_value_sizeof(v)) { continue; @@ -2145,7 +1903,7 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * if (alloc->sizes[a] < ir_value_sizeof(v)) alloc->sizes[a] = ir_value_sizeof(v); - v->code.local = a; + v->m_code.local = a; return true; } if (a >= vec_size(alloc->locals)) { @@ -2157,16 +1915,13 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * bool ir_function_allocate_locals(ir_function *self) { - size_t i; bool retval = true; size_t pos; bool opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS); - ir_value *v; - function_allocator lockalloc, globalloc; - if (!vec_size(self->locals) && !vec_size(self->values)) + if (self->m_locals.empty() && self->m_values.empty()) return true; globalloc.locals = nullptr; @@ -2178,86 +1933,87 @@ bool ir_function_allocate_locals(ir_function *self) lockalloc.positions = nullptr; lockalloc.unique = nullptr; - for (i = 0; i < vec_size(self->locals); ++i) + size_t i; + for (i = 0; i < self->m_locals.size(); ++i) { - v = self->locals[i]; - if ((self->flags & IR_FLAG_MASK_NO_LOCAL_TEMPS) || !OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) { - v->locked = true; - v->unique_life = true; + ir_value *v = self->m_locals[i].get(); + if ((self->m_flags & IR_FLAG_MASK_NO_LOCAL_TEMPS) || !OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) { + v->m_locked = true; + v->m_unique_life = true; } - else if (i >= vec_size(self->params)) + else if (i >= vec_size(self->m_params)) break; else - v->locked = true; /* lock parameters locals */ - if (!function_allocator_alloc((v->locked || !opt_gt ? &lockalloc : &globalloc), v)) + v->m_locked = true; /* lock parameters locals */ + if (!function_allocator_alloc((v->m_locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } - for (; i < vec_size(self->locals); ++i) + for (; i < self->m_locals.size(); ++i) { - v = self->locals[i]; - if (!vec_size(v->life)) + ir_value *v = self->m_locals[i].get(); + if (v->m_life.empty()) continue; - if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v)) + if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } /* Allocate a slot for any value that still exists */ - for (i = 0; i < vec_size(self->values); ++i) + for (i = 0; i < self->m_values.size(); ++i) { - v = self->values[i]; + ir_value *v = self->m_values[i].get(); - if (!vec_size(v->life)) + if (v->m_life.empty()) continue; /* CALL optimization: * If the value is a parameter-temp: 1 write, 1 read from a CALL * and it's not "locked", write it to the OFS_PARM directly. */ - if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->locked && !v->unique_life) { - if (v->reads.size() == 1 && v->writes.size() == 1 && - (v->reads[0]->opcode == VINSTR_NRCALL || - (v->reads[0]->opcode >= INSTR_CALL0 && v->reads[0]->opcode <= INSTR_CALL8) + if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->m_locked && !v->m_unique_life) { + if (v->m_reads.size() == 1 && v->m_writes.size() == 1 && + (v->m_reads[0]->m_opcode == VINSTR_NRCALL || + (v->m_reads[0]->m_opcode >= INSTR_CALL0 && v->m_reads[0]->m_opcode <= INSTR_CALL8) ) ) { size_t param; - ir_instr *call = v->reads[0]; - if (!vec_ir_value_find(call->params, v, ¶m)) { - irerror(call->context, "internal error: unlocked parameter %s not found", v->name); + ir_instr *call = v->m_reads[0]; + if (!vec_ir_value_find(call->m_params, v, ¶m)) { + irerror(call->m_context, "internal error: unlocked parameter %s not found", v->m_name.c_str()); goto error; } ++opts_optimizationcount[OPTIM_CALL_STORES]; - v->callparam = true; + v->m_callparam = true; if (param < 8) ir_value_code_setaddr(v, OFS_PARM0 + 3*param); else { - size_t nprotos = vec_size(self->owner->extparam_protos); + size_t nprotos = self->m_owner->m_extparam_protos.size(); ir_value *ep; param -= 8; if (nprotos > param) - ep = self->owner->extparam_protos[param]; + ep = self->m_owner->m_extparam_protos[param].get(); else { - ep = ir_gen_extparam_proto(self->owner); + ep = ir_gen_extparam_proto(self->m_owner); while (++nprotos <= param) - ep = ir_gen_extparam_proto(self->owner); + ep = ir_gen_extparam_proto(self->m_owner); } - ir_instr_op(v->writes[0], 0, ep, true); - call->params[param+8] = ep; + ir_instr_op(v->m_writes[0], 0, ep, true); + call->m_params[param+8] = ep; } continue; } - if (v->writes.size() == 1 && v->writes[0]->opcode == INSTR_CALL0) { - v->store = store_return; - if (v->members[0]) v->members[0]->store = store_return; - if (v->members[1]) v->members[1]->store = store_return; - if (v->members[2]) v->members[2]->store = store_return; + if (v->m_writes.size() == 1 && v->m_writes[0]->m_opcode == INSTR_CALL0) { + v->m_store = store_return; + if (v->m_members[0]) v->m_members[0]->m_store = store_return; + if (v->m_members[1]) v->m_members[1]->m_store = store_return; + if (v->m_members[2]) v->m_members[2]->m_store = store_return; ++opts_optimizationcount[OPTIM_CALL_STORES]; continue; } } - if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v)) + if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } @@ -2275,7 +2031,7 @@ bool ir_function_allocate_locals(ir_function *self) pos = lockalloc.positions[i-1] + lockalloc.sizes[i-1]; vec_push(lockalloc.positions, pos); } - self->allocated_locals = pos + vec_last(lockalloc.sizes); + self->m_allocated_locals = pos + vec_last(lockalloc.sizes); } if (globalloc.sizes) { pos = (vec_size(globalloc.sizes) ? globalloc.positions[0] : 0); @@ -2284,24 +2040,22 @@ bool ir_function_allocate_locals(ir_function *self) pos = globalloc.positions[i-1] + globalloc.sizes[i-1]; vec_push(globalloc.positions, pos); } - self->globaltemps = pos + vec_last(globalloc.sizes); + self->m_globaltemps = pos + vec_last(globalloc.sizes); } /* Locals need to know their new position */ - for (i = 0; i < vec_size(self->locals); ++i) { - v = self->locals[i]; - if (v->locked || !opt_gt) - v->code.local = lockalloc.positions[v->code.local]; + for (auto& local : self->m_locals) { + if (local->m_locked || !opt_gt) + local->m_code.local = lockalloc.positions[local->m_code.local]; else - v->code.local = globalloc.positions[v->code.local]; + local->m_code.local = globalloc.positions[local->m_code.local]; } /* Take over the actual slot positions on values */ - for (i = 0; i < vec_size(self->values); ++i) { - v = self->values[i]; - if (v->locked || !opt_gt) - v->code.local = lockalloc.positions[v->code.local]; + for (auto& value : self->m_values) { + if (value->m_locked || !opt_gt) + value->m_code.local = lockalloc.positions[value->m_code.local]; else - v->code.local = globalloc.positions[v->code.local]; + value->m_code.local = globalloc.positions[value->m_code.local]; } goto cleanup; @@ -2310,9 +2064,9 @@ error: retval = false; cleanup: for (i = 0; i < vec_size(lockalloc.locals); ++i) - ir_value_delete(lockalloc.locals[i]); + delete lockalloc.locals[i]; for (i = 0; i < vec_size(globalloc.locals); ++i) - ir_value_delete(globalloc.locals[i]); + delete globalloc.locals[i]; vec_free(globalloc.unique); vec_free(globalloc.locals); vec_free(globalloc.sizes); @@ -2365,7 +2119,7 @@ static void ir_op_read_write(int op, size_t *read, size_t *write) static bool ir_block_living_add_instr(ir_block *self, size_t eid) { bool changed = false; - for (auto &it : self->living) + for (auto &it : self->m_living) if (ir_value_life_merge(it, eid)) changed = true; return changed; @@ -2373,10 +2127,10 @@ static bool ir_block_living_add_instr(ir_block *self, size_t eid) { static bool ir_block_living_lock(ir_block *self) { bool changed = false; - for (auto &it : self->living) { - if (it->locked) + for (auto &it : self->m_living) { + if (it->m_locked) continue; - it->locked = true; + it->m_locked = true; changed = true; } return changed; @@ -2387,47 +2141,43 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) ir_instr *instr; ir_value *value; size_t i, o, p, mem; - /* bitmasks which operands are read from or written to */ + // bitmasks which operands are read from or written to size_t read, write; - char dbg_ind[16]; - dbg_ind[0] = '#'; - dbg_ind[1] = '0'; - (void)dbg_ind; - self->living.clear(); + self->m_living.clear(); - p = vec_size(self->exits); + p = vec_size(self->m_exits); for (i = 0; i < p; ++i) { - ir_block *prev = self->exits[i]; - for (auto &it : prev->living) - if (!vec_ir_value_find(self->living, it, nullptr)) - self->living.push_back(it); + ir_block *prev = self->m_exits[i]; + for (auto &it : prev->m_living) + if (!vec_ir_value_find(self->m_living, it, nullptr)) + self->m_living.push_back(it); } - i = vec_size(self->instr); + i = vec_size(self->m_instr); while (i) { --i; - instr = self->instr[i]; + instr = self->m_instr[i]; /* See which operands are read and write operands */ - ir_op_read_write(instr->opcode, &read, &write); + ir_op_read_write(instr->m_opcode, &read, &write); /* Go through the 3 main operands * writes first, then reads */ for (o = 0; o < 3; ++o) { - if (!instr->_ops[o]) /* no such operand */ + if (!instr->_m_ops[o]) /* no such operand */ continue; - value = instr->_ops[o]; + value = instr->_m_ops[o]; /* We only care about locals */ /* we also calculate parameter liferanges so that locals * can take up parameter slots */ - if (value->store != store_value && - value->store != store_local && - value->store != store_param) + if (value->m_store != store_value && + value->m_store != store_local && + value->m_store != store_param) continue; /* write operands */ @@ -2438,7 +2188,7 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) if (write & (1<living, value, &idx); + bool in_living = vec_ir_value_find(self->m_living, value, &idx); if (!in_living) { /* If the value isn't alive it hasn't been read before... */ @@ -2448,38 +2198,38 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) * and make sure it's only printed once * since this function is run multiple times. */ - /* con_err( "Value only written %s\n", value->name); */ - if (ir_value_life_merge(value, instr->eid)) + /* con_err( "Value only written %s\n", value->m_name); */ + if (ir_value_life_merge(value, instr->m_eid)) *changed = true; } else { /* since 'living' won't contain it * anymore, merge the value, since * (A) doesn't. */ - if (ir_value_life_merge(value, instr->eid)) + if (ir_value_life_merge(value, instr->m_eid)) *changed = true; // Then remove - self->living.erase(self->living.begin() + idx); + self->m_living.erase(self->m_living.begin() + idx); } /* Removing a vector removes all members */ for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], &idx)) { - if (ir_value_life_merge(value->members[mem], instr->eid)) + if (value->m_members[mem] && vec_ir_value_find(self->m_living, value->m_members[mem], &idx)) { + if (ir_value_life_merge(value->m_members[mem], instr->m_eid)) *changed = true; - self->living.erase(self->living.begin() + idx); + self->m_living.erase(self->m_living.begin() + idx); } } /* Removing the last member removes the vector */ - if (value->memberof) { - value = value->memberof; + if (value->m_memberof) { + value = value->m_memberof; for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], nullptr)) + if (value->m_members[mem] && vec_ir_value_find(self->m_living, value->m_members[mem], nullptr)) break; } - if (mem == 3 && vec_ir_value_find(self->living, value, &idx)) { - if (ir_value_life_merge(value, instr->eid)) + if (mem == 3 && vec_ir_value_find(self->m_living, value, &idx)) { + if (ir_value_life_merge(value, instr->m_eid)) *changed = true; - self->living.erase(self->living.begin() + idx); + self->m_living.erase(self->m_living.begin() + idx); } } } @@ -2488,105 +2238,105 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) /* These operations need a special case as they can break when using * same source and destination operand otherwise, as the engine may * read the source multiple times. */ - if (instr->opcode == INSTR_MUL_VF || - instr->opcode == VINSTR_BITAND_VF || - instr->opcode == VINSTR_BITOR_VF || - instr->opcode == VINSTR_BITXOR || - instr->opcode == VINSTR_BITXOR_VF || - instr->opcode == VINSTR_BITXOR_V || - instr->opcode == VINSTR_CROSS) + if (instr->m_opcode == INSTR_MUL_VF || + instr->m_opcode == VINSTR_BITAND_VF || + instr->m_opcode == VINSTR_BITOR_VF || + instr->m_opcode == VINSTR_BITXOR || + instr->m_opcode == VINSTR_BITXOR_VF || + instr->m_opcode == VINSTR_BITXOR_V || + instr->m_opcode == VINSTR_CROSS) { - value = instr->_ops[2]; + value = instr->_m_ops[2]; /* the float source will get an additional lifetime */ - if (ir_value_life_merge(value, instr->eid+1)) + if (ir_value_life_merge(value, instr->m_eid+1)) *changed = true; - if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1)) + if (value->m_memberof && ir_value_life_merge(value->m_memberof, instr->m_eid+1)) *changed = true; } - if (instr->opcode == INSTR_MUL_FV || - instr->opcode == INSTR_LOAD_V || - instr->opcode == VINSTR_BITXOR || - instr->opcode == VINSTR_BITXOR_VF || - instr->opcode == VINSTR_BITXOR_V || - instr->opcode == VINSTR_CROSS) + if (instr->m_opcode == INSTR_MUL_FV || + instr->m_opcode == INSTR_LOAD_V || + instr->m_opcode == VINSTR_BITXOR || + instr->m_opcode == VINSTR_BITXOR_VF || + instr->m_opcode == VINSTR_BITXOR_V || + instr->m_opcode == VINSTR_CROSS) { - value = instr->_ops[1]; + value = instr->_m_ops[1]; /* the float source will get an additional lifetime */ - if (ir_value_life_merge(value, instr->eid+1)) + if (ir_value_life_merge(value, instr->m_eid+1)) *changed = true; - if (value->memberof && ir_value_life_merge(value->memberof, instr->eid+1)) + if (value->m_memberof && ir_value_life_merge(value->m_memberof, instr->m_eid+1)) *changed = true; } for (o = 0; o < 3; ++o) { - if (!instr->_ops[o]) /* no such operand */ + if (!instr->_m_ops[o]) /* no such operand */ continue; - value = instr->_ops[o]; + value = instr->_m_ops[o]; /* We only care about locals */ /* we also calculate parameter liferanges so that locals * can take up parameter slots */ - if (value->store != store_value && - value->store != store_local && - value->store != store_param) + if (value->m_store != store_value && + value->m_store != store_local && + value->m_store != store_param) continue; /* read operands */ if (read & (1<living, value, nullptr)) - self->living.push_back(value); + if (!vec_ir_value_find(self->m_living, value, nullptr)) + self->m_living.push_back(value); /* reading adds the full vector */ - if (value->memberof && !vec_ir_value_find(self->living, value->memberof, nullptr)) - self->living.push_back(value->memberof); + if (value->m_memberof && !vec_ir_value_find(self->m_living, value->m_memberof, nullptr)) + self->m_living.push_back(value->m_memberof); for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], nullptr)) - self->living.push_back(value->members[mem]); + if (value->m_members[mem] && !vec_ir_value_find(self->m_living, value->m_members[mem], nullptr)) + self->m_living.push_back(value->m_members[mem]); } } } /* PHI operands are always read operands */ - for (auto &it : instr->phi) { + for (auto &it : instr->m_phi) { value = it.value; - if (!vec_ir_value_find(self->living, value, nullptr)) - self->living.push_back(value); + if (!vec_ir_value_find(self->m_living, value, nullptr)) + self->m_living.push_back(value); /* reading adds the full vector */ - if (value->memberof && !vec_ir_value_find(self->living, value->memberof, nullptr)) - self->living.push_back(value->memberof); + if (value->m_memberof && !vec_ir_value_find(self->m_living, value->m_memberof, nullptr)) + self->m_living.push_back(value->m_memberof); for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], nullptr)) - self->living.push_back(value->members[mem]); + if (value->m_members[mem] && !vec_ir_value_find(self->m_living, value->m_members[mem], nullptr)) + self->m_living.push_back(value->m_members[mem]); } } /* on a call, all these values must be "locked" */ - if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) { + if (instr->m_opcode >= INSTR_CALL0 && instr->m_opcode <= INSTR_CALL8) { if (ir_block_living_lock(self)) *changed = true; } /* call params are read operands too */ - for (auto &it : instr->params) { + for (auto &it : instr->m_params) { value = it; - if (!vec_ir_value_find(self->living, value, nullptr)) - self->living.push_back(value); + if (!vec_ir_value_find(self->m_living, value, nullptr)) + self->m_living.push_back(value); /* reading adds the full vector */ - if (value->memberof && !vec_ir_value_find(self->living, value->memberof, nullptr)) - self->living.push_back(value->memberof); + if (value->m_memberof && !vec_ir_value_find(self->m_living, value->m_memberof, nullptr)) + self->m_living.push_back(value->m_memberof); for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], nullptr)) - self->living.push_back(value->members[mem]); + if (value->m_members[mem] && !vec_ir_value_find(self->m_living, value->m_members[mem], nullptr)) + self->m_living.push_back(value->m_members[mem]); } } /* (A) */ - if (ir_block_living_add_instr(self, instr->eid)) + if (ir_block_living_add_instr(self, instr->m_eid)) *changed = true; } /* the "entry" instruction ID */ - if (ir_block_living_add_instr(self, self->entry_id)) + if (ir_block_living_add_instr(self, self->m_entry_id)) *changed = true; return true; @@ -2594,61 +2344,58 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) bool ir_function_calculate_liferanges(ir_function *self) { - size_t i, s; - bool changed; - /* parameters live at 0 */ - for (i = 0; i < vec_size(self->params); ++i) - if (!ir_value_life_merge(self->locals[i], 0)) - compile_error(self->context, "internal error: failed value-life merging"); + for (size_t i = 0; i < vec_size(self->m_params); ++i) + if (!ir_value_life_merge(self->m_locals[i].get(), 0)) + compile_error(self->m_context, "internal error: failed value-life merging"); + bool changed; do { - self->run_id++; + self->m_run_id++; changed = false; - i = vec_size(self->blocks); - while (i--) { - ir_block_life_propagate(self->blocks[i], &changed); - } + for (auto i = self->m_blocks.rbegin(); i != self->m_blocks.rend(); ++i) + ir_block_life_propagate(i->get(), &changed); } while (changed); - if (vec_size(self->blocks)) { - ir_block *block = self->blocks[0]; - for (auto &it : block->living) { + if (self->m_blocks.size()) { + ir_block *block = self->m_blocks[0].get(); + for (auto &it : block->m_living) { ir_value *v = it; - if (v->store != store_local) + if (v->m_store != store_local) continue; - if (v->vtype == TYPE_VECTOR) + if (v->m_vtype == TYPE_VECTOR) continue; - self->flags |= IR_FLAG_HAS_UNINITIALIZED; + self->m_flags |= IR_FLAG_HAS_UNINITIALIZED; /* find the instruction reading from it */ - for (s = 0; s < v->reads.size(); ++s) { - if (v->reads[s]->eid == v->life[0].end) + size_t s = 0; + for (; s < v->m_reads.size(); ++s) { + if (v->m_reads[s]->m_eid == v->m_life[0].end) break; } - if (s < v->reads.size()) { - if (irwarning(v->context, WARN_USED_UNINITIALIZED, + if (s < v->m_reads.size()) { + if (irwarning(v->m_context, WARN_USED_UNINITIALIZED, "variable `%s` may be used uninitialized in this function\n" " -> %s:%i", - v->name, - v->reads[s]->context.file, v->reads[s]->context.line) + v->m_name.c_str(), + v->m_reads[s]->m_context.file, v->m_reads[s]->m_context.line) ) { return false; } continue; } - if (v->memberof) { - ir_value *vec = v->memberof; - for (s = 0; s < vec->reads.size(); ++s) { - if (vec->reads[s]->eid == v->life[0].end) + if (v->m_memberof) { + ir_value *vec = v->m_memberof; + for (s = 0; s < vec->m_reads.size(); ++s) { + if (vec->m_reads[s]->m_eid == v->m_life[0].end) break; } - if (s < vec->reads.size()) { - if (irwarning(v->context, WARN_USED_UNINITIALIZED, + if (s < vec->m_reads.size()) { + if (irwarning(v->m_context, WARN_USED_UNINITIALIZED, "variable `%s` may be used uninitialized in this function\n" " -> %s:%i", - v->name, - vec->reads[s]->context.file, vec->reads[s]->context.line) + v->m_name.c_str(), + vec->m_reads[s]->m_context.file, vec->m_reads[s]->m_context.line) ) { return false; @@ -2656,8 +2403,8 @@ bool ir_function_calculate_liferanges(ir_function *self) continue; } } - if (irwarning(v->context, WARN_USED_UNINITIALIZED, - "variable `%s` may be used uninitialized in this function", v->name)) + if (irwarning(v->m_context, WARN_USED_UNINITIALIZED, + "variable `%s` may be used uninitialized in this function", v->m_name.c_str())) { return false; } @@ -2685,43 +2432,43 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc static bool gen_global_field(code_t *code, ir_value *global) { - if (global->hasvalue) + if (global->m_hasvalue) { - ir_value *fld = global->constval.vpointer; + ir_value *fld = global->m_constval.vpointer; if (!fld) { - irerror(global->context, "Invalid field constant with no field: %s", global->name); + irerror(global->m_context, "Invalid field constant with no field: %s", global->m_name.c_str()); return false; } /* copy the field's value */ ir_value_code_setaddr(global, code->globals.size()); - code->globals.push_back(fld->code.fieldaddr); - if (global->fieldtype == TYPE_VECTOR) { - code->globals.push_back(fld->code.fieldaddr+1); - code->globals.push_back(fld->code.fieldaddr+2); + code->globals.push_back(fld->m_code.fieldaddr); + if (global->m_fieldtype == TYPE_VECTOR) { + code->globals.push_back(fld->m_code.fieldaddr+1); + code->globals.push_back(fld->m_code.fieldaddr+2); } } else { ir_value_code_setaddr(global, code->globals.size()); code->globals.push_back(0); - if (global->fieldtype == TYPE_VECTOR) { + if (global->m_fieldtype == TYPE_VECTOR) { code->globals.push_back(0); code->globals.push_back(0); } } - if (global->code.globaladdr < 0) + if (global->m_code.globaladdr < 0) return false; return true; } static bool gen_global_pointer(code_t *code, ir_value *global) { - if (global->hasvalue) + if (global->m_hasvalue) { - ir_value *target = global->constval.vpointer; + ir_value *target = global->m_constval.vpointer; if (!target) { - irerror(global->context, "Invalid pointer constant: %s", global->name); + irerror(global->m_context, "Invalid pointer constant: %s", global->m_name.c_str()); /* nullptr pointers are pointing to the nullptr constant, which also * sits at address 0, but still has an ir_value for itself. */ @@ -2733,23 +2480,23 @@ static bool gen_global_pointer(code_t *code, ir_value *global) * void() *fooptr = &foo; * void() foo = { code } */ - if (!target->code.globaladdr) { + if (!target->m_code.globaladdr) { /* FIXME: Check for the constant nullptr ir_value! * because then code.globaladdr being 0 is valid. */ - irerror(global->context, "FIXME: Relocation support"); + irerror(global->m_context, "FIXME: Relocation support"); return false; } ir_value_code_setaddr(global, code->globals.size()); - code->globals.push_back(target->code.globaladdr); + code->globals.push_back(target->m_code.globaladdr); } else { ir_value_code_setaddr(global, code->globals.size()); code->globals.push_back(0); } - if (global->code.globaladdr < 0) + if (global->m_code.globaladdr < 0) return false; return true; } @@ -2765,232 +2512,232 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc size_t i; int j; - block->generated = true; - block->code_start = code->statements.size(); - for (i = 0; i < vec_size(block->instr); ++i) + block->m_generated = true; + block->m_code_start = code->statements.size(); + for (i = 0; i < vec_size(block->m_instr); ++i) { - instr = block->instr[i]; + instr = block->m_instr[i]; - if (instr->opcode == VINSTR_PHI) { - irerror(block->context, "cannot generate virtual instruction (phi)"); + if (instr->m_opcode == VINSTR_PHI) { + irerror(block->m_context, "cannot generate virtual instruction (phi)"); return false; } - if (instr->opcode == VINSTR_JUMP) { - target = instr->bops[0]; + if (instr->m_opcode == VINSTR_JUMP) { + target = instr->m_bops[0]; /* for uncoditional jumps, if the target hasn't been generated * yet, we generate them right here. */ - if (!target->generated) + if (!target->m_generated) return gen_blocks_recursive(code, func, target); /* otherwise we generate a jump instruction */ stmt.opcode = INSTR_GOTO; - stmt.o1.s1 = target->code_start - code->statements.size(); + stmt.o1.s1 = target->m_code_start - code->statements.size(); stmt.o2.s1 = 0; stmt.o3.s1 = 0; if (stmt.o1.s1 != 1) - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); /* no further instructions can be in this block */ return true; } - if (instr->opcode == VINSTR_BITXOR) { + if (instr->m_opcode == VINSTR_BITXOR) { stmt.opcode = INSTR_BITOR; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]); - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]); + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_BITAND; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]); - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]); + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]); + code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_SUB_F; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[0]); - stmt.o2.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[0]); + stmt.o2.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_BITAND_V) { + if (instr->m_opcode == VINSTR_BITAND_V) { stmt.opcode = INSTR_BITAND; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]); - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]); + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o2.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o2.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_BITOR_V) { + if (instr->m_opcode == VINSTR_BITOR_V) { stmt.opcode = INSTR_BITOR; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]); - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]); + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o2.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o2.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_BITXOR_V) { + if (instr->m_opcode == VINSTR_BITXOR_V) { for (j = 0; j < 3; ++j) { stmt.opcode = INSTR_BITOR; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j; - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]) + j; - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]) + j; - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]) + j; + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]) + j; + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]) + j; + code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_BITAND; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j; - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]) + j; - stmt.o3.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]) + j; - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]) + j; + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]) + j; + stmt.o3.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]) + j; + code_push_statement(code, &stmt, instr->m_context); } stmt.opcode = INSTR_SUB_V; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[0]); - stmt.o2.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[0]); + stmt.o2.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_BITAND_VF) { + if (instr->m_opcode == VINSTR_BITAND_VF) { stmt.opcode = INSTR_BITAND; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]); - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]); + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_BITOR_VF) { + if (instr->m_opcode == VINSTR_BITOR_VF) { stmt.opcode = INSTR_BITOR; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]); - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]); + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); ++stmt.o1.s1; ++stmt.o3.s1; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_BITXOR_VF) { + if (instr->m_opcode == VINSTR_BITXOR_VF) { for (j = 0; j < 3; ++j) { stmt.opcode = INSTR_BITOR; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j; - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]) + j; - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]) + j; + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]) + j; + code_push_statement(code, &stmt, instr->m_context); stmt.opcode = INSTR_BITAND; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + j; - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]); - stmt.o3.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]) + j; - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]) + j; + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]); + stmt.o3.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]) + j; + code_push_statement(code, &stmt, instr->m_context); } stmt.opcode = INSTR_SUB_V; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[0]); - stmt.o2.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[0]); + stmt.o2.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_CROSS) { + if (instr->m_opcode == VINSTR_CROSS) { stmt.opcode = INSTR_MUL_F; for (j = 0; j < 3; ++j) { - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + (j + 1) % 3; - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]) + (j + 2) % 3; - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]) + j; - code_push_statement(code, &stmt, instr->context); - stmt.o1.s1 = ir_value_code_addr(instr->_ops[1]) + (j + 2) % 3; - stmt.o2.s1 = ir_value_code_addr(instr->_ops[2]) + (j + 1) % 3; - stmt.o3.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]) + j; - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]) + (j + 1) % 3; + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]) + (j + 2) % 3; + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]) + j; + code_push_statement(code, &stmt, instr->m_context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[1]) + (j + 2) % 3; + stmt.o2.s1 = ir_value_code_addr(instr->_m_ops[2]) + (j + 1) % 3; + stmt.o3.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]) + j; + code_push_statement(code, &stmt, instr->m_context); } stmt.opcode = INSTR_SUB_V; - stmt.o1.s1 = ir_value_code_addr(instr->_ops[0]); - stmt.o2.s1 = ir_value_code_addr(func->owner->vinstr_temp[0]); - stmt.o3.s1 = ir_value_code_addr(instr->_ops[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.s1 = ir_value_code_addr(instr->_m_ops[0]); + stmt.o2.s1 = ir_value_code_addr(func->m_owner->m_vinstr_temp[0]); + stmt.o3.s1 = ir_value_code_addr(instr->_m_ops[0]); + code_push_statement(code, &stmt, instr->m_context); /* instruction generated */ continue; } - if (instr->opcode == VINSTR_COND) { - ontrue = instr->bops[0]; - onfalse = instr->bops[1]; + if (instr->m_opcode == VINSTR_COND) { + ontrue = instr->m_bops[0]; + onfalse = instr->m_bops[1]; /* TODO: have the AST signal which block should * come first: eg. optimize IFs without ELSE... */ - stmt.o1.u1 = ir_value_code_addr(instr->_ops[0]); + stmt.o1.u1 = ir_value_code_addr(instr->_m_ops[0]); stmt.o2.u1 = 0; stmt.o3.s1 = 0; - if (ontrue->generated) { + if (ontrue->m_generated) { stmt.opcode = INSTR_IF; - stmt.o2.s1 = ontrue->code_start - code->statements.size(); + stmt.o2.s1 = ontrue->m_code_start - code->statements.size(); if (stmt.o2.s1 != 1) - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); } - if (onfalse->generated) { + if (onfalse->m_generated) { stmt.opcode = INSTR_IFNOT; - stmt.o2.s1 = onfalse->code_start - code->statements.size(); + stmt.o2.s1 = onfalse->m_code_start - code->statements.size(); if (stmt.o2.s1 != 1) - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); } - if (!ontrue->generated) { - if (onfalse->generated) + if (!ontrue->m_generated) { + if (onfalse->m_generated) return gen_blocks_recursive(code, func, ontrue); } - if (!onfalse->generated) { - if (ontrue->generated) + if (!onfalse->m_generated) { + if (ontrue->m_generated) return gen_blocks_recursive(code, func, onfalse); } /* neither ontrue nor onfalse exist */ stmt.opcode = INSTR_IFNOT; - if (!instr->likely) { + if (!instr->m_likely) { /* Honor the likelyhood hint */ ir_block *tmp = onfalse; stmt.opcode = INSTR_IF; @@ -2998,16 +2745,16 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc ontrue = tmp; } stidx = code->statements.size(); - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); /* on false we jump, so add ontrue-path */ if (!gen_blocks_recursive(code, func, ontrue)) return false; /* fixup the jump address */ code->statements[stidx].o2.s1 = code->statements.size() - stidx; /* generate onfalse path */ - if (onfalse->generated) { + if (onfalse->m_generated) { /* fixup the jump address */ - code->statements[stidx].o2.s1 = onfalse->code_start - stidx; + code->statements[stidx].o2.s1 = onfalse->m_code_start - stidx; if (stidx+2 == code->statements.size() && code->statements[stidx].o2.s1 == 1) { code->statements[stidx] = code->statements[stidx+1]; if (code->statements[stidx].o1.s1 < 0) @@ -3026,11 +2773,11 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc } /* may have been generated in the previous recursive call */ stmt.opcode = INSTR_GOTO; - stmt.o1.s1 = onfalse->code_start - code->statements.size(); + stmt.o1.s1 = onfalse->m_code_start - code->statements.size(); stmt.o2.s1 = 0; stmt.o3.s1 = 0; if (stmt.o1.s1 != 1) - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); return true; } else if (stidx+2 == code->statements.size() && code->statements[stidx].o2.s1 == 1) { @@ -3043,141 +2790,141 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc return gen_blocks_recursive(code, func, onfalse); } - if ( (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) - || instr->opcode == VINSTR_NRCALL) + if ( (instr->m_opcode >= INSTR_CALL0 && instr->m_opcode <= INSTR_CALL8) + || instr->m_opcode == VINSTR_NRCALL) { size_t p, first; ir_value *retvalue; - first = instr->params.size(); + first = instr->m_params.size(); if (first > 8) first = 8; for (p = 0; p < first; ++p) { - ir_value *param = instr->params[p]; - if (param->callparam) + ir_value *param = instr->m_params[p]; + if (param->m_callparam) continue; stmt.opcode = INSTR_STORE_F; stmt.o3.u1 = 0; - if (param->vtype == TYPE_FIELD) - stmt.opcode = field_store_instr[param->fieldtype]; - else if (param->vtype == TYPE_NIL) + if (param->m_vtype == TYPE_FIELD) + stmt.opcode = field_store_instr[param->m_fieldtype]; + else if (param->m_vtype == TYPE_NIL) stmt.opcode = INSTR_STORE_V; else - stmt.opcode = type_store_instr[param->vtype]; + stmt.opcode = type_store_instr[param->m_vtype]; stmt.o1.u1 = ir_value_code_addr(param); stmt.o2.u1 = OFS_PARM0 + 3 * p; - if (param->vtype == TYPE_VECTOR && (param->flags & IR_FLAG_SPLIT_VECTOR)) { + if (param->m_vtype == TYPE_VECTOR && (param->m_flags & IR_FLAG_SPLIT_VECTOR)) { /* fetch 3 separate floats */ stmt.opcode = INSTR_STORE_F; - stmt.o1.u1 = ir_value_code_addr(param->members[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.u1 = ir_value_code_addr(param->m_members[0]); + code_push_statement(code, &stmt, instr->m_context); stmt.o2.u1++; - stmt.o1.u1 = ir_value_code_addr(param->members[1]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.u1 = ir_value_code_addr(param->m_members[1]); + code_push_statement(code, &stmt, instr->m_context); stmt.o2.u1++; - stmt.o1.u1 = ir_value_code_addr(param->members[2]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.u1 = ir_value_code_addr(param->m_members[2]); + code_push_statement(code, &stmt, instr->m_context); } else - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); } /* Now handle extparams */ - first = instr->params.size(); + first = instr->m_params.size(); for (; p < first; ++p) { - ir_builder *ir = func->owner; - ir_value *param = instr->params[p]; + ir_builder *ir = func->m_owner; + ir_value *param = instr->m_params[p]; ir_value *targetparam; - if (param->callparam) + if (param->m_callparam) continue; - if (p-8 >= vec_size(ir->extparams)) + if (p-8 >= ir->m_extparams.size()) ir_gen_extparam(ir); - targetparam = ir->extparams[p-8]; + targetparam = ir->m_extparams[p-8]; stmt.opcode = INSTR_STORE_F; stmt.o3.u1 = 0; - if (param->vtype == TYPE_FIELD) - stmt.opcode = field_store_instr[param->fieldtype]; - else if (param->vtype == TYPE_NIL) + if (param->m_vtype == TYPE_FIELD) + stmt.opcode = field_store_instr[param->m_fieldtype]; + else if (param->m_vtype == TYPE_NIL) stmt.opcode = INSTR_STORE_V; else - stmt.opcode = type_store_instr[param->vtype]; + stmt.opcode = type_store_instr[param->m_vtype]; stmt.o1.u1 = ir_value_code_addr(param); stmt.o2.u1 = ir_value_code_addr(targetparam); - if (param->vtype == TYPE_VECTOR && (param->flags & IR_FLAG_SPLIT_VECTOR)) { + if (param->m_vtype == TYPE_VECTOR && (param->m_flags & IR_FLAG_SPLIT_VECTOR)) { /* fetch 3 separate floats */ stmt.opcode = INSTR_STORE_F; - stmt.o1.u1 = ir_value_code_addr(param->members[0]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.u1 = ir_value_code_addr(param->m_members[0]); + code_push_statement(code, &stmt, instr->m_context); stmt.o2.u1++; - stmt.o1.u1 = ir_value_code_addr(param->members[1]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.u1 = ir_value_code_addr(param->m_members[1]); + code_push_statement(code, &stmt, instr->m_context); stmt.o2.u1++; - stmt.o1.u1 = ir_value_code_addr(param->members[2]); - code_push_statement(code, &stmt, instr->context); + stmt.o1.u1 = ir_value_code_addr(param->m_members[2]); + code_push_statement(code, &stmt, instr->m_context); } else - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); } - stmt.opcode = INSTR_CALL0 + instr->params.size(); + stmt.opcode = INSTR_CALL0 + instr->m_params.size(); if (stmt.opcode > INSTR_CALL8) stmt.opcode = INSTR_CALL8; - stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]); + stmt.o1.u1 = ir_value_code_addr(instr->_m_ops[1]); stmt.o2.u1 = 0; stmt.o3.u1 = 0; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); - retvalue = instr->_ops[0]; - if (retvalue && retvalue->store != store_return && - (retvalue->store == store_global || vec_size(retvalue->life))) + retvalue = instr->_m_ops[0]; + if (retvalue && retvalue->m_store != store_return && + (retvalue->m_store == store_global || retvalue->m_life.size())) { /* not to be kept in OFS_RETURN */ - if (retvalue->vtype == TYPE_FIELD && OPTS_FLAG(ADJUST_VECTOR_FIELDS)) - stmt.opcode = field_store_instr[retvalue->fieldtype]; + if (retvalue->m_vtype == TYPE_FIELD && OPTS_FLAG(ADJUST_VECTOR_FIELDS)) + stmt.opcode = field_store_instr[retvalue->m_fieldtype]; else - stmt.opcode = type_store_instr[retvalue->vtype]; + stmt.opcode = type_store_instr[retvalue->m_vtype]; stmt.o1.u1 = OFS_RETURN; stmt.o2.u1 = ir_value_code_addr(retvalue); stmt.o3.u1 = 0; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); } continue; } - if (instr->opcode == INSTR_STATE) { - stmt.opcode = instr->opcode; - if (instr->_ops[0]) - stmt.o1.u1 = ir_value_code_addr(instr->_ops[0]); - if (instr->_ops[1]) - stmt.o2.u1 = ir_value_code_addr(instr->_ops[1]); + if (instr->m_opcode == INSTR_STATE) { + stmt.opcode = instr->m_opcode; + if (instr->_m_ops[0]) + stmt.o1.u1 = ir_value_code_addr(instr->_m_ops[0]); + if (instr->_m_ops[1]) + stmt.o2.u1 = ir_value_code_addr(instr->_m_ops[1]); stmt.o3.u1 = 0; - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); continue; } - stmt.opcode = instr->opcode; + stmt.opcode = instr->m_opcode; stmt.o1.u1 = 0; stmt.o2.u1 = 0; stmt.o3.u1 = 0; /* This is the general order of operands */ - if (instr->_ops[0]) - stmt.o3.u1 = ir_value_code_addr(instr->_ops[0]); + if (instr->_m_ops[0]) + stmt.o3.u1 = ir_value_code_addr(instr->_m_ops[0]); - if (instr->_ops[1]) - stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]); + if (instr->_m_ops[1]) + stmt.o1.u1 = ir_value_code_addr(instr->_m_ops[1]); - if (instr->_ops[2]) - stmt.o2.u1 = ir_value_code_addr(instr->_ops[2]); + if (instr->_m_ops[2]) + stmt.o2.u1 = ir_value_code_addr(instr->_m_ops[2]); if (stmt.opcode == INSTR_RETURN || stmt.opcode == INSTR_DONE) { @@ -3203,7 +2950,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc continue; } } - code_push_statement(code, &stmt, instr->context); + code_push_statement(code, &stmt, instr->m_context); } return true; } @@ -3216,24 +2963,24 @@ static bool gen_function_code(code_t *code, ir_function *self) /* Starting from entry point, we generate blocks "as they come" * for now. Dead blocks will not be translated obviously. */ - if (!vec_size(self->blocks)) { - irerror(self->context, "Function '%s' declared without body.", self->name); + if (self->m_blocks.empty()) { + irerror(self->m_context, "Function '%s' declared without body.", self->m_name.c_str()); return false; } - block = self->blocks[0]; - if (block->generated) + block = self->m_blocks[0].get(); + if (block->m_generated) return true; if (!gen_blocks_recursive(code, self, block)) { - irerror(self->context, "failed to generate blocks for '%s'", self->name); + irerror(self->m_context, "failed to generate blocks for '%s'", self->m_name.c_str()); return false; } /* code_write and qcvm -disasm need to know that the function ends here */ retst = &code->statements.back(); if (OPTS_OPTIMIZATION(OPTIM_VOID_RETURN) && - self->outtype == TYPE_VOID && + self->m_outtype == TYPE_VOID && retst->opcode == INSTR_RETURN && !retst->o1.u1 && !retst->o2.u1 && !retst->o3.u1) { @@ -3259,17 +3006,16 @@ static qcint_t ir_builder_filestring(ir_builder *ir, const char *filename) /* NOTE: filename pointers are copied, we never strdup them, * thus we can use pointer-comparison to find the string. */ - size_t i; qcint_t str; - for (i = 0; i < vec_size(ir->filenames); ++i) { - if (ir->filenames[i] == filename) - return ir->filestrings[i]; + for (size_t i = 0; i != ir->m_filenames.size(); ++i) { + if (!strcmp(ir->m_filenames[i], filename)) + return i; } - str = code_genstring(ir->code, filename); - vec_push(ir->filenames, filename); - vec_push(ir->filestrings, str); + str = code_genstring(ir->m_code.get(), filename); + ir->m_filenames.push_back(filename); + ir->m_filestrings.push_back(str); return str; } @@ -3280,16 +3026,16 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) size_t i; - if (!global->hasvalue || (!global->constval.vfunc)) { - irerror(global->context, "Invalid state of function-global: not constant: %s", global->name); + if (!global->m_hasvalue || (!global->m_constval.vfunc)) { + irerror(global->m_context, "Invalid state of function-global: not constant: %s", global->m_name.c_str()); return false; } - irfun = global->constval.vfunc; - fun.name = global->code.name; - fun.file = ir_builder_filestring(ir, global->context.file); + irfun = global->m_constval.vfunc; + fun.name = global->m_code.name; + fun.file = ir_builder_filestring(ir, global->m_context.file); fun.profile = 0; /* always 0 */ - fun.nargs = vec_size(irfun->params); + fun.nargs = vec_size(irfun->m_params); if (fun.nargs > 8) fun.nargs = 8; @@ -3297,32 +3043,31 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) if ((int32_t)i >= fun.nargs) fun.argsize[i] = 0; else - fun.argsize[i] = type_sizeof_[irfun->params[i]]; + fun.argsize[i] = type_sizeof_[irfun->m_params[i]]; } fun.firstlocal = 0; - fun.locals = irfun->allocated_locals; + fun.locals = irfun->m_allocated_locals; - if (irfun->builtin) - fun.entry = irfun->builtin+1; + if (irfun->m_builtin) + fun.entry = irfun->m_builtin+1; else { - irfun->code_function_def = ir->code->functions.size(); - fun.entry = ir->code->statements.size(); + irfun->m_code_function_def = ir->m_code->functions.size(); + fun.entry = ir->m_code->statements.size(); } - ir->code->functions.push_back(fun); + ir->m_code->functions.push_back(fun); return true; } static ir_value* ir_gen_extparam_proto(ir_builder *ir) { - ir_value *global; char name[128]; - util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(vec_size(ir->extparam_protos))); - global = ir_value_var(name, store_global, TYPE_VECTOR); + util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(ir->m_extparam_protos.size())); + ir_value *global = new ir_value(name, store_global, TYPE_VECTOR); + ir->m_extparam_protos.emplace_back(global); - vec_push(ir->extparam_protos, global); return global; } @@ -3331,56 +3076,53 @@ static void ir_gen_extparam(ir_builder *ir) prog_section_def_t def; ir_value *global; - if (vec_size(ir->extparam_protos) < vec_size(ir->extparams)+1) + if (ir->m_extparam_protos.size() < ir->m_extparams.size()+1) global = ir_gen_extparam_proto(ir); else - global = ir->extparam_protos[vec_size(ir->extparams)]; + global = ir->m_extparam_protos[ir->m_extparams.size()].get(); - def.name = code_genstring(ir->code, global->name); + def.name = code_genstring(ir->m_code.get(), global->m_name.c_str()); def.type = TYPE_VECTOR; - def.offset = ir->code->globals.size(); + def.offset = ir->m_code->globals.size(); - ir->code->defs.push_back(def); + ir->m_code->defs.push_back(def); ir_value_code_setaddr(global, def.offset); - ir->code->globals.push_back(0); - ir->code->globals.push_back(0); - ir->code->globals.push_back(0); + ir->m_code->globals.push_back(0); + ir->m_code->globals.push_back(0); + ir->m_code->globals.push_back(0); - vec_push(ir->extparams, global); + ir->m_extparams.emplace_back(global); } static bool gen_function_extparam_copy(code_t *code, ir_function *self) { - size_t i, ext, numparams; + ir_builder *ir = self->m_owner; - ir_builder *ir = self->owner; - ir_value *ep; - prog_section_statement_t stmt; - - numparams = vec_size(self->params); + size_t numparams = vec_size(self->m_params); if (!numparams) return true; + prog_section_statement_t stmt; stmt.opcode = INSTR_STORE_F; stmt.o3.s1 = 0; - for (i = 8; i < numparams; ++i) { - ext = i - 8; - if (ext >= vec_size(ir->extparams)) + for (size_t i = 8; i < numparams; ++i) { + size_t ext = i - 8; + if (ext >= ir->m_extparams.size()) ir_gen_extparam(ir); - ep = ir->extparams[ext]; + ir_value *ep = ir->m_extparams[ext]; - stmt.opcode = type_store_instr[self->locals[i]->vtype]; - if (self->locals[i]->vtype == TYPE_FIELD && - self->locals[i]->fieldtype == TYPE_VECTOR) + stmt.opcode = type_store_instr[self->m_locals[i]->m_vtype]; + if (self->m_locals[i]->m_vtype == TYPE_FIELD && + self->m_locals[i]->m_fieldtype == TYPE_VECTOR) { stmt.opcode = INSTR_STORE_V; } stmt.o1.u1 = ir_value_code_addr(ep); - stmt.o2.u1 = ir_value_code_addr(self->locals[i]); - code_push_statement(code, &stmt, self->context); + stmt.o2.u1 = ir_value_code_addr(self->m_locals[i].get()); + code_push_statement(code, &stmt, self->m_context); } return true; @@ -3390,33 +3132,33 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self) { size_t i, ext, numparams, maxparams; - ir_builder *ir = self->owner; + ir_builder *ir = self->m_owner; ir_value *ep; prog_section_statement_t stmt; - numparams = vec_size(self->params); + numparams = vec_size(self->m_params); if (!numparams) return true; stmt.opcode = INSTR_STORE_V; stmt.o3.s1 = 0; - maxparams = numparams + self->max_varargs; + maxparams = numparams + self->m_max_varargs; for (i = numparams; i < maxparams; ++i) { if (i < 8) { stmt.o1.u1 = OFS_PARM0 + 3*i; - stmt.o2.u1 = ir_value_code_addr(self->locals[i]); - code_push_statement(code, &stmt, self->context); + stmt.o2.u1 = ir_value_code_addr(self->m_locals[i].get()); + code_push_statement(code, &stmt, self->m_context); continue; } ext = i - 8; - while (ext >= vec_size(ir->extparams)) + while (ext >= ir->m_extparams.size()) ir_gen_extparam(ir); - ep = ir->extparams[ext]; + ep = ir->m_extparams[ext]; stmt.o1.u1 = ir_value_code_addr(ep); - stmt.o2.u1 = ir_value_code_addr(self->locals[i]); - code_push_statement(code, &stmt, self->context); + stmt.o2.u1 = ir_value_code_addr(self->m_locals[i].get()); + code_push_statement(code, &stmt, self->m_context); } return true; @@ -3426,47 +3168,46 @@ static bool gen_function_locals(ir_builder *ir, ir_value *global) { prog_section_function_t *def; ir_function *irfun; - size_t i; uint32_t firstlocal, firstglobal; - irfun = global->constval.vfunc; - def = &ir->code->functions[0] + irfun->code_function_def; + irfun = global->m_constval.vfunc; + def = &ir->m_code->functions[0] + irfun->m_code_function_def; if (OPTS_OPTION_BOOL(OPTION_G) || !OPTS_OPTIMIZATION(OPTIM_OVERLAP_LOCALS) || - (irfun->flags & IR_FLAG_MASK_NO_OVERLAP)) + (irfun->m_flags & IR_FLAG_MASK_NO_OVERLAP)) { - firstlocal = def->firstlocal = ir->code->globals.size(); + firstlocal = def->firstlocal = ir->m_code->globals.size(); } else { - firstlocal = def->firstlocal = ir->first_common_local; + firstlocal = def->firstlocal = ir->m_first_common_local; ++opts_optimizationcount[OPTIM_OVERLAP_LOCALS]; } - firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? ir->first_common_globaltemp : firstlocal); + firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? ir->m_first_common_globaltemp : firstlocal); + + for (size_t i = ir->m_code->globals.size(); i < firstlocal + irfun->m_allocated_locals; ++i) + ir->m_code->globals.push_back(0); - for (i = ir->code->globals.size(); i < firstlocal + irfun->allocated_locals; ++i) - ir->code->globals.push_back(0); - for (i = 0; i < vec_size(irfun->locals); ++i) { - ir_value *v = irfun->locals[i]; - if (v->locked || !OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS)) { - ir_value_code_setaddr(v, firstlocal + v->code.local); - if (!ir_builder_gen_global(ir, irfun->locals[i], true)) { - irerror(irfun->locals[i]->context, "failed to generate local %s", irfun->locals[i]->name); + for (auto& lp : irfun->m_locals) { + ir_value *v = lp.get(); + if (v->m_locked || !OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS)) { + ir_value_code_setaddr(v, firstlocal + v->m_code.local); + if (!ir_builder_gen_global(ir, v, true)) { + irerror(v->m_context, "failed to generate local %s", v->m_name.c_str()); return false; } } else - ir_value_code_setaddr(v, firstglobal + v->code.local); + ir_value_code_setaddr(v, firstglobal + v->m_code.local); } - for (i = 0; i < vec_size(irfun->values); ++i) - { - ir_value *v = irfun->values[i]; - if (v->callparam) + for (auto& vp : irfun->m_values) { + ir_value *v = vp.get(); + if (v->m_callparam) continue; - if (v->locked) - ir_value_code_setaddr(v, firstlocal + v->code.local); + if (v->m_locked) + ir_value_code_setaddr(v, firstlocal + v->m_code.local); else - ir_value_code_setaddr(v, firstglobal + v->code.local); + ir_value_code_setaddr(v, firstglobal + v->m_code.local); } return true; } @@ -3478,12 +3219,12 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) (void)ir; - irfun = global->constval.vfunc; + irfun = global->m_constval.vfunc; if (!irfun) { - if (global->cvq == CV_NONE) { - if (irwarning(global->context, WARN_IMPLICIT_FUNCTION_POINTER, + if (global->m_cvq == CV_NONE) { + if (irwarning(global->m_context, WARN_IMPLICIT_FUNCTION_POINTER, "function `%s` has no body and in QC implicitly becomes a function-pointer", - global->name)) + global->m_name.c_str())) { /* Not bailing out just now. If this happens a lot you don't want to have * to rerun gmqcc for each such function. @@ -3496,38 +3237,38 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) return true; } - if (irfun->builtin) + if (irfun->m_builtin) return true; /* * If there is no definition and the thing is eraseable, we can ignore * outputting the function to begin with. */ - if (global->flags & IR_FLAG_ERASABLE && irfun->code_function_def < 0) { + if (global->m_flags & IR_FLAG_ERASABLE && irfun->m_code_function_def < 0) { return true; } - if (irfun->code_function_def < 0) { - irerror(irfun->context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->name); + if (irfun->m_code_function_def < 0) { + irerror(irfun->m_context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->m_name.c_str()); return false; } - fundef = &ir->code->functions[irfun->code_function_def]; + fundef = &ir->m_code->functions[irfun->m_code_function_def]; - fundef->entry = ir->code->statements.size(); + fundef->entry = ir->m_code->statements.size(); if (!gen_function_locals(ir, global)) { - irerror(irfun->context, "Failed to generate locals for function %s", irfun->name); + irerror(irfun->m_context, "Failed to generate locals for function %s", irfun->m_name.c_str()); return false; } - if (!gen_function_extparam_copy(ir->code, irfun)) { - irerror(irfun->context, "Failed to generate extparam-copy code for function %s", irfun->name); + if (!gen_function_extparam_copy(ir->m_code.get(), irfun)) { + irerror(irfun->m_context, "Failed to generate extparam-copy code for function %s", irfun->m_name.c_str()); return false; } - if (irfun->max_varargs && !gen_function_varargs_copy(ir->code, irfun)) { - irerror(irfun->context, "Failed to generate vararg-copy code for function %s", irfun->name); + if (irfun->m_max_varargs && !gen_function_varargs_copy(ir->m_code.get(), irfun)) { + irerror(irfun->m_context, "Failed to generate vararg-copy code for function %s", irfun->m_name.c_str()); return false; } - if (!gen_function_code(ir->code, irfun)) { - irerror(irfun->context, "Failed to generate code for function %s", irfun->name); + if (!gen_function_code(ir->m_code.get(), irfun)) { + irerror(irfun->m_context, "Failed to generate code for function %s", irfun->m_name.c_str()); return false; } return true; @@ -3601,11 +3342,11 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc bool pushdef = opts.optimizeoff; /* we don't generate split-vectors */ - if (global->vtype == TYPE_VECTOR && (global->flags & IR_FLAG_SPLIT_VECTOR)) + if (global->m_vtype == TYPE_VECTOR && (global->m_flags & IR_FLAG_SPLIT_VECTOR)) return true; - def.type = global->vtype; - def.offset = self->code->globals.size(); + def.type = global->m_vtype; + def.offset = self->m_code->globals.size(); def.name = 0; if (OPTS_OPTION_BOOL(OPTION_G) || !islocal) { @@ -3615,55 +3356,53 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc * if we're eraseable and the function isn't referenced ignore outputting * the function. */ - if (global->flags & IR_FLAG_ERASABLE && global->reads.empty()) { + if (global->m_flags & IR_FLAG_ERASABLE && global->m_reads.empty()) { return true; } if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) && - !(global->flags & IR_FLAG_INCLUDE_DEF) && - (global->name[0] == '#' || global->cvq == CV_CONST)) + !(global->m_flags & IR_FLAG_INCLUDE_DEF) && + (global->m_name[0] == '#' || global->m_cvq == CV_CONST)) { pushdef = false; } if (pushdef) { - if (global->name[0] == '#') { - if (!self->str_immediate) - self->str_immediate = code_genstring(self->code, "IMMEDIATE"); - def.name = global->code.name = self->str_immediate; + if (global->m_name[0] == '#') { + if (!self->m_str_immediate) + self->m_str_immediate = code_genstring(self->m_code.get(), "IMMEDIATE"); + def.name = global->m_code.name = self->m_str_immediate; } else - def.name = global->code.name = code_genstring(self->code, global->name); + def.name = global->m_code.name = code_genstring(self->m_code.get(), global->m_name.c_str()); } else def.name = 0; if (islocal) { def.offset = ir_value_code_addr(global); - self->code->defs.push_back(def); - if (global->vtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name); - else if (global->vtype == TYPE_FIELD && global->fieldtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name); + self->m_code->defs.push_back(def); + if (global->m_vtype == TYPE_VECTOR) + gen_vector_defs(self->m_code.get(), def, global->m_name.c_str()); + else if (global->m_vtype == TYPE_FIELD && global->m_fieldtype == TYPE_VECTOR) + gen_vector_defs(self->m_code.get(), def, global->m_name.c_str()); return true; } } if (islocal) return true; - switch (global->vtype) + switch (global->m_vtype) { case TYPE_VOID: - if (!strcmp(global->name, "end_sys_globals")) { - /* TODO: remember this point... all the defs before this one - * should be checksummed and added to progdefs.h when we generate it. - */ + if (0 == global->m_name.compare("end_sys_globals")) { + // TODO: remember this point... all the defs before this one + // should be checksummed and added to progdefs.h when we generate it. } - else if (!strcmp(global->name, "end_sys_fields")) { - /* TODO: same as above but for entity-fields rather than globsl - */ + else if (0 == global->m_name.compare("end_sys_fields")) { + // TODO: same as above but for entity-fields rather than globsl } - else if(irwarning(global->context, WARN_VOID_VARIABLES, "unrecognized variable of type void `%s`", - global->name)) + else if(irwarning(global->m_context, WARN_VOID_VARIABLES, "unrecognized variable of type void `%s`", + global->m_name.c_str())) { /* Not bailing out */ /* return false; */ @@ -3673,115 +3412,115 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc * Maybe this could be an -foption * fteqcc creates data for end_sys_* - of size 1, so let's do the same */ - ir_value_code_setaddr(global, self->code->globals.size()); - self->code->globals.push_back(0); + ir_value_code_setaddr(global, self->m_code->globals.size()); + self->m_code->globals.push_back(0); /* Add the def */ - if (pushdef) self->code->defs.push_back(def); + if (pushdef) self->m_code->defs.push_back(def); return true; case TYPE_POINTER: - if (pushdef) self->code->defs.push_back(def); - return gen_global_pointer(self->code, global); + if (pushdef) self->m_code->defs.push_back(def); + return gen_global_pointer(self->m_code.get(), global); case TYPE_FIELD: if (pushdef) { - self->code->defs.push_back(def); - if (global->fieldtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name); + self->m_code->defs.push_back(def); + if (global->m_fieldtype == TYPE_VECTOR) + gen_vector_defs(self->m_code.get(), def, global->m_name.c_str()); } - return gen_global_field(self->code, global); + return gen_global_field(self->m_code.get(), global); case TYPE_ENTITY: /* fall through */ case TYPE_FLOAT: { - ir_value_code_setaddr(global, self->code->globals.size()); - if (global->hasvalue) { - iptr = (int32_t*)&global->constval.ivec[0]; - self->code->globals.push_back(*iptr); + ir_value_code_setaddr(global, self->m_code->globals.size()); + if (global->m_hasvalue) { + iptr = (int32_t*)&global->m_constval.ivec[0]; + self->m_code->globals.push_back(*iptr); } else { - self->code->globals.push_back(0); + self->m_code->globals.push_back(0); } - if (!islocal && global->cvq != CV_CONST) + if (!islocal && global->m_cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) self->code->defs.push_back(def); + if (pushdef) self->m_code->defs.push_back(def); - return global->code.globaladdr >= 0; + return global->m_code.globaladdr >= 0; } case TYPE_STRING: { - ir_value_code_setaddr(global, self->code->globals.size()); - if (global->hasvalue) { - uint32_t load = code_genstring(self->code, global->constval.vstring); - self->code->globals.push_back(load); + ir_value_code_setaddr(global, self->m_code->globals.size()); + if (global->m_hasvalue) { + uint32_t load = code_genstring(self->m_code.get(), global->m_constval.vstring); + self->m_code->globals.push_back(load); } else { - self->code->globals.push_back(0); + self->m_code->globals.push_back(0); } - if (!islocal && global->cvq != CV_CONST) + if (!islocal && global->m_cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) self->code->defs.push_back(def); - return global->code.globaladdr >= 0; + if (pushdef) self->m_code->defs.push_back(def); + return global->m_code.globaladdr >= 0; } case TYPE_VECTOR: { size_t d; - ir_value_code_setaddr(global, self->code->globals.size()); - if (global->hasvalue) { - iptr = (int32_t*)&global->constval.ivec[0]; - self->code->globals.push_back(iptr[0]); - if (global->code.globaladdr < 0) + ir_value_code_setaddr(global, self->m_code->globals.size()); + if (global->m_hasvalue) { + iptr = (int32_t*)&global->m_constval.ivec[0]; + self->m_code->globals.push_back(iptr[0]); + if (global->m_code.globaladdr < 0) return false; - for (d = 1; d < type_sizeof_[global->vtype]; ++d) { - self->code->globals.push_back(iptr[d]); + for (d = 1; d < type_sizeof_[global->m_vtype]; ++d) { + self->m_code->globals.push_back(iptr[d]); } } else { - self->code->globals.push_back(0); - if (global->code.globaladdr < 0) + self->m_code->globals.push_back(0); + if (global->m_code.globaladdr < 0) return false; - for (d = 1; d < type_sizeof_[global->vtype]; ++d) { - self->code->globals.push_back(0); + for (d = 1; d < type_sizeof_[global->m_vtype]; ++d) { + self->m_code->globals.push_back(0); } } - if (!islocal && global->cvq != CV_CONST) + if (!islocal && global->m_cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; if (pushdef) { - self->code->defs.push_back(def); + self->m_code->defs.push_back(def); def.type &= ~DEF_SAVEGLOBAL; - gen_vector_defs(self->code, def, global->name); + gen_vector_defs(self->m_code.get(), def, global->m_name.c_str()); } - return global->code.globaladdr >= 0; + return global->m_code.globaladdr >= 0; } case TYPE_FUNCTION: - ir_value_code_setaddr(global, self->code->globals.size()); - if (!global->hasvalue) { - self->code->globals.push_back(0); - if (global->code.globaladdr < 0) + ir_value_code_setaddr(global, self->m_code->globals.size()); + if (!global->m_hasvalue) { + self->m_code->globals.push_back(0); + if (global->m_code.globaladdr < 0) return false; } else { - self->code->globals.push_back(self->code->functions.size()); + self->m_code->globals.push_back(self->m_code->functions.size()); if (!gen_global_function(self, global)) return false; } - if (!islocal && global->cvq != CV_CONST) + if (!islocal && global->m_cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) self->code->defs.push_back(def); + if (pushdef) self->m_code->defs.push_back(def); return true; case TYPE_VARIANT: /* assume biggest type */ - ir_value_code_setaddr(global, self->code->globals.size()); - self->code->globals.push_back(0); + ir_value_code_setaddr(global, self->m_code->globals.size()); + self->m_code->globals.push_back(0); for (i = 1; i < type_sizeof_[TYPE_VARIANT]; ++i) - self->code->globals.push_back(0); + self->m_code->globals.push_back(0); return true; default: /* refuse to create 'void' type or any other fancy business. */ - irerror(global->context, "Invalid type for global variable `%s`: %s", - global->name, type_name[global->vtype]); + irerror(global->m_context, "Invalid type for global variable `%s`: %s", + global->m_name.c_str(), type_name[global->m_vtype]); return false; } } static GMQCC_INLINE void ir_builder_prepare_field(code_t *code, ir_value *field) { - field->code.fieldaddr = code_alloc_field(code, type_sizeof_[field->fieldtype]); + field->m_code.fieldaddr = code_alloc_field(code, type_sizeof_[field->m_fieldtype]); } static bool ir_builder_gen_field(ir_builder *self, ir_value *field) @@ -3791,28 +3530,28 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) (void)self; - def.type = (uint16_t)field->vtype; - def.offset = (uint16_t)self->code->globals.size(); + def.type = (uint16_t)field->m_vtype; + def.offset = (uint16_t)self->m_code->globals.size(); /* create a global named the same as the field */ if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_GMQCC) { /* in our standard, the global gets a dot prefix */ - size_t len = strlen(field->name); + size_t len = field->m_name.length(); char name[1024]; /* we really don't want to have to allocate this, and 1024 * bytes is more than enough for a variable/field name */ if (len+2 >= sizeof(name)) { - irerror(field->context, "invalid field name size: %u", (unsigned int)len); + irerror(field->m_context, "invalid field name size: %u", (unsigned int)len); return false; } name[0] = '.'; - memcpy(name+1, field->name, len); /* no strncpy - we used strlen above */ + memcpy(name+1, field->m_name.c_str(), len); // no strncpy - we used strlen above name[len+1] = 0; - def.name = code_genstring(self->code, name); + def.name = code_genstring(self->m_code.get(), name); fld.name = def.name + 1; /* we reuse that string table entry */ } else { /* in plain QC, there cannot be a global with the same name, @@ -3820,220 +3559,217 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) * FIXME: fteqcc should create a global as well * check if it actually uses the same name. Probably does */ - def.name = code_genstring(self->code, field->name); + def.name = code_genstring(self->m_code.get(), field->m_name.c_str()); fld.name = def.name; } - field->code.name = def.name; + field->m_code.name = def.name; - self->code->defs.push_back(def); + self->m_code->defs.push_back(def); - fld.type = field->fieldtype; + fld.type = field->m_fieldtype; if (fld.type == TYPE_VOID) { - irerror(field->context, "field is missing a type: %s - don't know its size", field->name); + irerror(field->m_context, "field is missing a type: %s - don't know its size", field->m_name.c_str()); return false; } - fld.offset = field->code.fieldaddr; + fld.offset = field->m_code.fieldaddr; - self->code->fields.push_back(fld); + self->m_code->fields.push_back(fld); - ir_value_code_setaddr(field, self->code->globals.size()); - self->code->globals.push_back(fld.offset); + ir_value_code_setaddr(field, self->m_code->globals.size()); + self->m_code->globals.push_back(fld.offset); if (fld.type == TYPE_VECTOR) { - self->code->globals.push_back(fld.offset+1); - self->code->globals.push_back(fld.offset+2); + self->m_code->globals.push_back(fld.offset+1); + self->m_code->globals.push_back(fld.offset+2); } - if (field->fieldtype == TYPE_VECTOR) { - gen_vector_defs (self->code, def, field->name); - gen_vector_fields(self->code, fld, field->name); + if (field->m_fieldtype == TYPE_VECTOR) { + gen_vector_defs (self->m_code.get(), def, field->m_name.c_str()); + gen_vector_fields(self->m_code.get(), fld, field->m_name.c_str()); } - return field->code.globaladdr >= 0; + return field->m_code.globaladdr >= 0; } static void ir_builder_collect_reusables(ir_builder *builder) { - size_t i; - ir_value **reusables = nullptr; - for (i = 0; i < vec_size(builder->globals); ++i) { - ir_value *value = builder->globals[i]; - if (value->vtype != TYPE_FLOAT || !value->hasvalue) + std::vector reusables; + + for (auto& gp : builder->m_globals) { + ir_value *value = gp.get(); + if (value->m_vtype != TYPE_FLOAT || !value->m_hasvalue) continue; - if (value->cvq == CV_CONST || (value->name && value->name[0] == '#')) { - vec_push(reusables, value); - } + if (value->m_cvq == CV_CONST || (value->m_name.length() >= 1 && value->m_name[0] == '#')) + reusables.emplace_back(value); } - builder->const_floats = reusables; + builder->m_const_floats = move(reusables); } static void ir_builder_split_vector(ir_builder *self, ir_value *vec) { - size_t i, count; ir_value* found[3] = { nullptr, nullptr, nullptr }; - /* must not be written to */ - if (vec->writes.size()) + // must not be written to + if (vec->m_writes.size()) return; - /* must not be trying to access individual members */ - if (vec->members[0] || vec->members[1] || vec->members[2]) + // must not be trying to access individual members + if (vec->m_members[0] || vec->m_members[1] || vec->m_members[2]) return; - /* should be actually used otherwise it won't be generated anyway */ - count = vec->reads.size(); - if (!count) + // should be actually used otherwise it won't be generated anyway + if (vec->m_reads.empty()) return; - - /* may only be used directly as function parameters, so if we find some other instruction cancel */ - for (i = 0; i != count; ++i) { - /* we only split vectors if they're used directly as parameter to a call only! */ - ir_instr *user = vec->reads[i]; - if ((user->opcode < INSTR_CALL0 || user->opcode > INSTR_CALL8) && user->opcode != VINSTR_NRCALL) + //size_t count = vec->m_reads.size(); + //if (!count) + // return; + + // may only be used directly as function parameters, so if we find some other instruction cancel + for (ir_instr *user : vec->m_reads) { + // we only split vectors if they're used directly as parameter to a call only! + if ((user->m_opcode < INSTR_CALL0 || user->m_opcode > INSTR_CALL8) && user->m_opcode != VINSTR_NRCALL) return; } - vec->flags |= IR_FLAG_SPLIT_VECTOR; + vec->m_flags |= IR_FLAG_SPLIT_VECTOR; - /* find existing floats making up the split */ - count = vec_size(self->const_floats); - for (i = 0; i != count; ++i) { - ir_value *c = self->const_floats[i]; - if (!found[0] && c->constval.vfloat == vec->constval.vvec.x) + // find existing floats making up the split + for (ir_value *c : self->m_const_floats) { + if (!found[0] && c->m_constval.vfloat == vec->m_constval.vvec.x) found[0] = c; - if (!found[1] && c->constval.vfloat == vec->constval.vvec.y) + if (!found[1] && c->m_constval.vfloat == vec->m_constval.vvec.y) found[1] = c; - if (!found[2] && c->constval.vfloat == vec->constval.vvec.z) + if (!found[2] && c->m_constval.vfloat == vec->m_constval.vvec.z) found[2] = c; if (found[0] && found[1] && found[2]) break; } - /* generate floats for not yet found components */ + // generate floats for not yet found components if (!found[0]) - found[0] = ir_builder_imm_float(self, vec->constval.vvec.x, true); + found[0] = ir_builder_imm_float(self, vec->m_constval.vvec.x, true); if (!found[1]) { - if (vec->constval.vvec.y == vec->constval.vvec.x) + if (vec->m_constval.vvec.y == vec->m_constval.vvec.x) found[1] = found[0]; else - found[1] = ir_builder_imm_float(self, vec->constval.vvec.y, true); + found[1] = ir_builder_imm_float(self, vec->m_constval.vvec.y, true); } if (!found[2]) { - if (vec->constval.vvec.z == vec->constval.vvec.x) + if (vec->m_constval.vvec.z == vec->m_constval.vvec.x) found[2] = found[0]; - else if (vec->constval.vvec.z == vec->constval.vvec.y) + else if (vec->m_constval.vvec.z == vec->m_constval.vvec.y) found[2] = found[1]; else - found[2] = ir_builder_imm_float(self, vec->constval.vvec.z, true); + found[2] = ir_builder_imm_float(self, vec->m_constval.vvec.z, true); } - /* the .members array should be safe to use here. */ - vec->members[0] = found[0]; - vec->members[1] = found[1]; - vec->members[2] = found[2]; + // the .members array should be safe to use here + vec->m_members[0] = found[0]; + vec->m_members[1] = found[1]; + vec->m_members[2] = found[2]; - /* register the readers for these floats */ - count = vec->reads.size(); - for (i = 0; i != count; ++i) { - found[0]->reads.push_back(vec->reads[i]); - found[1]->reads.push_back(vec->reads[i]); - found[2]->reads.push_back(vec->reads[i]); - } + // register the readers for these floats + found[0]->m_reads.insert(found[0]->m_reads.end(), vec->m_reads.begin(), vec->m_reads.end()); + found[1]->m_reads.insert(found[1]->m_reads.end(), vec->m_reads.begin(), vec->m_reads.end()); + found[2]->m_reads.insert(found[2]->m_reads.end(), vec->m_reads.begin(), vec->m_reads.end()); } static void ir_builder_split_vectors(ir_builder *self) { - size_t i, count = vec_size(self->globals); - for (i = 0; i != count; ++i) { - ir_value *v = self->globals[i]; - if (v->vtype != TYPE_VECTOR || !v->name || v->name[0] != '#') + // member values may be added to self->m_globals during this operation, but + // no new vectors will be added, we need to iterate via an index as + // c++ iterators would be invalidated + const size_t count = self->m_globals.size(); + for (size_t i = 0; i != count; ++i) { + ir_value *v = self->m_globals[i].get(); + if (v->m_vtype != TYPE_VECTOR || !v->m_name.length() || v->m_name[0] != '#') continue; - ir_builder_split_vector(self, self->globals[i]); + ir_builder_split_vector(self, v); } } bool ir_builder_generate(ir_builder *self, const char *filename) { prog_section_statement_t stmt; - size_t i; char *lnofile = nullptr; if (OPTS_FLAG(SPLIT_VECTOR_PARAMETERS)) { ir_builder_collect_reusables(self); - if (vec_size(self->const_floats) > 0) + if (!self->m_const_floats.empty()) ir_builder_split_vectors(self); } - for (i = 0; i < vec_size(self->fields); ++i) - { - ir_builder_prepare_field(self->code, self->fields[i]); - } + for (auto& fp : self->m_fields) + ir_builder_prepare_field(self->m_code.get(), fp.get()); - for (i = 0; i < vec_size(self->globals); ++i) - { - if (!ir_builder_gen_global(self, self->globals[i], false)) { + for (auto& gp : self->m_globals) { + ir_value *global = gp.get(); + if (!ir_builder_gen_global(self, global, false)) { return false; } - if (self->globals[i]->vtype == TYPE_FUNCTION) { - ir_function *func = self->globals[i]->constval.vfunc; - if (func && self->max_locals < func->allocated_locals && - !(func->flags & IR_FLAG_MASK_NO_OVERLAP)) + if (global->m_vtype == TYPE_FUNCTION) { + ir_function *func = global->m_constval.vfunc; + if (func && self->m_max_locals < func->m_allocated_locals && + !(func->m_flags & IR_FLAG_MASK_NO_OVERLAP)) { - self->max_locals = func->allocated_locals; + self->m_max_locals = func->m_allocated_locals; } - if (func && self->max_globaltemps < func->globaltemps) - self->max_globaltemps = func->globaltemps; + if (func && self->m_max_globaltemps < func->m_globaltemps) + self->m_max_globaltemps = func->m_globaltemps; } } - for (i = 0; i < vec_size(self->fields); ++i) - { - if (!ir_builder_gen_field(self, self->fields[i])) { + for (auto& fp : self->m_fields) { + if (!ir_builder_gen_field(self, fp.get())) return false; - } } - /* generate nil */ - ir_value_code_setaddr(self->nil, self->code->globals.size()); - self->code->globals.push_back(0); - self->code->globals.push_back(0); - self->code->globals.push_back(0); - - /* generate virtual-instruction temps */ - for (i = 0; i < IR_MAX_VINSTR_TEMPS; ++i) { - ir_value_code_setaddr(self->vinstr_temp[i], self->code->globals.size()); - self->code->globals.push_back(0); - self->code->globals.push_back(0); - self->code->globals.push_back(0); - } - - /* generate global temps */ - self->first_common_globaltemp = self->code->globals.size(); - for (i = 0; i < self->max_globaltemps; ++i) { - self->code->globals.push_back(0); - } - /* generate common locals */ - self->first_common_local = self->code->globals.size(); - for (i = 0; i < self->max_locals; ++i) { - self->code->globals.push_back(0); - } - - /* generate function code */ - for (i = 0; i < vec_size(self->globals); ++i) - { - if (self->globals[i]->vtype == TYPE_FUNCTION) { - if (!gen_global_function_code(self, self->globals[i])) { + // generate nil + ir_value_code_setaddr(self->m_nil, self->m_code->globals.size()); + self->m_code->globals.push_back(0); + self->m_code->globals.push_back(0); + self->m_code->globals.push_back(0); + + // generate virtual-instruction temps + for (size_t i = 0; i < IR_MAX_VINSTR_TEMPS; ++i) { + ir_value_code_setaddr(self->m_vinstr_temp[i], self->m_code->globals.size()); + self->m_code->globals.push_back(0); + self->m_code->globals.push_back(0); + self->m_code->globals.push_back(0); + } + + // generate global temps + self->m_first_common_globaltemp = self->m_code->globals.size(); + self->m_code->globals.insert(self->m_code->globals.end(), self->m_max_globaltemps, 0); + // FIXME:DELME: + //for (size_t i = 0; i < self->m_max_globaltemps; ++i) { + // self->m_code->globals.push_back(0); + //} + // generate common locals + self->m_first_common_local = self->m_code->globals.size(); + self->m_code->globals.insert(self->m_code->globals.end(), self->m_max_locals, 0); + // FIXME:DELME: + //for (i = 0; i < self->m_max_locals; ++i) { + // self->m_code->globals.push_back(0); + //} + + // generate function code + + for (auto& gp : self->m_globals) { + ir_value *global = gp.get(); + if (global->m_vtype == TYPE_FUNCTION) { + if (!gen_global_function_code(self, global)) { return false; } } } - if (self->code->globals.size() >= 65536) { - irerror(vec_last(self->globals)->context, + if (self->m_code->globals.size() >= 65536) { + irerror(self->m_globals.back()->m_context, "This progs file would require more globals than the metadata can handle (%zu). Bailing out.", - self->code->globals.size()); + self->m_code->globals.size()); return false; } /* DP errors if the last instruction is not an INSTR_DONE. */ - if (self->code->statements.back().opcode != INSTR_DONE) + if (self->m_code->statements.back().opcode != INSTR_DONE) { lex_ctx_t last; @@ -4041,19 +3777,19 @@ bool ir_builder_generate(ir_builder *self, const char *filename) stmt.o1.u1 = 0; stmt.o2.u1 = 0; stmt.o3.u1 = 0; - last.line = self->code->linenums.back(); - last.column = self->code->columnnums.back(); + last.line = self->m_code->linenums.back(); + last.column = self->m_code->columnnums.back(); - code_push_statement(self->code, &stmt, last); + code_push_statement(self->m_code.get(), &stmt, last); } if (OPTS_OPTION_BOOL(OPTION_PP_ONLY)) return true; - if (self->code->statements.size() != self->code->linenums.size()) { + if (self->m_code->statements.size() != self->m_code->linenums.size()) { con_err("Linecounter wrong: %lu != %lu\n", - self->code->statements.size(), - self->code->linenums.size()); + self->m_code->statements.size(), + self->m_code->linenums.size()); } else if (OPTS_FLAG(LNO)) { char *dot; size_t filelen = strlen(filename); @@ -4068,7 +3804,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename) memcpy(vec_add(lnofile, 5), ".lno", 5); } - if (!code_write(self->code, filename, lnofile)) { + if (!code_write(self->m_code.get(), filename, lnofile)) { vec_free(lnofile); return false; } @@ -4114,18 +3850,18 @@ void ir_builder_dump(ir_builder *b, int (*oprintf)(const char*, ...)) indent[0] = '\t'; indent[1] = 0; - oprintf("module %s\n", b->name); - for (i = 0; i < vec_size(b->globals); ++i) + oprintf("module %s\n", b->m_name.c_str()); + for (i = 0; i < b->m_globals.size(); ++i) { oprintf("global "); - if (b->globals[i]->hasvalue) - oprintf("%s = ", b->globals[i]->name); - ir_value_dump(b->globals[i], oprintf); + if (b->m_globals[i]->m_hasvalue) + oprintf("%s = ", b->m_globals[i]->m_name.c_str()); + ir_value_dump(b->m_globals[i].get(), oprintf); oprintf("\n"); } - for (i = 0; i < vec_size(b->functions); ++i) - ir_function_dump(b->functions[i], indent, oprintf); - oprintf("endmodule %s\n", b->name); + for (i = 0; i < b->m_functions.size(); ++i) + ir_function_dump(b->m_functions[i].get(), indent, oprintf); + oprintf("endmodule %s\n", b->m_name.c_str()); } static const char *storenames[] = { @@ -4136,122 +3872,122 @@ void ir_function_dump(ir_function *f, char *ind, int (*oprintf)(const char*, ...)) { size_t i; - if (f->builtin != 0) { - oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin); + if (f->m_builtin != 0) { + oprintf("%sfunction %s = builtin %i\n", ind, f->m_name.c_str(), -f->m_builtin); return; } - oprintf("%sfunction %s\n", ind, f->name); + oprintf("%sfunction %s\n", ind, f->m_name.c_str()); util_strncat(ind, "\t", IND_BUFSZ-1); - if (vec_size(f->locals)) + if (f->m_locals.size()) { - oprintf("%s%i locals:\n", ind, (int)vec_size(f->locals)); - for (i = 0; i < vec_size(f->locals); ++i) { + oprintf("%s%i locals:\n", ind, (int)f->m_locals.size()); + for (i = 0; i < f->m_locals.size(); ++i) { oprintf("%s\t", ind); - ir_value_dump(f->locals[i], oprintf); + ir_value_dump(f->m_locals[i].get(), oprintf); oprintf("\n"); } } oprintf("%sliferanges:\n", ind); - for (i = 0; i < vec_size(f->locals); ++i) { + for (i = 0; i < f->m_locals.size(); ++i) { const char *attr = ""; size_t l, m; - ir_value *v = f->locals[i]; - if (v->unique_life && v->locked) + ir_value *v = f->m_locals[i].get(); + if (v->m_unique_life && v->m_locked) attr = "unique,locked "; - else if (v->unique_life) + else if (v->m_unique_life) attr = "unique "; - else if (v->locked) + else if (v->m_locked) attr = "locked "; - oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype], - storenames[v->store], - attr, (v->callparam ? "callparam " : ""), - (int)v->code.local); - if (!v->life) + oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->m_name.c_str(), type_name[v->m_vtype], + storenames[v->m_store], + attr, (v->m_callparam ? "callparam " : ""), + (int)v->m_code.local); + if (v->m_life.empty()) oprintf("[null]"); - for (l = 0; l < vec_size(v->life); ++l) { - oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); + for (l = 0; l < v->m_life.size(); ++l) { + oprintf("[%i,%i] ", v->m_life[l].start, v->m_life[l].end); } oprintf("\n"); for (m = 0; m < 3; ++m) { - ir_value *vm = v->members[m]; + ir_value *vm = v->m_members[m]; if (!vm) continue; - oprintf("%s\t%s: @%i ", ind, vm->name, (int)vm->code.local); - for (l = 0; l < vec_size(vm->life); ++l) { - oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end); + oprintf("%s\t%s: @%i ", ind, vm->m_name.c_str(), (int)vm->m_code.local); + for (l = 0; l < vm->m_life.size(); ++l) { + oprintf("[%i,%i] ", vm->m_life[l].start, vm->m_life[l].end); } oprintf("\n"); } } - for (i = 0; i < vec_size(f->values); ++i) { + for (i = 0; i < f->m_values.size(); ++i) { const char *attr = ""; size_t l, m; - ir_value *v = f->values[i]; - if (v->unique_life && v->locked) + ir_value *v = f->m_values[i].get(); + if (v->m_unique_life && v->m_locked) attr = "unique,locked "; - else if (v->unique_life) + else if (v->m_unique_life) attr = "unique "; - else if (v->locked) + else if (v->m_locked) attr = "locked "; - oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype], - storenames[v->store], - attr, (v->callparam ? "callparam " : ""), - (int)v->code.local); - if (!v->life) + oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->m_name.c_str(), type_name[v->m_vtype], + storenames[v->m_store], + attr, (v->m_callparam ? "callparam " : ""), + (int)v->m_code.local); + if (v->m_life.empty()) oprintf("[null]"); - for (l = 0; l < vec_size(v->life); ++l) { - oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); + for (l = 0; l < v->m_life.size(); ++l) { + oprintf("[%i,%i] ", v->m_life[l].start, v->m_life[l].end); } oprintf("\n"); for (m = 0; m < 3; ++m) { - ir_value *vm = v->members[m]; + ir_value *vm = v->m_members[m]; if (!vm) continue; - if (vm->unique_life && vm->locked) + if (vm->m_unique_life && vm->m_locked) attr = "unique,locked "; - else if (vm->unique_life) + else if (vm->m_unique_life) attr = "unique "; - else if (vm->locked) + else if (vm->m_locked) attr = "locked "; - oprintf("%s\t%s: %s@%i ", ind, vm->name, attr, (int)vm->code.local); - for (l = 0; l < vec_size(vm->life); ++l) { - oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end); + oprintf("%s\t%s: %s@%i ", ind, vm->m_name.c_str(), attr, (int)vm->m_code.local); + for (l = 0; l < vm->m_life.size(); ++l) { + oprintf("[%i,%i] ", vm->m_life[l].start, vm->m_life[l].end); } oprintf("\n"); } } - if (vec_size(f->blocks)) + if (f->m_blocks.size()) { - oprintf("%slife passes: %i\n", ind, (int)f->run_id); - for (i = 0; i < vec_size(f->blocks); ++i) { - ir_block_dump(f->blocks[i], ind, oprintf); + oprintf("%slife passes: %i\n", ind, (int)f->m_run_id); + for (i = 0; i < f->m_blocks.size(); ++i) { + ir_block_dump(f->m_blocks[i].get(), ind, oprintf); } } ind[strlen(ind)-1] = 0; - oprintf("%sendfunction %s\n", ind, f->name); + oprintf("%sendfunction %s\n", ind, f->m_name.c_str()); } void ir_block_dump(ir_block* b, char *ind, int (*oprintf)(const char*, ...)) { size_t i; - oprintf("%s:%s\n", ind, b->label); + oprintf("%s:%s\n", ind, b->m_label.c_str()); util_strncat(ind, "\t", IND_BUFSZ-1); - if (b->instr && b->instr[0]) - oprintf("%s (%i) [entry]\n", ind, (int)(b->instr[0]->eid-1)); - for (i = 0; i < vec_size(b->instr); ++i) - ir_instr_dump(b->instr[i], ind, oprintf); + if (b->m_instr && b->m_instr[0]) + oprintf("%s (%i) [entry]\n", ind, (int)(b->m_instr[0]->m_eid-1)); + for (i = 0; i < vec_size(b->m_instr); ++i) + ir_instr_dump(b->m_instr[i], ind, oprintf); ind[strlen(ind)-1] = 0; } static void dump_phi(ir_instr *in, int (*oprintf)(const char*, ...)) { - oprintf("%s <- phi ", in->_ops[0]->name); - for (auto &it : in->phi) { - oprintf("([%s] : %s) ", it.from->label, - it.value->name); + oprintf("%s <- phi ", in->_m_ops[0]->m_name.c_str()); + for (auto &it : in->m_phi) { + oprintf("([%s] : %s) ", it.from->m_label.c_str(), + it.value->m_name.c_str()); } oprintf("\n"); } @@ -4262,52 +3998,52 @@ void ir_instr_dump(ir_instr *in, char *ind, size_t i; const char *comma = nullptr; - oprintf("%s (%i) ", ind, (int)in->eid); + oprintf("%s (%i) ", ind, (int)in->m_eid); - if (in->opcode == VINSTR_PHI) { + if (in->m_opcode == VINSTR_PHI) { dump_phi(in, oprintf); return; } util_strncat(ind, "\t", IND_BUFSZ-1); - if (in->_ops[0] && (in->_ops[1] || in->_ops[2])) { - ir_value_dump(in->_ops[0], oprintf); - if (in->_ops[1] || in->_ops[2]) + if (in->_m_ops[0] && (in->_m_ops[1] || in->_m_ops[2])) { + ir_value_dump(in->_m_ops[0], oprintf); + if (in->_m_ops[1] || in->_m_ops[2]) oprintf(" <- "); } - if (in->opcode == INSTR_CALL0 || in->opcode == VINSTR_NRCALL) { - oprintf("CALL%i\t", in->params.size()); + if (in->m_opcode == INSTR_CALL0 || in->m_opcode == VINSTR_NRCALL) { + oprintf("CALL%i\t", in->m_params.size()); } else - oprintf("%s\t", qc_opname(in->opcode)); + oprintf("%s\t", qc_opname(in->m_opcode)); - if (in->_ops[0] && !(in->_ops[1] || in->_ops[2])) { - ir_value_dump(in->_ops[0], oprintf); + if (in->_m_ops[0] && !(in->_m_ops[1] || in->_m_ops[2])) { + ir_value_dump(in->_m_ops[0], oprintf); comma = ",\t"; } else { for (i = 1; i != 3; ++i) { - if (in->_ops[i]) { + if (in->_m_ops[i]) { if (comma) oprintf(comma); - ir_value_dump(in->_ops[i], oprintf); + ir_value_dump(in->_m_ops[i], oprintf); comma = ",\t"; } } } - if (in->bops[0]) { + if (in->m_bops[0]) { if (comma) oprintf(comma); - oprintf("[%s]", in->bops[0]->label); + oprintf("[%s]", in->m_bops[0]->m_label.c_str()); comma = ",\t"; } - if (in->bops[1]) - oprintf("%s[%s]", comma, in->bops[1]->label); - if (in->params.size()) { + if (in->m_bops[1]) + oprintf("%s[%s]", comma, in->m_bops[1]->m_label.c_str()); + if (in->m_params.size()) { oprintf("\tparams: "); - for (auto &it : in->params) - oprintf("%s, ", it->name); + for (auto &it : in->m_params) + oprintf("%s, ", it->m_name.c_str()); } oprintf("\n"); ind[strlen(ind)-1] = 0; @@ -4335,51 +4071,50 @@ static void ir_value_dump_string(const char *str, int (*oprintf)(const char*, .. void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...)) { - if (v->hasvalue) { - switch (v->vtype) { + if (v->m_hasvalue) { + switch (v->m_vtype) { default: case TYPE_VOID: oprintf("(void)"); break; case TYPE_FUNCTION: - oprintf("fn:%s", v->name); + oprintf("fn:%s", v->m_name.c_str()); break; case TYPE_FLOAT: - oprintf("%g", v->constval.vfloat); + oprintf("%g", v->m_constval.vfloat); break; case TYPE_VECTOR: oprintf("'%g %g %g'", - v->constval.vvec.x, - v->constval.vvec.y, - v->constval.vvec.z); + v->m_constval.vvec.x, + v->m_constval.vvec.y, + v->m_constval.vvec.z); break; case TYPE_ENTITY: oprintf("(entity)"); break; case TYPE_STRING: - ir_value_dump_string(v->constval.vstring, oprintf); + ir_value_dump_string(v->m_constval.vstring, oprintf); break; #if 0 case TYPE_INTEGER: - oprintf("%i", v->constval.vint); + oprintf("%i", v->m_constval.vint); break; #endif case TYPE_POINTER: oprintf("&%s", - v->constval.vpointer->name); + v->m_constval.vpointer->m_name.c_str()); break; } } else { - oprintf("%s", v->name); + oprintf("%s", v->m_name.c_str()); } } void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...)) { - size_t i; - oprintf("Life of %12s:", self->name); - for (i = 0; i < vec_size(self->life); ++i) + oprintf("Life of %12s:", self->m_name.c_str()); + for (size_t i = 0; i < self->m_life.size(); ++i) { - oprintf(" + [%i, %i]\n", self->life[i].start, self->life[i].end); + oprintf(" + [%i, %i]\n", self->m_life[i].start, self->m_life[i].end); } } diff --git a/ir.h b/ir.h index 6dcbd5a..7964b74 100644 --- a/ir.h +++ b/ir.h @@ -36,29 +36,33 @@ enum { }; struct ir_value { - char *name; - int vtype; - int store; - lex_ctx_t context; - int fieldtype; // even the IR knows the subtype of a field - int outtype; // and the output type of a function - int cvq; // 'const' vs 'var' qualifier - ir_flag_t flags; - - std::vector reads; - std::vector writes; + ir_value(std::string&& name, store_type storetype, qc_type vtype); + ~ir_value(); + + std::string m_name; + + qc_type m_vtype; + store_type m_store; + lex_ctx_t m_context; + qc_type m_fieldtype; // even the IR knows the subtype of a field + qc_type m_outtype; // and the output type of a function + int m_cvq; // 'const' vs 'var' qualifier + ir_flag_t m_flags; + + std::vector m_reads; + std::vector m_writes; // constant values - bool hasvalue; + bool m_hasvalue; union { - qcfloat_t vfloat; - int vint; - vec3_t vvec; - int32_t ivec[3]; - char *vstring; - ir_value *vpointer; + qcfloat_t vfloat; + int vint; + vec3_t vvec; + int32_t ivec[3]; + char *vstring; + ir_value *vpointer; ir_function *vfunc; - } constval; + } m_constval; struct { int32_t globaladdr; @@ -66,17 +70,17 @@ struct ir_value { int32_t local; // filled by the local-allocator int32_t addroffset; // added for members int32_t fieldaddr; // to generate field-addresses early - } code; + } m_code; // for accessing vectors - ir_value *members[3]; - ir_value *memberof; + ir_value *m_members[3]; + ir_value *m_memberof; - bool unique_life; // arrays will never overlap with temps - bool locked; // temps living during a CALL must be locked - bool callparam; + bool m_unique_life; // arrays will never overlap with temps + bool m_locked; // temps living during a CALL must be locked + bool m_callparam; - ir_life_entry_t *life; // For the temp allocator + std::vector m_life; // For the temp allocator }; /* @@ -84,7 +88,6 @@ struct ir_value { * if a result of an operation: the function should store * it to remember to delete it / garbage collect it */ -void ir_value_delete(ir_value*); ir_value* ir_value_vector_member(ir_value*, unsigned int member); bool GMQCC_WARN ir_value_set_float(ir_value*, float f); bool GMQCC_WARN ir_value_set_func(ir_value*, int f); @@ -102,57 +105,63 @@ struct ir_phi_entry_t { /* instruction */ struct ir_instr { - int opcode; - lex_ctx_t context; - ir_value *(_ops[3]); - ir_block *(bops[2]); + ir_instr(lex_ctx_t, ir_block *owner, int opcode); + ~ir_instr(); - std::vector phi; - std::vector params; + int m_opcode; + lex_ctx_t m_context; + ir_value *(_m_ops[3]) = { nullptr, nullptr, nullptr }; + ir_block *(m_bops[2]) = { nullptr, nullptr }; + + std::vector m_phi; + std::vector m_params; // For the temp-allocation - size_t eid; + size_t m_eid = 0; // For IFs - bool likely; + bool m_likely = true; - ir_block *owner; + ir_block *m_owner; }; /* block */ struct ir_block { - char *label; - lex_ctx_t context; - bool final; /* once a jump is added we're done */ + ir_block(ir_function *owner, const std::string& name); + ~ir_block(); - ir_instr **instr; - ir_block **entries; - ir_block **exits; - std::vector living; + ir_function *m_owner; + std::string m_label; - /* For the temp-allocation */ - size_t entry_id; - size_t eid; - bool is_return; + lex_ctx_t m_context; + bool m_final = false; /* once a jump is added we're done */ - ir_function *owner; + ir_instr **m_instr = nullptr; + ir_block **m_entries = nullptr; + ir_block **m_exits = nullptr; + std::vector m_living; - bool generated; - size_t code_start; + /* For the temp-allocation */ + size_t m_entry_id = 0; + size_t m_eid = 0; + bool m_is_return = false; + + bool m_generated = false; + size_t m_code_start = 0; }; ir_value* ir_block_create_binop(ir_block*, lex_ctx_t, const char *label, int op, ir_value *left, ir_value *right); ir_value* ir_block_create_unary(ir_block*, lex_ctx_t, const char *label, int op, ir_value *operand); bool GMQCC_WARN ir_block_create_store_op(ir_block*, lex_ctx_t, int op, ir_value *target, ir_value *what); bool GMQCC_WARN ir_block_create_storep(ir_block*, lex_ctx_t, ir_value *target, ir_value *what); -ir_value* ir_block_create_load_from_ent(ir_block*, lex_ctx_t, const char *label, ir_value *ent, ir_value *field, int outype); +ir_value* ir_block_create_load_from_ent(ir_block*, lex_ctx_t, const char *label, ir_value *ent, ir_value *field, qc_type outype); ir_value* ir_block_create_fieldaddress(ir_block*, lex_ctx_t, const char *label, ir_value *entity, ir_value *field); bool GMQCC_WARN ir_block_create_state_op(ir_block*, lex_ctx_t, ir_value *frame, ir_value *think); /* This is to create an instruction of the form * %label := opcode a, b */ -ir_instr* ir_block_create_phi(ir_block*, lex_ctx_t, const char *label, int vtype); +ir_instr* ir_block_create_phi(ir_block*, lex_ctx_t, const char *label, qc_type vtype); ir_value* ir_phi_value(ir_instr*); void ir_phi_add(ir_instr*, ir_block *b, ir_value *v); ir_instr* ir_block_create_call(ir_block*, lex_ctx_t, const char *label, ir_value *func, bool noreturn); @@ -175,29 +184,35 @@ bool GMQCC_WARN ir_block_create_goto(ir_block*, lex_ctx_t, ir_block *to); /* function */ struct ir_function { - char *name; - int outtype; - int *params; - ir_block **blocks; - ir_flag_t flags; - int builtin; + ir_function(ir_builder *owner, qc_type returntype); + ~ir_function(); + + ir_builder *m_owner; + + std::string m_name; + qc_type m_outtype; + int *m_params = nullptr; + ir_flag_t m_flags = 0; + int m_builtin = 0; + + std::vector> m_blocks; /* * values generated from operations * which might get optimized away, so anything * in there needs to be deleted in the dtor. */ - ir_value **values; - ir_value **locals; /* locally defined variables */ - ir_value *value; + std::vector> m_values; + std::vector> m_locals; /* locally defined variables */ + ir_value *m_value = nullptr; - size_t allocated_locals; - size_t globaltemps; + size_t m_allocated_locals = 0; + size_t m_globaltemps = 0; - ir_block* first; - ir_block* last; + ir_block* m_first = nullptr; + ir_block* m_last = nullptr; - lex_ctx_t context; + lex_ctx_t m_context; /* * for prototypes - first we generate all the @@ -206,19 +221,17 @@ struct ir_function { * * remember the ID: */ - qcint_t code_function_def; + qcint_t m_code_function_def = -1; /* for temp allocation */ - size_t run_id; - - ir_builder *owner; + size_t m_run_id = 0; /* vararg support: */ - size_t max_varargs; + size_t m_max_varargs = 0; }; -ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param); +ir_value* ir_function_create_local(ir_function *self, const std::string& name, qc_type vtype, bool param); bool GMQCC_WARN ir_function_finalize(ir_function*); ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function*, const char *label); @@ -227,47 +240,53 @@ ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function*, const char #define IR_MAX_VINSTR_TEMPS 1 struct ir_builder { - char *name; - ir_function **functions; - ir_value **globals; - ir_value **fields; - ir_value **const_floats; /* for reusing them in vector-splits, TODO: sort this or use a radix-tree */ - - ht htfunctions; - ht htglobals; - ht htfields; - - ir_value **extparams; - ir_value **extparam_protos; - - /* the highest func->allocated_locals */ - size_t max_locals; - size_t max_globaltemps; - uint32_t first_common_local; - uint32_t first_common_globaltemp; - - const char **filenames; - qcint_t *filestrings; - /* we cache the #IMMEDIATE string here */ - qcint_t str_immediate; - /* there should just be this one nil */ - ir_value *nil; - ir_value *reserved_va_count; - ir_value *coverage_func; + ir_builder(const std::string& modulename); + ~ir_builder(); + + std::string m_name; + std::vector> m_functions; + std::vector> m_globals; + std::vector> m_fields; + // for reusing them in vector-splits, TODO: sort this or use a radix-tree + std::vector m_const_floats; + + ht m_htfunctions; + ht m_htglobals; + ht m_htfields; + + // extparams' ir_values reference the ones from extparam_protos + std::vector> m_extparam_protos; + std::vector m_extparams; + + // the highest func->allocated_locals + size_t m_max_locals = 0; + size_t m_max_globaltemps = 0; + uint32_t m_first_common_local = 0; + uint32_t m_first_common_globaltemp = 0; + + std::vector m_filenames; + std::vector m_filestrings; + + // we cache the #IMMEDIATE string here + qcint_t m_str_immediate = 0; + + // there should just be this one nil + ir_value *m_nil; + ir_value *m_reserved_va_count = nullptr; + ir_value *m_coverage_func = nullptr; + /* some virtual instructions require temps, and their code is isolated * so that we don't need to keep track of their liveness. */ - ir_value *vinstr_temp[IR_MAX_VINSTR_TEMPS]; + ir_value *m_vinstr_temp[IR_MAX_VINSTR_TEMPS]; /* code generator */ - code_t *code; + std::unique_ptr m_code; }; -ir_builder* ir_builder_new(const char *modulename); -void ir_builder_delete(ir_builder*); -ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype); -ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype); -ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype); +ir_function* ir_builder_create_function(ir_builder*, const std::string& name, qc_type outtype); +ir_value* ir_builder_create_global(ir_builder*, const std::string& name, qc_type vtype); +ir_value* ir_builder_create_field(ir_builder*, const std::string& name, qc_type vtype); ir_value* ir_builder_get_va_count(ir_builder*); bool ir_builder_generate(ir_builder *self, const char *filename); void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...)); diff --git a/lexer.cpp b/lexer.cpp index 79ad182..34fc71b 100644 --- a/lexer.cpp +++ b/lexer.cpp @@ -65,7 +65,7 @@ static void lex_token_new(lex_file *lex) if (lex->tok.value) vec_shrinkto(lex->tok.value, 0); - lex->tok.constval.t = 0; + lex->tok.constval.t = TYPE_VOID; lex->tok.ctx.line = lex->sline; lex->tok.ctx.file = lex->name; lex->tok.ctx.column = lex->column; diff --git a/lexer.h b/lexer.h index dc180f0..8ed85a9 100644 --- a/lexer.h +++ b/lexer.h @@ -9,7 +9,7 @@ struct token { vec3_t v; int i; qcfloat_t f; - int t; /* type */ + qc_type t; /* type */ } constval; lex_ctx_t ctx; }; diff --git a/parser.cpp b/parser.cpp index 631adf6..fcb782c 100644 --- a/parser.cpp +++ b/parser.cpp @@ -84,7 +84,7 @@ static ast_expression* parser_find_field(parser_t *parser, const char *name) static ast_expression* parser_find_label(parser_t *parser, const char *name) { for (auto &it : parser->labels) - if (!strcmp(it->name, name)) + if (!strcmp(it->m_name, name)) return (ast_expression*)it; return nullptr; } @@ -102,9 +102,9 @@ static ast_expression* parser_find_param(parser_t *parser, const char *name) ast_value *fun; if (!parser->function) return nullptr; - fun = parser->function->vtype; - for (auto &it : fun->expression.params) { - if (!strcmp(it->name, name)) + fun = parser->function->m_function_type; + for (auto &it : fun->m_type_params) { + if (!strcmp(it->m_name, name)) return (ast_expression*)it; } return nullptr; @@ -230,22 +230,22 @@ static bool rotate_entfield_array_index_nodes(ast_expression **out) ast_expression *sub; ast_expression *entity; - lex_ctx_t ctx = ast_ctx(*out); + lex_ctx_t ctx = (*out)->m_context; if (!ast_istype(*out, ast_array_index)) return false; index = (ast_array_index*)*out; - if (!ast_istype(index->array, ast_entfield)) + if (!ast_istype(index->m_array, ast_entfield)) return false; - entfield = (ast_entfield*)index->array; + entfield = (ast_entfield*)index->m_array; - if (!ast_istype(entfield->field, ast_value)) + if (!ast_istype(entfield->m_field, ast_value)) return false; - field = (ast_value*)entfield->field; + field = (ast_value*)entfield->m_field; - sub = index->index; - entity = entfield->entity; + sub = index->m_index; + entity = entfield->m_entity; oldindex = index; @@ -253,8 +253,8 @@ static bool rotate_entfield_array_index_nodes(ast_expression **out) entfield = ast_entfield_new(ctx, entity, (ast_expression*)index); *out = (ast_expression*)entfield; - oldindex->array = nullptr; - oldindex->index = nullptr; + oldindex->m_array = nullptr; + oldindex->m_index = nullptr; ast_delete(oldindex); return true; @@ -264,8 +264,8 @@ static bool check_write_to(lex_ctx_t ctx, ast_expression *expr) { if (ast_istype(expr, ast_value)) { ast_value *val = (ast_value*)expr; - if (val->cvq == CV_CONST) { - if (val->name[0] == '#') { + if (val->m_cvq == CV_CONST) { + if (val->m_name[0] == '#') { compile_error(ctx, "invalid assignment to a literal constant"); return false; } @@ -274,9 +274,9 @@ static bool check_write_to(lex_ctx_t ctx, ast_expression *expr) * a warning instead. */ if (OPTS_OPTION_U32(OPTION_STANDARD) != COMPILER_QCC) - compile_error(ctx, "assignment to constant `%s`", val->name); + compile_error(ctx, "assignment to constant `%s`", val->m_name); else - (void)!compile_warning(ctx, WARN_CONST_OVERWRITE, "assignment to constant `%s`", val->name); + (void)!compile_warning(ctx, WARN_CONST_OVERWRITE, "assignment to constant `%s`", val->m_name); return false; } } @@ -329,26 +329,26 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) exprs[i] = sy->out[sy->out.size()+i].out; blocks[i] = sy->out[sy->out.size()+i].block; - if (exprs[i]->vtype == TYPE_NOEXPR && + if (exprs[i]->m_vtype == TYPE_NOEXPR && !(i != 0 && op->id == opid2('?',':')) && !(i == 1 && op->id == opid1('.'))) { if (ast_istype(exprs[i], ast_label)) - compile_error(ast_ctx(exprs[i]), "expected expression, got an unknown identifier"); + compile_error(exprs[i]->m_context, "expected expression, got an unknown identifier"); else - compile_error(ast_ctx(exprs[i]), "not an expression"); - (void)!compile_warning(ast_ctx(exprs[i]), WARN_DEBUG, "expression %u\n", (unsigned int)i); + compile_error(exprs[i]->m_context, "not an expression"); + (void)!compile_warning(exprs[i]->m_context, WARN_DEBUG, "expression %u\n", (unsigned int)i); } } - if (blocks[0] && blocks[0]->exprs.empty() && op->id != opid1(',')) { + if (blocks[0] && blocks[0]->m_exprs.empty() && op->id != opid1(',')) { compile_error(ctx, "internal error: operator cannot be applied on empty blocks"); return false; } #define NotSameType(T) \ - (exprs[0]->vtype != exprs[1]->vtype || \ - exprs[0]->vtype != T) + (exprs[0]->m_vtype != exprs[1]->m_vtype || \ + exprs[0]->m_vtype != T) switch (op->id) { @@ -357,8 +357,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; case opid1('.'): - if (exprs[0]->vtype == TYPE_VECTOR && - exprs[1]->vtype == TYPE_NOEXPR) + if (exprs[0]->m_vtype == TYPE_VECTOR && + exprs[1]->m_vtype == TYPE_NOEXPR) { if (exprs[1] == (ast_expression*)parser->const_vec[0]) out = (ast_expression*)ast_member_new(ctx, exprs[0], 0, nullptr); @@ -371,35 +371,35 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } } - else if (exprs[0]->vtype == TYPE_ENTITY) { - if (exprs[1]->vtype != TYPE_FIELD) { - compile_error(ast_ctx(exprs[1]), "type error: right hand of member-operand should be an entity-field"); + else if (exprs[0]->m_vtype == TYPE_ENTITY) { + if (exprs[1]->m_vtype != TYPE_FIELD) { + compile_error(exprs[1]->m_context, "type error: right hand of member-operand should be an entity-field"); return false; } out = (ast_expression*)ast_entfield_new(ctx, exprs[0], exprs[1]); } - else if (exprs[0]->vtype == TYPE_VECTOR) { - compile_error(ast_ctx(exprs[1]), "vectors cannot be accessed this way"); + else if (exprs[0]->m_vtype == TYPE_VECTOR) { + compile_error(exprs[1]->m_context, "vectors cannot be accessed this way"); return false; } else { - compile_error(ast_ctx(exprs[1]), "type error: member-of operator on something that is not an entity or vector"); + compile_error(exprs[1]->m_context, "type error: member-of operator on something that is not an entity or vector"); return false; } break; case opid1('['): - if (exprs[0]->vtype != TYPE_ARRAY && - !(exprs[0]->vtype == TYPE_FIELD && - exprs[0]->next->vtype == TYPE_ARRAY)) + if (exprs[0]->m_vtype != TYPE_ARRAY && + !(exprs[0]->m_vtype == TYPE_FIELD && + exprs[0]->m_next->m_vtype == TYPE_ARRAY)) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - compile_error(ast_ctx(exprs[0]), "cannot index value of type %s", ty1); + compile_error(exprs[0]->m_context, "cannot index value of type %s", ty1); return false; } - if (exprs[1]->vtype != TYPE_FLOAT) { + if (exprs[1]->m_vtype != TYPE_FLOAT) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - compile_error(ast_ctx(exprs[1]), "index must be of type float, not %s", ty1); + compile_error(exprs[1]->m_context, "index must be of type float, not %s", ty1); return false; } out = (ast_expression*)ast_array_index_new(ctx, exprs[0], exprs[1]); @@ -436,13 +436,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if ((out = parser->m_fold.op(op, exprs))) break; - if (exprs[0]->vtype != TYPE_FLOAT && - exprs[0]->vtype != TYPE_VECTOR) { + if (exprs[0]->m_vtype != TYPE_FLOAT && + exprs[0]->m_vtype != TYPE_VECTOR) { compile_error(ctx, "invalid types used in unary expression: cannot negate type %s", - type_name[exprs[0]->vtype]); + type_name[exprs[0]->m_vtype]); return false; } - if (exprs[0]->vtype == TYPE_FLOAT) + if (exprs[0]->m_vtype == TYPE_FLOAT) out = (ast_expression*)ast_unary_new(ctx, VINSTR_NEG_F, exprs[0]); else out = (ast_expression*)ast_unary_new(ctx, VINSTR_NEG_V, exprs[0]); @@ -450,7 +450,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('!','P'): if (!(out = parser->m_fold.op(op, exprs))) { - switch (exprs[0]->vtype) { + switch (exprs[0]->m_vtype) { case TYPE_FLOAT: out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); break; @@ -472,23 +472,23 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; default: compile_error(ctx, "invalid types used in expression: cannot logically negate type %s", - type_name[exprs[0]->vtype]); + type_name[exprs[0]->m_vtype]); return false; } } break; case opid1('+'): - if (exprs[0]->vtype != exprs[1]->vtype || - (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) ) + if (exprs[0]->m_vtype != exprs[1]->m_vtype || + (exprs[0]->m_vtype != TYPE_VECTOR && exprs[0]->m_vtype != TYPE_FLOAT) ) { compile_error(ctx, "invalid types used in expression: cannot add type %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } if (!(out = parser->m_fold.op(op, exprs))) { - switch (exprs[0]->vtype) { + switch (exprs[0]->m_vtype) { case TYPE_FLOAT: out = fold::binary(ctx, INSTR_ADD_F, exprs[0], exprs[1]); break; @@ -497,23 +497,23 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; default: compile_error(ctx, "invalid types used in expression: cannot add type %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } } break; case opid1('-'): - if (exprs[0]->vtype != exprs[1]->vtype || - (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT)) + if (exprs[0]->m_vtype != exprs[1]->m_vtype || + (exprs[0]->m_vtype != TYPE_VECTOR && exprs[0]->m_vtype != TYPE_FLOAT)) { compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s", - type_name[exprs[1]->vtype], - type_name[exprs[0]->vtype]); + type_name[exprs[1]->m_vtype], + type_name[exprs[0]->m_vtype]); return false; } if (!(out = parser->m_fold.op(op, exprs))) { - switch (exprs[0]->vtype) { + switch (exprs[0]->m_vtype) { case TYPE_FLOAT: out = fold::binary(ctx, INSTR_SUB_F, exprs[0], exprs[1]); break; @@ -522,57 +522,57 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; default: compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s", - type_name[exprs[1]->vtype], - type_name[exprs[0]->vtype]); + type_name[exprs[1]->m_vtype], + type_name[exprs[0]->m_vtype]); return false; } } break; case opid1('*'): - if (exprs[0]->vtype != exprs[1]->vtype && - !(exprs[0]->vtype == TYPE_VECTOR && - exprs[1]->vtype == TYPE_FLOAT) && - !(exprs[1]->vtype == TYPE_VECTOR && - exprs[0]->vtype == TYPE_FLOAT) + if (exprs[0]->m_vtype != exprs[1]->m_vtype && + !(exprs[0]->m_vtype == TYPE_VECTOR && + exprs[1]->m_vtype == TYPE_FLOAT) && + !(exprs[1]->m_vtype == TYPE_VECTOR && + exprs[0]->m_vtype == TYPE_FLOAT) ) { compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s", - type_name[exprs[1]->vtype], - type_name[exprs[0]->vtype]); + type_name[exprs[1]->m_vtype], + type_name[exprs[0]->m_vtype]); return false; } if (!(out = parser->m_fold.op(op, exprs))) { - switch (exprs[0]->vtype) { + switch (exprs[0]->m_vtype) { case TYPE_FLOAT: - if (exprs[1]->vtype == TYPE_VECTOR) + if (exprs[1]->m_vtype == TYPE_VECTOR) out = fold::binary(ctx, INSTR_MUL_FV, exprs[0], exprs[1]); else out = fold::binary(ctx, INSTR_MUL_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: - if (exprs[1]->vtype == TYPE_FLOAT) + if (exprs[1]->m_vtype == TYPE_FLOAT) out = fold::binary(ctx, INSTR_MUL_VF, exprs[0], exprs[1]); else out = fold::binary(ctx, INSTR_MUL_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s", - type_name[exprs[1]->vtype], - type_name[exprs[0]->vtype]); + type_name[exprs[1]->m_vtype], + type_name[exprs[0]->m_vtype]); return false; } } break; case opid1('/'): - if (exprs[1]->vtype != TYPE_FLOAT) { + if (exprs[1]->m_vtype != TYPE_FLOAT) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2); return false; } if (!(out = parser->m_fold.op(op, exprs))) { - if (exprs[0]->vtype == TYPE_FLOAT) + if (exprs[0]->m_vtype == TYPE_FLOAT) out = fold::binary(ctx, INSTR_DIV_F, exprs[0], exprs[1]); else { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); @@ -586,8 +586,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid1('%'): if (NotSameType(TYPE_FLOAT)) { compile_error(ctx, "invalid types used in expression: cannot perform modulo operation between types %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } else if (!(out = parser->m_fold.op(op, exprs))) { /* generate a call to __builtin_mod */ @@ -596,8 +596,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (!mod) return false; /* can return null for missing floor */ call = ast_call_new(parser_ctx(parser), mod); - call->params.push_back(exprs[0]); - call->params.push_back(exprs[1]); + call->m_params.push_back(exprs[0]); + call->m_params.push_back(exprs[1]); out = (ast_expression*)call; } @@ -610,13 +610,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid1('|'): case opid1('&'): case opid1('^'): - if ( !(exprs[0]->vtype == TYPE_FLOAT && exprs[1]->vtype == TYPE_FLOAT) && - !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_FLOAT) && - !(exprs[0]->vtype == TYPE_VECTOR && exprs[1]->vtype == TYPE_VECTOR)) + if ( !(exprs[0]->m_vtype == TYPE_FLOAT && exprs[1]->m_vtype == TYPE_FLOAT) && + !(exprs[0]->m_vtype == TYPE_VECTOR && exprs[1]->m_vtype == TYPE_FLOAT) && + !(exprs[0]->m_vtype == TYPE_VECTOR && exprs[1]->m_vtype == TYPE_VECTOR)) { compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } @@ -625,7 +625,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * IF the first expression is float, the following will be too * since scalar ^ vector is not allowed. */ - if (exprs[0]->vtype == TYPE_FLOAT) { + if (exprs[0]->m_vtype == TYPE_FLOAT) { out = fold::binary(ctx, (op->id == opid1('^') ? VINSTR_BITXOR : op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND), exprs[0], exprs[1]); @@ -634,7 +634,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * The first is a vector: vector is allowed to bitop with vector and * with scalar, branch here for the second operand. */ - if (exprs[1]->vtype == TYPE_VECTOR) { + if (exprs[1]->m_vtype == TYPE_VECTOR) { /* * Bitop all the values of the vector components against the * vectors components in question. @@ -655,16 +655,16 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('>','>'): if (NotSameType(TYPE_FLOAT)) { compile_error(ctx, "invalid types used in expression: cannot perform shift between types %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } if (!(out = parser->m_fold.op(op, exprs))) { ast_expression *shift = parser->m_intrin.func((op->id == opid2('<','<')) ? "__builtin_lshift" : "__builtin_rshift"); ast_call *call = ast_call_new(parser_ctx(parser), shift); - call->params.push_back(exprs[0]); - call->params.push_back(exprs[1]); + call->m_params.push_back(exprs[0]); + call->m_params.push_back(exprs[1]); out = (ast_expression*)call; } break; @@ -673,16 +673,16 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid3('>','>','='): if (NotSameType(TYPE_FLOAT)) { compile_error(ctx, "invalid types used in expression: cannot perform shift operation between types %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } if(!(out = parser->m_fold.op(op, exprs))) { ast_expression *shift = parser->m_intrin.func((op->id == opid3('<','<','=')) ? "__builtin_lshift" : "__builtin_rshift"); ast_call *call = ast_call_new(parser_ctx(parser), shift); - call->params.push_back(exprs[0]); - call->params.push_back(exprs[1]); + call->m_params.push_back(exprs[0]); + call->m_params.push_back(exprs[1]); out = (ast_expression*)ast_store_new( parser_ctx(parser), INSTR_STORE_F, @@ -705,7 +705,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } for (i = 0; i < 2; ++i) { - if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->vtype == TYPE_VECTOR) { + if (OPTS_FLAG(CORRECT_LOGIC) && exprs[i]->m_vtype == TYPE_VECTOR) { out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]); if (!out) break; out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); @@ -716,7 +716,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; } } - else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->vtype == TYPE_STRING) { + else if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && exprs[i]->m_vtype == TYPE_STRING) { out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_S, exprs[i]); if (!out) break; out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out); @@ -759,8 +759,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (!(out = parser->m_fold.op(op, exprs))) { ast_call *gencall = ast_call_new(parser_ctx(parser), parser->m_intrin.func("pow")); - gencall->params.push_back(exprs[0]); - gencall->params.push_back(exprs[1]); + gencall->m_params.push_back(exprs[0]); + gencall->m_params.push_back(exprs[1]); out = (ast_expression*)gencall; } break; @@ -799,7 +799,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) /* This whole block is NOT fold_binary safe */ ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]); - eq->refs = AST_REF_NONE; + eq->m_refs = AST_REF_NONE; /* if (lt) { */ out = (ast_expression*)ast_ternary_new(ctx, @@ -832,52 +832,52 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) generated_op += INSTR_LE; if (NotSameType(TYPE_FLOAT)) { compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } if (!(out = parser->m_fold.op(op, exprs))) out = fold::binary(ctx, generated_op, exprs[0], exprs[1]); break; case opid2('!', '='): - if (exprs[0]->vtype != exprs[1]->vtype) { + if (exprs[0]->m_vtype != exprs[1]->m_vtype) { compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } if (!(out = parser->m_fold.op(op, exprs))) - out = fold::binary(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]); + out = fold::binary(ctx, type_ne_instr[exprs[0]->m_vtype], exprs[0], exprs[1]); break; case opid2('=', '='): - if (exprs[0]->vtype != exprs[1]->vtype) { + if (exprs[0]->m_vtype != exprs[1]->m_vtype) { compile_error(ctx, "invalid types used in expression: cannot perform comparison between types %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; } if (!(out = parser->m_fold.op(op, exprs))) - out = fold::binary(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]); + out = fold::binary(ctx, type_eq_instr[exprs[0]->m_vtype], exprs[0], exprs[1]); break; case opid1('='): if (ast_istype(exprs[0], ast_entfield)) { - ast_expression *field = ((ast_entfield*)exprs[0])->field; + ast_expression *field = ((ast_entfield*)exprs[0])->m_field; if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) && - exprs[0]->vtype == TYPE_FIELD && - exprs[0]->next->vtype == TYPE_VECTOR) + exprs[0]->m_vtype == TYPE_FIELD && + exprs[0]->m_next->m_vtype == TYPE_VECTOR) { assignop = type_storep_instr[TYPE_VECTOR]; } else - assignop = type_storep_instr[exprs[0]->vtype]; - if (assignop == VINSTR_END || !ast_compare_type(field->next, exprs[1])) + assignop = type_storep_instr[exprs[0]->m_vtype]; + if (assignop == VINSTR_END || !ast_compare_type(field->m_next, exprs[1])) { - ast_type_to_string(field->next, ty1, sizeof(ty1)); + ast_type_to_string(field->m_next, ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) && - field->next->vtype == TYPE_FUNCTION && - exprs[1]->vtype == TYPE_FUNCTION) + field->m_next->m_vtype == TYPE_FUNCTION && + exprs[1]->m_vtype == TYPE_FUNCTION) { (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES, "invalid types in assignment: cannot assign %s to %s", ty2, ty1); @@ -889,13 +889,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) else { if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) && - exprs[0]->vtype == TYPE_FIELD && - exprs[0]->next->vtype == TYPE_VECTOR) + exprs[0]->m_vtype == TYPE_FIELD && + exprs[0]->m_next->m_vtype == TYPE_VECTOR) { assignop = type_store_instr[TYPE_VECTOR]; } else { - assignop = type_store_instr[exprs[0]->vtype]; + assignop = type_store_instr[exprs[0]->m_vtype]; } if (assignop == VINSTR_END) { @@ -908,8 +908,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); if (OPTS_FLAG(ASSIGN_FUNCTION_TYPES) && - exprs[0]->vtype == TYPE_FUNCTION && - exprs[1]->vtype == TYPE_FUNCTION) + exprs[0]->m_vtype == TYPE_FUNCTION && + exprs[1]->m_vtype == TYPE_FUNCTION) { (void)!compile_warning(ctx, WARN_ASSIGN_FUNCTION_TYPES, "invalid types in assignment: cannot assign %s to %s", ty2, ty1); @@ -920,23 +920,23 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } (void)check_write_to(ctx, exprs[0]); /* When we're a vector of part of an entity field we use STOREP */ - if (ast_istype(exprs[0], ast_member) && ast_istype(((ast_member*)exprs[0])->owner, ast_entfield)) + if (ast_istype(exprs[0], ast_member) && ast_istype(((ast_member*)exprs[0])->m_owner, ast_entfield)) assignop = INSTR_STOREP_F; out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]); break; case opid3('+','+','P'): case opid3('-','-','P'): /* prefix ++ */ - if (exprs[0]->vtype != TYPE_FLOAT) { + if (exprs[0]->m_vtype != TYPE_FLOAT) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - compile_error(ast_ctx(exprs[0]), "invalid type for prefix increment: %s", ty1); + compile_error(exprs[0]->m_context, "invalid type for prefix increment: %s", ty1); return false; } if (op->id == opid3('+','+','P')) addop = INSTR_ADD_F; else addop = INSTR_SUB_F; - (void)check_write_to(ast_ctx(exprs[0]), exprs[0]); + (void)check_write_to(exprs[0]->m_context, exprs[0]); if (ast_istype(exprs[0], ast_entfield)) { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, exprs[0], @@ -950,9 +950,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid3('S','+','+'): case opid3('S','-','-'): /* prefix ++ */ - if (exprs[0]->vtype != TYPE_FLOAT) { + if (exprs[0]->m_vtype != TYPE_FLOAT) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - compile_error(ast_ctx(exprs[0]), "invalid type for suffix increment: %s", ty1); + compile_error(exprs[0]->m_context, "invalid type for suffix increment: %s", ty1); return false; } if (op->id == opid3('S','+','+')) { @@ -962,7 +962,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) addop = INSTR_SUB_F; subop = INSTR_ADD_F; } - (void)check_write_to(ast_ctx(exprs[0]), exprs[0]); + (void)check_write_to(exprs[0]->m_context, exprs[0]); if (ast_istype(exprs[0], ast_entfield)) { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, exprs[0], @@ -981,8 +981,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; case opid2('+','='): case opid2('-','='): - if (exprs[0]->vtype != exprs[1]->vtype || - (exprs[0]->vtype != TYPE_VECTOR && exprs[0]->vtype != TYPE_FLOAT) ) + if (exprs[0]->m_vtype != exprs[1]->m_vtype || + (exprs[0]->m_vtype != TYPE_VECTOR && exprs[0]->m_vtype != TYPE_FLOAT) ) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); @@ -992,10 +992,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } (void)check_write_to(ctx, exprs[0]); if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->vtype]; + assignop = type_storep_instr[exprs[0]->m_vtype]; else - assignop = type_store_instr[exprs[0]->vtype]; - switch (exprs[0]->vtype) { + assignop = type_store_instr[exprs[0]->m_vtype]; + switch (exprs[0]->m_vtype) { case TYPE_FLOAT: out = (ast_expression*)ast_binstore_new(ctx, assignop, (op->id == opid2('+','=') ? INSTR_ADD_F : INSTR_SUB_F), @@ -1008,16 +1008,16 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; default: compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; }; break; case opid2('*','='): case opid2('/','='): - if (exprs[1]->vtype != TYPE_FLOAT || - !(exprs[0]->vtype == TYPE_FLOAT || - exprs[0]->vtype == TYPE_VECTOR)) + if (exprs[1]->m_vtype != TYPE_FLOAT || + !(exprs[0]->m_vtype == TYPE_FLOAT || + exprs[0]->m_vtype == TYPE_VECTOR)) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); @@ -1027,10 +1027,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } (void)check_write_to(ctx, exprs[0]); if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->vtype]; + assignop = type_storep_instr[exprs[0]->m_vtype]; else - assignop = type_store_instr[exprs[0]->vtype]; - switch (exprs[0]->vtype) { + assignop = type_store_instr[exprs[0]->m_vtype]; + switch (exprs[0]->m_vtype) { case TYPE_FLOAT: out = (ast_expression*)ast_binstore_new(ctx, assignop, (op->id == opid2('*','=') ? INSTR_MUL_F : INSTR_DIV_F), @@ -1054,8 +1054,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; default: compile_error(ctx, "invalid types used in expression: cannot add or subtract type %s and %s", - type_name[exprs[0]->vtype], - type_name[exprs[1]->vtype]); + type_name[exprs[0]->m_vtype], + type_name[exprs[1]->m_vtype]); return false; }; break; @@ -1071,10 +1071,10 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } (void)check_write_to(ctx, exprs[0]); if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->vtype]; + assignop = type_storep_instr[exprs[0]->m_vtype]; else - assignop = type_store_instr[exprs[0]->vtype]; - if (exprs[0]->vtype == TYPE_FLOAT) + assignop = type_store_instr[exprs[0]->m_vtype]; + if (exprs[0]->m_vtype == TYPE_FLOAT) out = (ast_expression*)ast_binstore_new(ctx, assignop, (op->id == opid2('^','=') ? VINSTR_BITXOR : op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR), exprs[0], exprs[1]); @@ -1096,48 +1096,48 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } if (ast_istype(exprs[0], ast_entfield)) - assignop = type_storep_instr[exprs[0]->vtype]; + assignop = type_storep_instr[exprs[0]->m_vtype]; else - assignop = type_store_instr[exprs[0]->vtype]; - if (exprs[0]->vtype == TYPE_FLOAT) + assignop = type_store_instr[exprs[0]->m_vtype]; + if (exprs[0]->m_vtype == TYPE_FLOAT) out = fold::binary(ctx, INSTR_BITAND, exprs[0], exprs[1]); else out = fold::binary(ctx, VINSTR_BITAND_V, exprs[0], exprs[1]); if (!out) return false; (void)check_write_to(ctx, exprs[0]); - if (exprs[0]->vtype == TYPE_FLOAT) + if (exprs[0]->m_vtype == TYPE_FLOAT) asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out); else asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_V, exprs[0], out); - asbinstore->keep_dest = true; + asbinstore->m_keep_dest = true; out = (ast_expression*)asbinstore; break; case opid3('l', 'e', 'n'): - if (exprs[0]->vtype != TYPE_STRING && exprs[0]->vtype != TYPE_ARRAY) { + if (exprs[0]->m_vtype != TYPE_STRING && exprs[0]->m_vtype != TYPE_ARRAY) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - compile_error(ast_ctx(exprs[0]), "invalid type for length operator: %s", ty1); + compile_error(exprs[0]->m_context, "invalid type for length operator: %s", ty1); return false; } /* strings must be const, arrays are statically sized */ - if (exprs[0]->vtype == TYPE_STRING && - !(((ast_value*)exprs[0])->hasvalue && ((ast_value*)exprs[0])->cvq == CV_CONST)) + if (exprs[0]->m_vtype == TYPE_STRING && + !(((ast_value*)exprs[0])->m_hasvalue && ((ast_value*)exprs[0])->m_cvq == CV_CONST)) { - compile_error(ast_ctx(exprs[0]), "operand of length operator not a valid constant expression"); + compile_error(exprs[0]->m_context, "operand of length operator not a valid constant expression"); return false; } out = parser->m_fold.op(op, exprs); break; case opid2('~', 'P'): - if (exprs[0]->vtype != TYPE_FLOAT && exprs[0]->vtype != TYPE_VECTOR) { + if (exprs[0]->m_vtype != TYPE_FLOAT && exprs[0]->m_vtype != TYPE_VECTOR) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); - compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1); + compile_error(exprs[0]->m_context, "invalid type for bit not: %s", ty1); return false; } if (!(out = parser->m_fold.op(op, exprs))) { - if (exprs[0]->vtype == TYPE_FLOAT) { + if (exprs[0]->m_vtype == TYPE_FLOAT) { out = fold::binary(ctx, INSTR_SUB_F, (ast_expression*)parser->m_fold.imm_float(2), exprs[0]); } else { out = fold::binary(ctx, INSTR_SUB_V, (ast_expression*)parser->m_fold.imm_vector(1), exprs[0]); @@ -1200,7 +1200,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) } ast_type_to_string(sy->out.back().out, ty, sizeof(ty)); ast_unref(sy->out.back().out); - sy->out[fid] = syexp(ast_ctx(sy->out.back().out), + sy->out[fid] = syexp(sy->out.back().out->m_context, (ast_expression*)parser->m_fold.constgen_string(ty, false)); sy->out.pop_back(); return true; @@ -1212,8 +1212,8 @@ static bool parser_close_call(parser_t *parser, shunt *sy) * and than fruitfully fold them. */ #define fold_can_1(X) \ - (ast_istype(((ast_expression*)(X)), ast_value) && (X)->hasvalue && ((X)->cvq == CV_CONST) && \ - ((ast_expression*)(X))->vtype != TYPE_FUNCTION) + (ast_istype(((ast_expression*)(X)), ast_value) && (X)->m_hasvalue && ((X)->m_cvq == CV_CONST) && \ + ((ast_expression*)(X))->m_vtype != TYPE_FUNCTION) if (fid + 1 < sy->out.size()) ++paramcount; @@ -1229,7 +1229,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) * All is well which ends well, if we make it into here we can ignore the * intrinsic call and just evaluate it i.e constant fold it. */ - if (fold && ast_istype(fun, ast_value) && ((ast_value*)fun)->intrinsic) { + if (fold && ast_istype(fun, ast_value) && ((ast_value*)fun)->m_intrinsic) { ast_expression **exprs = nullptr; ast_expression *foldval = nullptr; @@ -1245,7 +1245,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) * Blub: what sorts of unreffing and resizing of * sy->out should I be doing here? */ - sy->out[fid] = syexp(foldval->node.context, foldval); + sy->out[fid] = syexp(foldval->m_context, foldval); sy->out.erase(sy->out.end() - paramcount, sy->out.end()); vec_free(exprs); @@ -1267,72 +1267,72 @@ static bool parser_close_call(parser_t *parser, shunt *sy) } for (i = 0; i < paramcount; ++i) - call->params.push_back(sy->out[fid+1 + i].out); + call->m_params.push_back(sy->out[fid+1 + i].out); sy->out.erase(sy->out.end() - paramcount, sy->out.end()); - (void)!ast_call_check_types(call, parser->function->vtype->expression.varparam); + (void)!ast_call_check_types(call, parser->function->m_function_type->m_varparam); if (parser->max_param_count < paramcount) parser->max_param_count = paramcount; if (ast_istype(fun, ast_value)) { funval = (ast_value*)fun; - if ((fun->flags & AST_FLAG_VARIADIC) && - !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin)) + if ((fun->m_flags & AST_FLAG_VARIADIC) && + !(/*funval->m_cvq == CV_CONST && */ funval->m_hasvalue && funval->m_constval.vfunc->m_builtin)) { - call->va_count = (ast_expression*)parser->m_fold.constgen_float((qcfloat_t)paramcount, false); + call->m_va_count = (ast_expression*)parser->m_fold.constgen_float((qcfloat_t)paramcount, false); } } /* overwrite fid, the function, with a call */ - sy->out[fid] = syexp(call->expression.node.context, (ast_expression*)call); + sy->out[fid] = syexp(call->m_context, (ast_expression*)call); - if (fun->vtype != TYPE_FUNCTION) { - parseerror(parser, "not a function (%s)", type_name[fun->vtype]); + if (fun->m_vtype != TYPE_FUNCTION) { + parseerror(parser, "not a function (%s)", type_name[fun->m_vtype]); return false; } - if (!fun->next) { + if (!fun->m_next) { parseerror(parser, "could not determine function return type"); return false; } else { ast_value *fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : nullptr); - if (fun->flags & AST_FLAG_DEPRECATED) { + if (fun->m_flags & AST_FLAG_DEPRECATED) { if (!fval) { return !parsewarning(parser, WARN_DEPRECATED, "call to function (which is marked deprecated)\n", "-> it has been declared here: %s:%i", - ast_ctx(fun).file, ast_ctx(fun).line); + fun->m_context.file, fun->m_context.line); } - if (!fval->desc) { + if (!fval->m_desc) { return !parsewarning(parser, WARN_DEPRECATED, "call to `%s` (which is marked deprecated)\n" "-> `%s` declared here: %s:%i", - fval->name, fval->name, ast_ctx(fun).file, ast_ctx(fun).line); + fval->m_name, fval->m_name, fun->m_context.file, fun->m_context.line); } return !parsewarning(parser, WARN_DEPRECATED, "call to `%s` (deprecated: %s)\n" "-> `%s` declared here: %s:%i", - fval->name, fval->desc, fval->name, ast_ctx(fun).file, - ast_ctx(fun).line); + fval->m_name, fval->m_desc, fval->m_name, fun->m_context.file, + fun->m_context.line); } - if (fun->params.size() != paramcount && - !((fun->flags & AST_FLAG_VARIADIC) && - fun->params.size() < paramcount)) + if (fun->m_type_params.size() != paramcount && + !((fun->m_flags & AST_FLAG_VARIADIC) && + fun->m_type_params.size() < paramcount)) { - const char *fewmany = (fun->params.size() > paramcount) ? "few" : "many"; + const char *fewmany = (fun->m_type_params.size() > paramcount) ? "few" : "many"; if (fval) return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT, "too %s parameters for call to %s: expected %i, got %i\n" " -> `%s` has been declared here: %s:%i", - fewmany, fval->name, (int)fun->params.size(), (int)paramcount, - fval->name, ast_ctx(fun).file, (int)ast_ctx(fun).line); + fewmany, fval->m_name, (int)fun->m_type_params.size(), (int)paramcount, + fval->m_name, fun->m_context.file, (int)fun->m_context.line); else return !parsewarning(parser, WARN_INVALID_PARAMETER_COUNT, "too %s parameters for function call: expected %i, got %i\n" " -> it has been declared here: %s:%i", - fewmany, (int)fun->params.size(), (int)paramcount, - ast_ctx(fun).file, (int)ast_ctx(fun).line); + fewmany, (int)fun->m_type_params.size(), (int)paramcount, + fun->m_context.file, (int)fun->m_context.line); } } @@ -1405,10 +1405,10 @@ static ast_expression* parse_vararg_do(parser_t *parser) { ast_expression *idx, *out; ast_value *typevar; - ast_value *funtype = parser->function->vtype; + ast_value *funtype = parser->function->m_function_type; lex_ctx_t ctx = parser_ctx(parser); - if (!parser->function->varargs) { + if (!parser->function->m_varargs) { parseerror(parser, "function has no variable argument list"); return nullptr; } @@ -1456,19 +1456,19 @@ static ast_expression* parse_vararg_do(parser_t *parser) return nullptr; } - if (funtype->expression.varparam && - !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam)) + if (funtype->m_varparam && + !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->m_varparam)) { char ty1[1024]; char ty2[1024]; ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1)); - ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2)); - compile_error(ast_ctx(typevar), + ast_type_to_string((ast_expression*)funtype->m_varparam, ty2, sizeof(ty2)); + compile_error(typevar->m_context, "function was declared to take varargs of type `%s`, requested type is: %s", ty2, ty1); } - out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->varargs), idx); + out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->m_varargs), idx); ast_type_adopt(out, typevar); ast_delete(typevar); return out; @@ -1573,7 +1573,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) /* When adding more intrinsics, fix the above condition */ prev = nullptr; } - if (prev && prev->vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1]) + if (prev && prev->m_vtype == TYPE_VECTOR && ctoken[0] >= 'x' && ctoken[0] <= 'z' && !ctoken[1]) { var = (ast_expression*)parser->const_vec[ctoken[0]-'x']; } else { @@ -1590,7 +1590,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) } } if (!var && !strcmp(parser_tokval(parser), "__FUNC__")) - var = (ast_expression*)parser->m_fold.constgen_string(parser->function->name, false); + var = (ast_expression*)parser->m_fold.constgen_string(parser->function->m_name, false); if (!var) { /* * now we try for the real intrinsic hashtable. If the string @@ -1636,12 +1636,12 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) else { if (ast_istype(var, ast_value)) { - ((ast_value*)var)->uses++; + ((ast_value*)var)->m_uses++; } else if (ast_istype(var, ast_member)) { ast_member *mem = (ast_member*)var; - if (ast_istype(mem->owner, ast_value)) - ((ast_value*)(mem->owner))->uses++; + if (ast_istype(mem->m_owner, ast_value)) + ((ast_value*)(mem->m_owner))->m_uses++; } } sy->out.push_back(syexp(parser_ctx(parser), var)); @@ -1889,11 +1889,11 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma ast_expression *lexpr = sy.out.back().out; if (ast_istype(lexpr, ast_value)) { ast_value *last = (ast_value*)lexpr; - if (last->isimm == true && last->cvq == CV_CONST && - last->hasvalue && last->expression.vtype == TYPE_STRING) + if (last->m_isimm == true && last->m_cvq == CV_CONST && + last->m_hasvalue && last->m_vtype == TYPE_STRING) { char *newstr = nullptr; - util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser)); + util_asprintf(&newstr, "%s%s", last->m_constval.vstring, parser_tokval(parser)); sy.out.back().out = (ast_expression*)parser->m_fold.constgen_string(newstr, false); mem_d(newstr); concatenated = true; @@ -1991,8 +1991,8 @@ static bool parser_leaveblock(parser_t *parser) ast_expression *e = vec_last(parser->_locals); ast_value *v = (ast_value*)e; vec_pop(parser->_locals); - if (ast_istype(e, ast_value) && !v->uses) { - if (compile_warning(ast_ctx(v), WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name)) + if (ast_istype(e, ast_value) && !v->m_uses) { + if (compile_warning(v->m_context, WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->m_name)) rv = false; } } @@ -2028,16 +2028,16 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, ast_unary *unary; ast_expression *prev; - if (cond->vtype == TYPE_VOID || cond->vtype >= TYPE_VARIANT) { + if (cond->m_vtype == TYPE_VOID || cond->m_vtype >= TYPE_VARIANT) { char ty[1024]; ast_type_to_string(cond, ty, sizeof(ty)); - compile_error(ast_ctx(cond), "invalid type for if() condition: %s", ty); + compile_error(cond->m_context, "invalid type for if() condition: %s", ty); } - if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->vtype == TYPE_STRING) + if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->m_vtype == TYPE_STRING) { prev = cond; - cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond); + cond = (ast_expression*)ast_unary_new(cond->m_context, INSTR_NOT_S, cond); if (!cond) { ast_unref(prev); parseerror(parser, "internal error: failed to process condition"); @@ -2045,15 +2045,15 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, } ifnot = !ifnot; } - else if (OPTS_FLAG(CORRECT_LOGIC) && cond->vtype == TYPE_VECTOR) + else if (OPTS_FLAG(CORRECT_LOGIC) && cond->m_vtype == TYPE_VECTOR) { /* vector types need to be cast to true booleans */ ast_binary *bin = (ast_binary*)cond; - if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR)) + if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->m_op == INSTR_AND || bin->m_op == INSTR_OR)) { /* in perl-logic, AND and OR take care of the -fcorrect-logic */ prev = cond; - cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond); + cond = (ast_expression*)ast_unary_new(cond->m_context, INSTR_NOT_V, cond); if (!cond) { ast_unref(prev); parseerror(parser, "internal error: failed to process condition"); @@ -2065,10 +2065,10 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, unary = (ast_unary*)cond; /* ast_istype dereferences cond, should test here for safety */ - while (cond && ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F) + while (cond && ast_istype(cond, ast_unary) && unary->m_op == INSTR_NOT_F) { - cond = unary->operand; - unary->operand = nullptr; + cond = unary->m_operand; + unary->m_operand = nullptr; ast_delete(unary); ifnot = !ifnot; unary = (ast_unary*)cond; @@ -2480,18 +2480,20 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou initexpr = parse_expression_leave(parser, false, false, false); if (!initexpr) goto onerr; - /* move on to condition */ if (parser->tok != ';') { parseerror(parser, "expected semicolon after for-loop initializer"); goto onerr; } - if (!parser_next(parser)) { parseerror(parser, "expected for-loop condition"); goto onerr; } } + else if (!parser_next(parser)) { + parseerror(parser, "expected for-loop condition"); + goto onerr; + } /* parse the condition */ if (parser->tok != ';') { @@ -2516,7 +2518,7 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou increment = parse_expression_leave(parser, false, false, false); if (!increment) goto onerr; - if (!ast_side_effects(increment)) { + if (!increment->m_side_effects) { if (compile_warning(condctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect")) goto onerr; } @@ -2561,8 +2563,8 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou ast_expression *exp = nullptr; ast_expression *var = nullptr; ast_return *ret = nullptr; - ast_value *retval = parser->function->return_value; - ast_value *expected = parser->function->vtype; + ast_value *retval = parser->function->m_return_value; + ast_value *expected = parser->function->m_function_type; lex_ctx_t ctx = parser_ctx(parser); @@ -2580,9 +2582,9 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou return false; } - if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) { + if (type_store_instr[expected->m_next->m_vtype] == VINSTR_END) { char ty1[1024]; - ast_type_to_string(expected->expression.next, ty1, sizeof(ty1)); + ast_type_to_string(expected->m_next, ty1, sizeof(ty1)); parseerror(parser, "invalid return type: `%s'", ty1); return false; } @@ -2598,21 +2600,21 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou /* prepare the return value */ if (!retval) { retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID); - ast_type_adopt(retval, expected->expression.next); - parser->function->return_value = retval; + ast_type_adopt(retval, expected->m_next); + parser->function->m_return_value = retval; } if (!ast_compare_type(exp, (ast_expression*)retval)) { char ty1[1024], ty2[1024]; ast_type_to_string(exp, ty1, sizeof(ty1)); - ast_type_to_string(&retval->expression, ty2, sizeof(ty2)); + ast_type_to_string(retval, ty2, sizeof(ty2)); parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2); } /* store to 'return' local variable */ var = (ast_expression*)ast_store_new( ctx, - type_store_instr[expected->expression.next->vtype], + type_store_instr[expected->m_next->m_vtype], (ast_expression*)retval, exp); if (!var) { @@ -2634,8 +2636,8 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou if (!exp) return false; - if (exp->vtype != TYPE_NIL && - exp->vtype != ((ast_expression*)expected)->next->vtype) + if (exp->m_vtype != TYPE_NIL && + exp->m_vtype != ((ast_expression*)expected)->m_next->m_vtype) { parseerror(parser, "return with invalid expression"); } @@ -2649,7 +2651,7 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou if (!parser_next(parser)) parseerror(parser, "parse error"); - if (!retval && expected->expression.next->vtype != TYPE_VOID) + if (!retval && expected->m_next->m_vtype != TYPE_VOID) { (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value"); } @@ -3085,14 +3087,14 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * parseerror(parser, "expected expression for case"); return false; } - swcase.value = parse_expression_leave(parser, false, false, false); - if (!swcase.value) { + swcase.m_value = parse_expression_leave(parser, false, false, false); + if (!swcase.m_value) { ast_delete(switchnode); parseerror(parser, "expected expression for case"); return false; } if (!OPTS_FLAG(RELAXED_SWITCH)) { - if (!ast_istype(swcase.value, ast_value)) { /* || ((ast_value*)swcase.value)->cvq != CV_CONST) { */ + if (!ast_istype(swcase.m_value, ast_value)) { /* || ((ast_value*)swcase.m_value)->m_cvq != CV_CONST) { */ parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch"); ast_unref(operand); return false; @@ -3100,7 +3102,7 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * } } else if (!strcmp(parser_tokval(parser), "default")) { - swcase.value = nullptr; + swcase.m_value = nullptr; if (!parser_next(parser)) { ast_delete(switchnode); parseerror(parser, "expected colon"); @@ -3115,26 +3117,26 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * /* Now the colon and body */ if (parser->tok != ':') { - if (swcase.value) ast_unref(swcase.value); + if (swcase.m_value) ast_unref(swcase.m_value); ast_delete(switchnode); parseerror(parser, "expected colon"); return false; } if (!parser_next(parser)) { - if (swcase.value) ast_unref(swcase.value); + if (swcase.m_value) ast_unref(swcase.m_value); ast_delete(switchnode); parseerror(parser, "expected statements or case"); return false; } caseblock = ast_block_new(parser_ctx(parser)); if (!caseblock) { - if (swcase.value) ast_unref(swcase.value); + if (swcase.m_value) ast_unref(swcase.m_value); ast_delete(switchnode); return false; } - swcase.code = (ast_expression*)caseblock; - switchnode->cases.push_back(swcase); + swcase.m_code = (ast_expression*)caseblock; + switchnode->m_cases.push_back(swcase); while (true) { ast_expression *expr; if (parser->tok == '}') @@ -3187,8 +3189,8 @@ static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **si if (ast_istype(*side, ast_ternary)) { ast_ternary *tern = (ast_ternary*)*side; - on_true = parse_goto_computed(parser, &tern->on_true); - on_false = parse_goto_computed(parser, &tern->on_false); + on_true = parse_goto_computed(parser, &tern->m_on_true); + on_false = parse_goto_computed(parser, &tern->m_on_false); if (!on_true || !on_false) { parseerror(parser, "expected label or expression in ternary"); @@ -3197,13 +3199,13 @@ static ast_expression *parse_goto_computed(parser_t *parser, ast_expression **si return nullptr; } - cond = tern->cond; - tern->cond = nullptr; + cond = tern->m_cond; + tern->m_cond = nullptr; ast_delete(tern); *side = nullptr; return (ast_expression*)ast_ifthen_new(parser_ctx(parser), cond, on_true, on_false); } else if (ast_istype(*side, ast_label)) { - ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->name); + ast_goto *gt = ast_goto_new(parser_ctx(parser), ((ast_label*)*side)->m_name); ast_goto_set_label(gt, ((ast_label*)*side)); *side = nullptr; return (ast_expression*)gt; @@ -3242,7 +3244,7 @@ static bool parse_goto(parser_t *parser, ast_expression **out) /* not computed goto */ gt = ast_goto_new(parser_ctx(parser), parser_tokval(parser)); - lbl = parser_find_label(parser, gt->name); + lbl = parser_find_label(parser, gt->m_name); if (lbl) { if (!ast_istype(lbl, ast_label)) { parseerror(parser, "internal error: label is not an ast_label"); @@ -3391,7 +3393,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * if (parser->tok == TOKEN_IDENT && (tdef = parser_find_typedef(parser, parser_tokval(parser), 0))) { ast_type_to_string((ast_expression*)tdef, ty, sizeof(ty)); - con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->name, ty); + con_out("__builtin_debug_printtype: `%s`=`%s`\n", tdef->m_name, ty); if (!parser_next(parser)) { parseerror(parser, "parse error after __builtin_debug_printtype typename argument"); return false; @@ -3494,11 +3496,11 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * } label = (ast_label*)parser_find_label(parser, parser_tokval(parser)); if (label) { - if (!label->undefined) { - parseerror(parser, "label `%s` already defined", label->name); + if (!label->m_undefined) { + parseerror(parser, "label `%s` already defined", label->m_name); return false; } - label->undefined = false; + label->m_undefined = false; } else { label = ast_label_new(parser_ctx(parser), parser_tokval(parser), false); @@ -3510,7 +3512,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * return false; } for (i = 0; i < parser->gotos.size(); ++i) { - if (!strcmp(parser->gotos[i]->name, label->name)) { + if (!strcmp(parser->gotos[i]->m_name, label->m_name)) { ast_goto_set_label(parser->gotos[i], label); parser->gotos.erase(parser->gotos.begin() + i); --i; @@ -3533,7 +3535,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression * if (!exp) return false; *out = exp; - if (!ast_side_effects(exp)) { + if (!exp->m_side_effects) { if (compile_warning(ctx, WARN_EFFECTLESS_STATEMENT, "statement has no effect")) return false; } @@ -3598,18 +3600,18 @@ static bool parse_enum(parser_t *parser) old = parser_find_global(parser, parser_tokval(parser)); if (old) { parseerror(parser, "value `%s` has already been declared here: %s:%i", - parser_tokval(parser), ast_ctx(old).file, ast_ctx(old).line); + parser_tokval(parser), old->m_context.file, old->m_context.line); goto onerror; } var = ast_value_new(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT); vec_push(values, var); - var->cvq = CV_CONST; - var->hasvalue = true; + var->m_cvq = CV_CONST; + var->m_hasvalue = true; /* for flagged enumerations increment in POTs of TWO */ - var->constval.vfloat = (flag) ? (num *= 2) : (num ++); - parser_addglobal(parser, var->name, (ast_expression*)var); + var->m_constval.vfloat = (flag) ? (num *= 2) : (num ++); + parser_addglobal(parser, var->m_name, (ast_expression*)var); if (!parser_next(parser)) { parseerror(parser, "expected `=`, `}` or comma after identifier"); @@ -3633,11 +3635,11 @@ static bool parse_enum(parser_t *parser) /* We got a value! */ old = parse_expression_leave(parser, true, false, false); asvalue = (ast_value*)old; - if (!ast_istype(old, ast_value) || asvalue->cvq != CV_CONST || !asvalue->hasvalue) { - compile_error(ast_ctx(var), "constant value or expression expected"); + if (!ast_istype(old, ast_value) || asvalue->m_cvq != CV_CONST || !asvalue->m_hasvalue) { + compile_error(var->m_context, "constant value or expression expected"); goto onerror; } - num = (var->constval.vfloat = asvalue->constval.vfloat) + 1; + num = (var->m_constval.vfloat = asvalue->m_constval.vfloat) + 1; if (parser->tok == '}') break; @@ -3651,7 +3653,7 @@ static bool parse_enum(parser_t *parser) if (reverse) { size_t i; for (i = 0; i < vec_size(values); i++) - values[i]->constval.vfloat = vec_size(values) - i - 1; + values[i]->m_constval.vfloat = vec_size(values) - i - 1; } if (parser->tok != '}') { @@ -3745,15 +3747,15 @@ static bool parse_statement_or_block(parser_t *parser, ast_expression **out) static bool create_vector_members(ast_value *var, ast_member **me) { size_t i; - size_t len = strlen(var->name); + size_t len = strlen(var->m_name); for (i = 0; i < 3; ++i) { char *name = (char*)mem_a(len+3); - memcpy(name, var->name, len); + memcpy(name, var->m_name, len); name[len+0] = '_'; name[len+1] = 'x'+i; name[len+2] = 0; - me[i] = ast_member_new(ast_ctx(var), (ast_expression*)var, i, name); + me[i] = ast_member_new(var->m_context, (ast_expression*)var, i, name); mem_d(name); if (!me[i]) break; @@ -3784,7 +3786,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) has_frame_think = false; old = parser->function; - if (var->expression.flags & AST_FLAG_ALIAS) { + if (var->m_flags & AST_FLAG_ALIAS) { parseerror(parser, "function aliases cannot have bodies"); return false; } @@ -3794,7 +3796,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) return false; } - if (!OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) { + if (!OPTS_FLAG(VARIADIC_ARGS) && var->m_flags & AST_FLAG_VARIADIC) { if (parsewarning(parser, WARN_VARIADIC_FUNCTION, "variadic function with implementation will not be able to access additional parameters (try -fvariadic-args)")) { @@ -3835,7 +3837,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) parseerror(parser, "expected a framenumber constant in[frame,think] notation"); return false; } - if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->hasvalue) { + if (!ast_istype(framenum, ast_value) || !( (ast_value*)framenum )->m_hasvalue) { ast_unref(framenum); parseerror(parser, "framenumber in [frame,think] notation must be a constant"); return false; @@ -3858,9 +3860,9 @@ static bool parse_function_body(parser_t *parser, ast_value *var) /* qc allows the use of not-yet-declared functions here * - this automatically creates a prototype */ ast_value *thinkfunc; - ast_expression *functype = fld_think->next; + ast_expression *functype = fld_think->m_next; - thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->vtype); + thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->m_vtype); if (!thinkfunc) { /* || !ast_type_adopt(thinkfunc, functype)*/ ast_unref(framenum); parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser)); @@ -3874,7 +3876,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) return false; } - parser_addglobal(parser, thinkfunc->name, (ast_expression*)thinkfunc); + parser_addglobal(parser, thinkfunc->m_name, (ast_expression*)thinkfunc); nextthink = (ast_expression*)thinkfunc; @@ -4006,24 +4008,24 @@ static bool parse_function_body(parser_t *parser, ast_value *var) } } - if (var->hasvalue) { - if (!(var->expression.flags & AST_FLAG_ACCUMULATE)) { - parseerror(parser, "function `%s` declared with multiple bodies", var->name); + if (var->m_hasvalue) { + if (!(var->m_flags & AST_FLAG_ACCUMULATE)) { + parseerror(parser, "function `%s` declared with multiple bodies", var->m_name); ast_block_delete(block); goto enderr; } - func = var->constval.vfunc; + func = var->m_constval.vfunc; if (!func) { - parseerror(parser, "internal error: nullptr function: `%s`", var->name); + parseerror(parser, "internal error: nullptr function: `%s`", var->m_name); ast_block_delete(block); goto enderr; } } else { - func = ast_function_new(ast_ctx(var), var->name, var); + func = ast_function_new(var->m_context, var->m_name, var); if (!func) { - parseerror(parser, "failed to allocate function for `%s`", var->name); + parseerror(parser, "failed to allocate function for `%s`", var->m_name); ast_block_delete(block); goto enderr; } @@ -4032,13 +4034,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var) parser_enterblock(parser); - for (auto &it : var->expression.params) { + for (auto &it : var->m_type_params) { size_t e; ast_member *me[3]; - if (it->expression.vtype != TYPE_VECTOR && - (it->expression.vtype != TYPE_FIELD || - it->expression.next->vtype != TYPE_VECTOR)) + if (it->m_vtype != TYPE_VECTOR && + (it->m_vtype != TYPE_FIELD || + it->m_next->m_vtype != TYPE_VECTOR)) { continue; } @@ -4049,37 +4051,37 @@ static bool parse_function_body(parser_t *parser, ast_value *var) } for (e = 0; e < 3; ++e) { - parser_addlocal(parser, me[e]->name, (ast_expression*)me[e]); + parser_addlocal(parser, me[e]->m_name, (ast_expression*)me[e]); ast_block_collect(block, (ast_expression*)me[e]); } } - if (var->argcounter && !func->argc) { - ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT); - parser_addlocal(parser, argc->name, (ast_expression*)argc); - func->argc = argc; + if (var->m_argcounter && !func->m_argc) { + ast_value *argc = ast_value_new(var->m_context, var->m_argcounter, TYPE_FLOAT); + parser_addlocal(parser, argc->m_name, (ast_expression*)argc); + func->m_argc = argc; } - if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC && !func->varargs) { + if (OPTS_FLAG(VARIADIC_ARGS) && var->m_flags & AST_FLAG_VARIADIC && !func->m_varargs) { char name[1024]; - ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY); - varargs->expression.flags |= AST_FLAG_IS_VARARG; - varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), nullptr, TYPE_VECTOR); - varargs->expression.count = 0; - util_snprintf(name, sizeof(name), "%s##va##SET", var->name); + ast_value *varargs = ast_value_new(var->m_context, "reserved:va_args", TYPE_ARRAY); + varargs->m_flags |= AST_FLAG_IS_VARARG; + varargs->m_next = (ast_expression*)ast_value_new(var->m_context, nullptr, TYPE_VECTOR); + varargs->m_count = 0; + util_snprintf(name, sizeof(name), "%s##va##SET", var->m_name); if (!parser_create_array_setter_proto(parser, varargs, name)) { ast_delete(varargs); ast_block_delete(block); goto enderrfn; } - util_snprintf(name, sizeof(name), "%s##va##GET", var->name); - if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) { + util_snprintf(name, sizeof(name), "%s##va##GET", var->m_name); + if (!parser_create_array_getter_proto(parser, varargs, varargs->m_next, name)) { ast_delete(varargs); ast_block_delete(block); goto enderrfn; } - func->varargs = varargs; - func->fixedparams = (ast_value*)parser->m_fold.constgen_float(var->expression.params.size(), false); + func->m_varargs = varargs; + func->m_fixedparams = (ast_value*)parser->m_fold.constgen_float(var->m_type_params.size(), false); } parser->function = func; @@ -4088,7 +4090,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) goto enderrfn; } - func->blocks.push_back(block); + func->m_blocks.emplace_back(block); parser->function = old; if (!parser_leaveblock(parser)) @@ -4108,7 +4110,7 @@ enderrfn: (void)!parser_leaveblock(parser); parser->functions.pop_back(); ast_function_delete(func); - var->constval.vfunc = nullptr; + var->m_constval.vfunc = nullptr; enderr: parser->function = old; @@ -4127,7 +4129,7 @@ static ast_expression *array_accessor_split( ast_ifthen *ifthen; ast_binary *cmp; - lex_ctx_t ctx = ast_ctx(array); + lex_ctx_t ctx = array->m_context; if (!left || !right) { if (left) ast_delete(left); @@ -4157,7 +4159,7 @@ static ast_expression *array_accessor_split( static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast_value *index, ast_value *value, size_t from, size_t afterend) { - lex_ctx_t ctx = ast_ctx(array); + lex_ctx_t ctx = array->m_context; if (from+1 == afterend) { /* set this value */ @@ -4165,9 +4167,9 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast ast_return *ret; ast_array_index *subscript; ast_store *st; - int assignop = type_store_instr[value->expression.vtype]; + int assignop = type_store_instr[value->m_vtype]; - if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) + if (value->m_vtype == TYPE_FIELD && value->m_next->m_vtype == TYPE_VECTOR) assignop = INSTR_STORE_V; subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); @@ -4222,7 +4224,7 @@ static ast_expression *array_field_setter_node( size_t from, size_t afterend) { - lex_ctx_t ctx = ast_ctx(array); + lex_ctx_t ctx = array->m_context; if (from+1 == afterend) { /* set this value */ @@ -4231,17 +4233,17 @@ static ast_expression *array_field_setter_node( ast_entfield *entfield; ast_array_index *subscript; ast_store *st; - int assignop = type_storep_instr[value->expression.vtype]; + int assignop = type_storep_instr[value->m_vtype]; - if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) + if (value->m_vtype == TYPE_FIELD && value->m_next->m_vtype == TYPE_VECTOR) assignop = INSTR_STOREP_V; subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); if (!subscript) return nullptr; - subscript->expression.next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript); - subscript->expression.vtype = TYPE_FIELD; + subscript->m_next = ast_type_copy(subscript->m_context, (ast_expression*)subscript); + subscript->m_vtype = TYPE_FIELD; entfield = ast_entfield_new_force(ctx, (ast_expression*)entity, @@ -4293,7 +4295,7 @@ static ast_expression *array_field_setter_node( static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast_value *index, size_t from, size_t afterend) { - lex_ctx_t ctx = ast_ctx(array); + lex_ctx_t ctx = array->m_context; if (from+1 == afterend) { ast_return *ret; @@ -4326,21 +4328,21 @@ static bool parser_create_array_accessor(parser_t *parser, ast_value *array, con ast_value *fval = nullptr; ast_block *body = nullptr; - fval = ast_value_new(ast_ctx(array), funcname, TYPE_FUNCTION); + fval = ast_value_new(array->m_context, funcname, TYPE_FUNCTION); if (!fval) { parseerror(parser, "failed to create accessor function value"); return false; } - fval->expression.flags &= ~(AST_FLAG_COVERAGE_MASK); + fval->m_flags &= ~(AST_FLAG_COVERAGE_MASK); - func = ast_function_new(ast_ctx(array), funcname, fval); + func = ast_function_new(array->m_context, funcname, fval); if (!func) { ast_delete(fval); parseerror(parser, "failed to create accessor function node"); return false; } - body = ast_block_new(ast_ctx(array)); + body = ast_block_new(array->m_context); if (!body) { parseerror(parser, "failed to create block for array accessor"); ast_delete(fval); @@ -4348,7 +4350,7 @@ static bool parser_create_array_accessor(parser_t *parser, ast_value *array, con return false; } - func->blocks.push_back(body); + func->m_blocks.emplace_back(body); *out = fval; parser->accessors.push_back(fval); @@ -4363,28 +4365,28 @@ static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value * ast_function *func; ast_value *fval; - if (!ast_istype(array->expression.next, ast_value)) { + if (!ast_istype(array->m_next, ast_value)) { parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type"); return nullptr; } if (!parser_create_array_accessor(parser, array, funcname, &fval)) return nullptr; - func = fval->constval.vfunc; - fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "", TYPE_VOID); + func = fval->m_constval.vfunc; + fval->m_next = (ast_expression*)ast_value_new(array->m_context, "", TYPE_VOID); - index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT); - value = ast_value_copy((ast_value*)array->expression.next); + index = ast_value_new(array->m_context, "index", TYPE_FLOAT); + value = ast_value_from_type((ast_value*)array->m_next); if (!index || !value) { parseerror(parser, "failed to create locals for array accessor"); goto cleanup; } (void)!ast_value_set_name(value, "value"); /* not important */ - fval->expression.params.push_back(index); - fval->expression.params.push_back(value); + fval->m_type_params.push_back(index); + fval->m_type_params.push_back(value); - array->setter = fval; + array->m_setter = fval; return fval; cleanup: if (index) ast_delete(index); @@ -4398,14 +4400,14 @@ static bool parser_create_array_setter_impl(parser_t *parser, ast_value *array) { ast_expression *root = nullptr; root = array_setter_node(parser, array, - array->setter->expression.params[0], - array->setter->expression.params[1], - 0, array->expression.count); + array->m_setter->m_type_params[0], + array->m_setter->m_type_params[1], + 0, array->m_count); if (!root) { parseerror(parser, "failed to build accessor search tree"); return false; } - if (!ast_block_add_expr(array->setter->constval.vfunc->blocks[0], root)) { + if (!ast_block_add_expr(array->m_setter->m_constval.vfunc->m_blocks[0].get(), root)) { ast_delete(root); return false; } @@ -4428,36 +4430,36 @@ static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, ast_function *func; ast_value *fval; - if (!ast_istype(array->expression.next, ast_value)) { + if (!ast_istype(array->m_next, ast_value)) { parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type"); return false; } if (!parser_create_array_accessor(parser, array, funcname, &fval)) return false; - func = fval->constval.vfunc; - fval->expression.next = (ast_expression*)ast_value_new(ast_ctx(array), "", TYPE_VOID); + func = fval->m_constval.vfunc; + fval->m_next = (ast_expression*)ast_value_new(array->m_context, "", TYPE_VOID); - entity = ast_value_new(ast_ctx(array), "entity", TYPE_ENTITY); - index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT); - value = ast_value_copy((ast_value*)array->expression.next); + entity = ast_value_new(array->m_context, "entity", TYPE_ENTITY); + index = ast_value_new(array->m_context, "index", TYPE_FLOAT); + value = ast_value_from_type((ast_value*)array->m_next); if (!entity || !index || !value) { parseerror(parser, "failed to create locals for array accessor"); goto cleanup; } (void)!ast_value_set_name(value, "value"); /* not important */ - fval->expression.params.push_back(entity); - fval->expression.params.push_back(index); - fval->expression.params.push_back(value); + fval->m_type_params.push_back(entity); + fval->m_type_params.push_back(index); + fval->m_type_params.push_back(value); - root = array_field_setter_node(parser, array, entity, index, value, 0, array->expression.count); + root = array_field_setter_node(parser, array, entity, index, value, 0, array->m_count); if (!root) { parseerror(parser, "failed to build accessor search tree"); goto cleanup; } - array->setter = fval; - return ast_block_add_expr(func->blocks[0], root); + array->m_setter = fval; + return ast_block_add_expr(func->m_blocks[0].get(), root); cleanup: if (entity) ast_delete(entity); if (index) ast_delete(index); @@ -4474,28 +4476,28 @@ static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value * ast_value *fval; ast_function *func; - /* NOTE: checking array->expression.next rather than elemtype since + /* NOTE: checking array->m_next rather than elemtype since * for fields elemtype is a temporary fieldtype. */ - if (!ast_istype(array->expression.next, ast_value)) { + if (!ast_istype(array->m_next, ast_value)) { parseerror(parser, "internal error: array accessor needs to build an ast_value with a copy of the element type"); return nullptr; } if (!parser_create_array_accessor(parser, array, funcname, &fval)) return nullptr; - func = fval->constval.vfunc; - fval->expression.next = ast_type_copy(ast_ctx(array), elemtype); + func = fval->m_constval.vfunc; + fval->m_next = ast_type_copy(array->m_context, elemtype); - index = ast_value_new(ast_ctx(array), "index", TYPE_FLOAT); + index = ast_value_new(array->m_context, "index", TYPE_FLOAT); if (!index) { parseerror(parser, "failed to create locals for array accessor"); goto cleanup; } - fval->expression.params.push_back(index); + fval->m_type_params.push_back(index); - array->getter = fval; + array->m_getter = fval; return fval; cleanup: if (index) ast_delete(index); @@ -4508,12 +4510,12 @@ static bool parser_create_array_getter_impl(parser_t *parser, ast_value *array) { ast_expression *root = nullptr; - root = array_getter_node(parser, array, array->getter->expression.params[0], 0, array->expression.count); + root = array_getter_node(parser, array, array->m_getter->m_type_params[0], 0, array->m_count); if (!root) { parseerror(parser, "failed to build accessor search tree"); return false; } - if (!ast_block_add_expr(array->getter->constval.vfunc->blocks[0], root)) { + if (!ast_block_add_expr(array->m_getter->m_constval.vfunc->m_blocks[0].get(), root)) { ast_delete(root); return false; } @@ -4580,7 +4582,7 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } } else { params.push_back(param); - if (param->expression.vtype >= TYPE_VARIANT) { + if (param->m_vtype >= TYPE_VARIANT) { char tname[1024]; /* typename is reserved in C++ */ ast_type_to_string((ast_expression*)param, tname, sizeof(tname)); parseerror(parser, "type not supported as part of a parameter list: %s", tname); @@ -4604,14 +4606,14 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) } } } - if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC && param->name[0] == '<') { + if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC && param->m_name[0] == '<') { parseerror(parser, "parameter name omitted"); goto on_error; } } } - if (params.size() == 1 && params[0]->expression.vtype == TYPE_VOID) + if (params.size() == 1 && params[0]->m_vtype == TYPE_VOID) params.clear(); /* sanity check */ @@ -4626,14 +4628,14 @@ static ast_value *parse_parameter_list(parser_t *parser, ast_value *var) /* now turn 'var' into a function type */ fval = ast_value_new(ctx, "", TYPE_FUNCTION); - fval->expression.next = (ast_expression*)var; + fval->m_next = (ast_expression*)var; if (variadic) - fval->expression.flags |= AST_FLAG_VARIADIC; + fval->m_flags |= AST_FLAG_VARIADIC; var = fval; - var->expression.params = params; - var->expression.varparam = (ast_expression*)varparam; - var->argcounter = argcounter; + var->m_type_params = move(params); + var->m_varparam = (ast_expression*)varparam; + var->m_argcounter = argcounter; return var; @@ -4680,14 +4682,14 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) } tmp = ast_value_new(ctx, "", TYPE_ARRAY); - tmp->expression.next = (ast_expression*)var; + tmp->m_next = (ast_expression*)var; var = tmp; if (cval) { - 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; + if (cval->m_vtype == TYPE_INTEGER) + tmp->m_count = cval->m_constval.vint; + else if (cval->m_vtype == TYPE_FLOAT) + tmp->m_count = cval->m_constval.vfloat; else { ast_unref(cexp); ast_delete(var); @@ -4697,8 +4699,8 @@ static ast_value *parse_arraysize(parser_t *parser, ast_value *var) ast_unref(cexp); } else { - var->expression.count = -1; - var->expression.flags |= AST_FLAG_ARRAY_INIT; + var->m_count = -1; + var->m_flags |= AST_FLAG_ARRAY_INIT; } if (parser->tok != ']') { @@ -4788,14 +4790,14 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* generate the basic type value */ if (cached_typedef) { - var = ast_value_copy(cached_typedef); + var = ast_value_from_type(cached_typedef); ast_value_set_name(var, ""); } else var = ast_value_new(ctx, "", parser_token(parser)->constval.t); for (; morefields; --morefields) { tmp = ast_value_new(ctx, "<.type>", TYPE_FIELD); - tmp->expression.next = (ast_expression*)var; + tmp->m_next = (ast_expression*)var; var = tmp; } @@ -4824,10 +4826,10 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va /* store the base if requested */ if (storebase) { - *storebase = ast_value_copy(var); + *storebase = ast_value_from_type(var); if (isfield) { tmp = ast_value_new(ctx, "", TYPE_FIELD); - tmp->expression.next = (ast_expression*)*storebase; + tmp->m_next = (ast_expression*)*storebase; *storebase = tmp; } } @@ -4865,7 +4867,7 @@ static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_va if (isfield) { /* turn it into a field if desired */ tmp = ast_value_new(ctx, "", TYPE_FIELD); - tmp->expression.next = (ast_expression*)var; + tmp->m_next = (ast_expression*)var; var = tmp; } @@ -4908,29 +4910,29 @@ static bool parse_typedef(parser_t *parser) return false; /* while parsing types, the ast_value's get named '' */ - if (!typevar->name || typevar->name[0] == '<') { + if (!typevar->m_name || typevar->m_name[0] == '<') { parseerror(parser, "missing name in typedef"); ast_delete(typevar); return false; } - if ( (old = parser_find_var(parser, typevar->name)) ) { + if ( (old = parser_find_var(parser, typevar->m_name)) ) { parseerror(parser, "cannot define a type with the same name as a variable: %s\n" " -> `%s` has been declared here: %s:%i", - typevar->name, ast_ctx(old).file, ast_ctx(old).line); + typevar->m_name, old->m_context.file, old->m_context.line); ast_delete(typevar); return false; } - if ( (oldtype = parser_find_typedef(parser, typevar->name, vec_last(parser->_blocktypedefs))) ) { + if ( (oldtype = parser_find_typedef(parser, typevar->m_name, vec_last(parser->_blocktypedefs))) ) { parseerror(parser, "type `%s` has already been declared here: %s:%i", - typevar->name, ast_ctx(oldtype).file, ast_ctx(oldtype).line); + typevar->m_name, oldtype->m_context.file, oldtype->m_context.line); ast_delete(typevar); return false; } vec_push(parser->_typedefs, typevar); - util_htset(vec_last(parser->typedefs), typevar->name, typevar); + util_htset(vec_last(parser->typedefs), typevar->m_name, typevar); if (parser->tok != ';') { parseerror(parser, "expected semicolon after typedef"); @@ -4956,27 +4958,27 @@ static const char *cvq_to_str(int cvq) { static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, const ast_value *proto) { bool av, ao; - if (proto->cvq != var->cvq) { - if (!(proto->cvq == CV_CONST && var->cvq == CV_NONE && + if (proto->m_cvq != var->m_cvq) { + if (!(proto->m_cvq == CV_CONST && var->m_cvq == CV_NONE && !OPTS_FLAG(INITIALIZED_NONCONSTANTS) && parser->tok == '=')) { return !parsewarning(parser, WARN_DIFFERENT_QUALIFIERS, "`%s` declared with different qualifiers: %s\n" " -> previous declaration here: %s:%i uses %s", - var->name, cvq_to_str(var->cvq), - ast_ctx(proto).file, ast_ctx(proto).line, - cvq_to_str(proto->cvq)); + var->m_name, cvq_to_str(var->m_cvq), + proto->m_context.file, proto->m_context.line, + cvq_to_str(proto->m_cvq)); } } - av = (var ->expression.flags & AST_FLAG_NORETURN); - ao = (proto->expression.flags & AST_FLAG_NORETURN); + av = (var ->m_flags & AST_FLAG_NORETURN); + ao = (proto->m_flags & AST_FLAG_NORETURN); if (!av != !ao) { return !parsewarning(parser, WARN_DIFFERENT_ATTRIBUTES, "`%s` declared with different attributes%s\n" " -> previous declaration here: %s:%i", - var->name, (av ? ": noreturn" : ""), - ast_ctx(proto).file, ast_ctx(proto).line, + var->m_name, (av ? ": noreturn" : ""), + proto->m_context.file, proto->m_context.line, (ao ? ": noreturn" : "")); } return true; @@ -4985,11 +4987,11 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons static bool create_array_accessors(parser_t *parser, ast_value *var) { char name[1024]; - util_snprintf(name, sizeof(name), "%s##SET", var->name); + util_snprintf(name, sizeof(name), "%s##SET", var->m_name); if (!parser_create_array_setter(parser, var, name)) return false; - util_snprintf(name, sizeof(name), "%s##GET", var->name); - if (!parser_create_array_getter(parser, var, var->expression.next, name)) + util_snprintf(name, sizeof(name), "%s##GET", var->m_name); + if (!parser_create_array_getter(parser, var, var->m_next, name)) return false; return true; } @@ -4997,7 +4999,7 @@ static bool create_array_accessors(parser_t *parser, ast_value *var) static bool parse_array(parser_t *parser, ast_value *array) { size_t i; - if (array->initlist.size()) { + if (array->m_initlist.size()) { parseerror(parser, "array already initialized elsewhere"); return false; } @@ -5010,14 +5012,14 @@ static bool parse_array(parser_t *parser, ast_value *array) ast_value *v = (ast_value*)parse_expression_leave(parser, true, false, false); if (!v) return false; - if (!ast_istype(v, ast_value) || !v->hasvalue || v->cvq != CV_CONST) { + if (!ast_istype(v, ast_value) || !v->m_hasvalue || v->m_cvq != CV_CONST) { ast_unref(v); parseerror(parser, "initializing element must be a compile time constant"); return false; } - array->initlist.push_back(v->constval); - if (v->expression.vtype == TYPE_STRING) { - array->initlist[i].vstring = util_strdupe(array->initlist[i].vstring); + array->m_initlist.push_back(v->m_constval); + if (v->m_vtype == TYPE_STRING) { + array->m_initlist[i].vstring = util_strdupe(array->m_initlist[i].vstring); ++i; } ast_unref(v); @@ -5039,12 +5041,12 @@ static bool parse_array(parser_t *parser, ast_value *array) } */ - if (array->expression.flags & AST_FLAG_ARRAY_INIT) { - if (array->expression.count != (size_t)-1) { + if (array->m_flags & AST_FLAG_ARRAY_INIT) { + if (array->m_count != (size_t)-1) { parseerror(parser, "array `%s' has already been initialized with %u elements", - array->name, (unsigned)array->expression.count); + array->m_name, (unsigned)array->m_count); } - array->expression.count = array->initlist.size(); + array->m_count = array->m_initlist.size(); if (!create_array_accessors(parser, array)) return false; } @@ -5081,7 +5083,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } /* while parsing types, the ast_value's get named '' */ - if (!var->name || var->name[0] == '<') { + if (!var->m_name || var->m_name[0] == '<') { parseerror(parser, "declaration does not declare anything"); if (basetype) ast_delete(basetype); @@ -5126,20 +5128,20 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } } - var->cvq = qualifier; + var->m_cvq = qualifier; if (qflags & AST_FLAG_COVERAGE) /* specified in QC, drop our default */ - var->expression.flags &= ~(AST_FLAG_COVERAGE_MASK); - var->expression.flags |= qflags; + var->m_flags &= ~(AST_FLAG_COVERAGE_MASK); + var->m_flags |= qflags; /* * store the vstring back to var for alias and * deprecation messages. */ - if (var->expression.flags & AST_FLAG_DEPRECATED || - var->expression.flags & AST_FLAG_ALIAS) - var->desc = vstring; + if (var->m_flags & AST_FLAG_DEPRECATED || + var->m_flags & AST_FLAG_ALIAS) + var->m_desc = vstring; - if (parser_find_global(parser, var->name) && var->expression.flags & AST_FLAG_ALIAS) { + if (parser_find_global(parser, var->m_name) && var->m_flags & AST_FLAG_ALIAS) { parseerror(parser, "function aliases cannot be forward declared"); retval = false; goto cleanup; @@ -5151,7 +5153,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield * Also: if there was a prototype, `var` will be deleted and set to `proto` which * is then filled with the previous definition and the parameter-names replaced. */ - if (!strcmp(var->name, "nil")) { + if (!strcmp(var->m_name, "nil")) { if (OPTS_FLAG(UNTYPED_NIL)) { if (!localblock || !OPTS_FLAG(PERMISSIVE)) parseerror(parser, "name `nil` not allowed (try -fpermissive)"); @@ -5161,17 +5163,17 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield if (!localblock) { /* Deal with end_sys_ vars */ was_end = false; - if (!strcmp(var->name, "end_sys_globals")) { - var->uses++; + if (!strcmp(var->m_name, "end_sys_globals")) { + var->m_uses++; parser->crc_globals = parser->globals.size(); was_end = true; } - else if (!strcmp(var->name, "end_sys_fields")) { - var->uses++; + else if (!strcmp(var->m_name, "end_sys_fields")) { + var->m_uses++; parser->crc_fields = parser->fields.size(); was_end = true; } - if (was_end && var->expression.vtype == TYPE_FIELD) { + if (was_end && var->m_vtype == TYPE_FIELD) { if (parsewarning(parser, WARN_END_SYS_FIELDS, "global '%s' hint should not be a field", parser_tokval(parser))) @@ -5181,13 +5183,13 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } } - if (!nofields && var->expression.vtype == TYPE_FIELD) + if (!nofields && var->m_vtype == TYPE_FIELD) { /* deal with field declarations */ - old = parser_find_field(parser, var->name); + old = parser_find_field(parser, var->m_name); if (old) { if (parsewarning(parser, WARN_FIELD_REDECLARED, "field `%s` already declared here: %s:%i", - var->name, ast_ctx(old).file, (int)ast_ctx(old).line)) + var->m_name, old->m_context.file, (int)old->m_context.line)) { retval = false; goto cleanup; @@ -5197,17 +5199,17 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield goto skipvar; /* parseerror(parser, "field `%s` already declared here: %s:%i", - var->name, ast_ctx(old).file, ast_ctx(old).line); + var->m_name, old->m_context.file, old->m_context.line); retval = false; goto cleanup; */ } if ((OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC || OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_FTEQCC) && - (old = parser_find_global(parser, var->name))) + (old = parser_find_global(parser, var->m_name))) { parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc"); parseerror(parser, "field `%s` already declared here: %s:%i", - var->name, ast_ctx(old).file, ast_ctx(old).line); + var->m_name, old->m_context.file, old->m_context.line); retval = false; goto cleanup; } @@ -5215,8 +5217,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield else { /* deal with other globals */ - old = parser_find_global(parser, var->name); - if (old && var->expression.vtype == TYPE_FUNCTION && old->vtype == TYPE_FUNCTION) + old = parser_find_global(parser, var->m_name); + if (old && var->m_vtype == TYPE_FUNCTION && old->m_vtype == TYPE_FUNCTION) { /* This is a function which had a prototype */ if (!ast_istype(old, ast_value)) { @@ -5225,25 +5227,25 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield goto cleanup; } proto = (ast_value*)old; - proto->desc = var->desc; + proto->m_desc = var->m_desc; if (!ast_compare_type((ast_expression*)proto, (ast_expression*)var)) { parseerror(parser, "conflicting types for `%s`, previous declaration was here: %s:%i", - proto->name, - ast_ctx(proto).file, ast_ctx(proto).line); + proto->m_name, + proto->m_context.file, proto->m_context.line); retval = false; goto cleanup; } /* we need the new parameter-names */ - for (i = 0; i < proto->expression.params.size(); ++i) - ast_value_set_name(proto->expression.params[i], var->expression.params[i]->name); + for (i = 0; i < proto->m_type_params.size(); ++i) + ast_value_set_name(proto->m_type_params[i], var->m_type_params[i]->m_name); if (!parser_check_qualifiers(parser, var, proto)) { retval = false; - if (proto->desc) - mem_d(proto->desc); + if (proto->m_desc) + mem_d(proto->m_desc); proto = nullptr; goto cleanup; } - proto->expression.flags |= var->expression.flags; + proto->m_flags |= var->m_flags; ast_delete(var); var = proto; } @@ -5253,14 +5255,14 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield if (old) { if (parsewarning(parser, WARN_DOUBLE_DECLARATION, "global `%s` already declared here: %s:%i", - var->name, ast_ctx(old).file, ast_ctx(old).line)) + var->m_name, old->m_context.file, old->m_context.line)) { retval = false; goto cleanup; } - if (old->flags & AST_FLAG_FINAL_DECL) { + if (old->m_flags & AST_FLAG_FINAL_DECL) { parseerror(parser, "cannot redeclare variable `%s`, declared final here: %s:%i", - var->name, ast_ctx(old).file, ast_ctx(old).line); + var->m_name, old->m_context.file, old->m_context.line); retval = false; goto cleanup; } @@ -5276,21 +5278,21 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield proto = nullptr; goto cleanup; } - proto->expression.flags |= var->expression.flags; + proto->m_flags |= var->m_flags; /* copy the context for finals, * so the error can show where it was actually made 'final' */ - if (proto->expression.flags & AST_FLAG_FINAL_DECL) - ast_ctx(old) = ast_ctx(var); + if (proto->m_flags & AST_FLAG_FINAL_DECL) + old->m_context = var->m_context; ast_delete(var); var = proto; } if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC && - (old = parser_find_field(parser, var->name))) + (old = parser_find_field(parser, var->m_name))) { parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc"); parseerror(parser, "global `%s` already declared here: %s:%i", - var->name, ast_ctx(old).file, ast_ctx(old).line); + var->m_name, old->m_context.file, old->m_context.line); retval = false; goto cleanup; } @@ -5299,21 +5301,21 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } else /* it's not a global */ { - old = parser_find_local(parser, var->name, vec_size(parser->variables)-1, &isparam); + old = parser_find_local(parser, var->m_name, vec_size(parser->variables)-1, &isparam); if (old && !isparam) { parseerror(parser, "local `%s` already declared here: %s:%i", - var->name, ast_ctx(old).file, (int)ast_ctx(old).line); + var->m_name, old->m_context.file, (int)old->m_context.line); retval = false; goto cleanup; } /* doing this here as the above is just for a single scope */ - old = parser_find_local(parser, var->name, 0, &isparam); + old = parser_find_local(parser, var->m_name, 0, &isparam); if (old && isparam) { if (parsewarning(parser, WARN_LOCAL_SHADOWS, - "local `%s` is shadowing a parameter", var->name)) + "local `%s` is shadowing a parameter", var->m_name)) { parseerror(parser, "local `%s` already declared here: %s:%i", - var->name, ast_ctx(old).file, (int)ast_ctx(old).line); + var->m_name, old->m_context.file, (int)old->m_context.line); retval = false; goto cleanup; } @@ -5331,16 +5333,16 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield /* in a noref section we simply bump the usecount */ if (noref || parser->noref) - var->uses++; + var->m_uses++; /* Part 2: * Create the global/local, and deal with vector types. */ if (!proto) { - if (var->expression.vtype == TYPE_VECTOR) + if (var->m_vtype == TYPE_VECTOR) isvector = true; - else if (var->expression.vtype == TYPE_FIELD && - var->expression.next->vtype == TYPE_VECTOR) + else if (var->m_vtype == TYPE_FIELD && + var->m_next->m_vtype == TYPE_VECTOR) isvector = true; if (isvector) { @@ -5352,30 +5354,30 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield if (!localblock) { /* deal with global variables, fields, functions */ - if (!nofields && var->expression.vtype == TYPE_FIELD && parser->tok != '=') { - var->isfield = true; + if (!nofields && var->m_vtype == TYPE_FIELD && parser->tok != '=') { + var->m_isfield = true; parser->fields.push_back((ast_expression*)var); - util_htset(parser->htfields, var->name, var); + util_htset(parser->htfields, var->m_name, var); if (isvector) { for (i = 0; i < 3; ++i) { parser->fields.push_back((ast_expression*)me[i]); - util_htset(parser->htfields, me[i]->name, me[i]); + util_htset(parser->htfields, me[i]->m_name, me[i]); } } } else { - if (!(var->expression.flags & AST_FLAG_ALIAS)) { - parser_addglobal(parser, var->name, (ast_expression*)var); + if (!(var->m_flags & AST_FLAG_ALIAS)) { + parser_addglobal(parser, var->m_name, (ast_expression*)var); if (isvector) { for (i = 0; i < 3; ++i) { - parser_addglobal(parser, me[i]->name, (ast_expression*)me[i]); + parser_addglobal(parser, me[i]->m_name, (ast_expression*)me[i]); } } } else { - ast_expression *find = parser_find_global(parser, var->desc); + ast_expression *find = parser_find_global(parser, var->m_desc); if (!find) { - compile_error(parser_ctx(parser), "undeclared variable `%s` for alias `%s`", var->desc, var->name); + compile_error(parser_ctx(parser), "undeclared variable `%s` for alias `%s`", var->m_desc, var->m_name); return false; } @@ -5387,24 +5389,24 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield ast_type_to_string((ast_expression*)var, ty2, sizeof(ty2)); compile_error(parser_ctx(parser), "incompatible types `%s` and `%s` for alias `%s`", - ty1, ty2, var->name + ty1, ty2, var->m_name ); return false; } - util_htset(parser->aliases, var->name, find); + util_htset(parser->aliases, var->m_name, find); /* generate aliases for vector components */ if (isvector) { char *buffer[3]; - util_asprintf(&buffer[0], "%s_x", var->desc); - util_asprintf(&buffer[1], "%s_y", var->desc); - util_asprintf(&buffer[2], "%s_z", var->desc); + util_asprintf(&buffer[0], "%s_x", var->m_desc); + util_asprintf(&buffer[1], "%s_y", var->m_desc); + util_asprintf(&buffer[2], "%s_z", var->m_desc); - util_htset(parser->aliases, me[0]->name, parser_find_global(parser, buffer[0])); - util_htset(parser->aliases, me[1]->name, parser_find_global(parser, buffer[1])); - util_htset(parser->aliases, me[2]->name, parser_find_global(parser, buffer[2])); + util_htset(parser->aliases, me[0]->m_name, parser_find_global(parser, buffer[0])); + util_htset(parser->aliases, me[1]->m_name, parser_find_global(parser, buffer[1])); + util_htset(parser->aliases, me[2]->m_name, parser_find_global(parser, buffer[2])); mem_d(buffer[0]); mem_d(buffer[1]); @@ -5421,37 +5423,37 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield size_t prefix_len, ln; size_t sn, sn_size; - ln = strlen(parser->function->name); - vec_append(defname, ln, parser->function->name); + ln = strlen(parser->function->m_name); + vec_append(defname, ln, parser->function->m_name); vec_append(defname, 2, "::"); /* remember the length up to here */ prefix_len = vec_size(defname); /* Add it to the local scope */ - util_htset(vec_last(parser->variables), var->name, (void*)var); + util_htset(vec_last(parser->variables), var->m_name, (void*)var); /* now rename the global */ - ln = strlen(var->name); - vec_append(defname, ln, var->name); + ln = strlen(var->m_name); + vec_append(defname, ln, var->m_name); /* if a variable of that name already existed, add the * counter value. * The counter is incremented either way. */ - sn_size = parser->function->static_names.size(); + sn_size = parser->function->m_static_names.size(); for (sn = 0; sn != sn_size; ++sn) { - if (strcmp(parser->function->static_names[sn], var->name) == 0) + if (strcmp(parser->function->m_static_names[sn], var->m_name) == 0) break; } if (sn != sn_size) { char *num = nullptr; - int len = util_asprintf(&num, "#%u", parser->function->static_count); + int len = util_asprintf(&num, "#%u", parser->function->m_static_count); vec_append(defname, len, num); mem_d(num); } else - parser->function->static_names.push_back(util_strdup(var->name)); - parser->function->static_count++; + parser->function->m_static_names.push_back(util_strdup(var->m_name)); + parser->function->m_static_count++; ast_value_set_name(var, defname); /* push it to the to-be-generated globals */ @@ -5460,11 +5462,11 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield /* same game for the vector members */ if (isvector) { for (i = 0; i < 3; ++i) { - util_htset(vec_last(parser->variables), me[i]->name, (void*)(me[i])); + util_htset(vec_last(parser->variables), me[i]->m_name, (void*)(me[i])); vec_shrinkto(defname, prefix_len); - ln = strlen(me[i]->name); - vec_append(defname, ln, me[i]->name); + ln = strlen(me[i]->m_name); + vec_append(defname, ln, me[i]->m_name); ast_member_set_name(me[i], defname); parser->globals.push_back((ast_expression*)me[i]); @@ -5472,11 +5474,11 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } vec_free(defname); } else { - localblock->locals.push_back(var); - parser_addlocal(parser, var->name, (ast_expression*)var); + localblock->m_locals.push_back(var); + parser_addlocal(parser, var->m_name, (ast_expression*)var); if (isvector) { for (i = 0; i < 3; ++i) { - parser_addlocal(parser, me[i]->name, (ast_expression*)me[i]); + parser_addlocal(parser, me[i]->m_name, (ast_expression*)me[i]); ast_block_collect(localblock, (ast_expression*)me[i]); } } @@ -5489,34 +5491,34 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield /* Part 2.2 * deal with arrays */ - if (var->expression.vtype == TYPE_ARRAY) { - if (var->expression.count != (size_t)-1) { + if (var->m_vtype == TYPE_ARRAY) { + if (var->m_count != (size_t)-1) { if (!create_array_accessors(parser, var)) goto cleanup; } } else if (!localblock && !nofields && - var->expression.vtype == TYPE_FIELD && - var->expression.next->vtype == TYPE_ARRAY) + var->m_vtype == TYPE_FIELD && + var->m_next->m_vtype == TYPE_ARRAY) { char name[1024]; ast_expression *telem; ast_value *tfield; - ast_value *array = (ast_value*)var->expression.next; + ast_value *array = (ast_value*)var->m_next; - if (!ast_istype(var->expression.next, ast_value)) { + if (!ast_istype(var->m_next, ast_value)) { parseerror(parser, "internal error: field element type must be an ast_value"); goto cleanup; } - util_snprintf(name, sizeof(name), "%s##SETF", var->name); + util_snprintf(name, sizeof(name), "%s##SETF", var->m_name); if (!parser_create_array_field_setter(parser, array, name)) goto cleanup; - telem = ast_type_copy(ast_ctx(var), array->expression.next); - tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD); - tfield->expression.next = telem; - util_snprintf(name, sizeof(name), "%s##GETFP", var->name); + telem = ast_type_copy(var->m_context, array->m_next); + tfield = ast_value_new(var->m_context, "<.type>", TYPE_FIELD); + tfield->m_next = telem; + util_snprintf(name, sizeof(name), "%s##GETFP", var->m_name); if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) { ast_delete(tfield); goto cleanup; @@ -5538,7 +5540,7 @@ skipvar: goto another; /* - if (!var || (!localblock && !nofields && basetype->expression.vtype == TYPE_FIELD)) { + if (!var || (!localblock && !nofields && basetype->m_vtype == TYPE_FIELD)) { */ if (!var) { parseerror(parser, "missing comma or semicolon while parsing variables"); @@ -5548,13 +5550,13 @@ skipvar: if (localblock && OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) { if (parsewarning(parser, WARN_LOCAL_CONSTANTS, "initializing expression turns variable `%s` into a constant in this standard", - var->name) ) + var->m_name) ) { break; } } - if (parser->tok != '{' || var->expression.vtype != TYPE_FUNCTION) { + if (parser->tok != '{' || var->m_vtype != TYPE_FUNCTION) { if (parser->tok != '=') { parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser)); break; @@ -5580,8 +5582,8 @@ skipvar: parseerror(parser, "cannot declare builtins within functions"); break; } - if (var->expression.vtype != TYPE_FUNCTION) { - parseerror(parser, "unexpected builtin number, '%s' is not a function", var->name); + if (var->m_vtype != TYPE_FUNCTION) { + parseerror(parser, "unexpected builtin number, '%s' is not a function", var->m_name); break; } if (!parser_next(parser)) { @@ -5595,16 +5597,16 @@ skipvar: parseerror(parser, "builtin number expected"); break; } - if (!ast_istype(number, ast_value) || !number->hasvalue || number->cvq != CV_CONST) + if (!ast_istype(number, ast_value) || !number->m_hasvalue || number->m_cvq != CV_CONST) { ast_unref(number); parseerror(parser, "builtin number must be a compile time constant"); break; } - if (number->expression.vtype == TYPE_INTEGER) - builtin_num = number->constval.vint; - else if (number->expression.vtype == TYPE_FLOAT) - builtin_num = number->constval.vfloat; + if (number->m_vtype == TYPE_INTEGER) + builtin_num = number->m_constval.vint; + else if (number->m_vtype == TYPE_FLOAT) + builtin_num = number->m_constval.vfloat; else { ast_unref(number); parseerror(parser, "builtin number must be an integer constant"); @@ -5627,22 +5629,22 @@ skipvar: break; } - if (var->hasvalue) { + if (var->m_hasvalue) { (void)!parsewarning(parser, WARN_DOUBLE_DECLARATION, "builtin `%s` has already been defined\n" " -> previous declaration here: %s:%i", - var->name, ast_ctx(var).file, (int)ast_ctx(var).line); + var->m_name, var->m_context.file, (int)var->m_context.line); } else { - func = ast_function_new(ast_ctx(var), var->name, var); + func = ast_function_new(var->m_context, var->m_name, var); if (!func) { - parseerror(parser, "failed to allocate function for `%s`", var->name); + parseerror(parser, "failed to allocate function for `%s`", var->m_name); break; } parser->functions.push_back(func); - func->builtin = -builtin_num-1; + func->m_builtin = -builtin_num-1; } if (OPTS_FLAG(EXPRESSIONS_FOR_BUILTINS) @@ -5652,11 +5654,11 @@ skipvar: parseerror(parser, "expected comma or semicolon"); if (func) ast_function_delete(func); - var->constval.vfunc = nullptr; + var->m_constval.vfunc = nullptr; break; } } - else if (var->expression.vtype == TYPE_ARRAY && parser->tok == '{') + else if (var->m_vtype == TYPE_ARRAY && parser->tok == '{') { if (localblock) { /* Note that fteqcc and most others don't even *have* @@ -5666,11 +5668,11 @@ skipvar: break; } - var->hasvalue = true; + var->m_hasvalue = true; if (!parse_array(parser, var)) break; } - else if (var->expression.vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '[')) + else if (var->m_vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '[')) { if (localblock) { parseerror(parser, "cannot declare functions within functions"); @@ -5678,13 +5680,15 @@ skipvar: } if (proto) - ast_ctx(proto) = parser_ctx(parser); + proto->m_context = parser_ctx(parser); if (!parse_function_body(parser, var)) break; ast_delete(basetype); for (auto &it : parser->gotos) - parseerror(parser, "undefined label: `%s`", it->name); + parseerror(parser, "undefined label: `%s`", it->m_name); + parser->gotos.clear(); + parser->labels.clear(); return true; } else { ast_expression *cexp; @@ -5698,13 +5702,13 @@ skipvar: /* deal with foldable constants: */ if (localblock && - var->cvq == CV_CONST && cval && cval->hasvalue && cval->cvq == CV_CONST && !cval->isfield) + var->m_cvq == CV_CONST && cval && cval->m_hasvalue && cval->m_cvq == CV_CONST && !cval->m_isfield) { /* remove it from the current locals */ if (isvector) { for (i = 0; i < 3; ++i) { vec_pop(parser->_locals); - localblock->collect.pop_back(); + localblock->m_collect.pop_back(); } } /* do sanity checking, this function really needs refactoring */ @@ -5712,10 +5716,10 @@ skipvar: parseerror(parser, "internal error: unexpected change in local variable handling"); else vec_pop(parser->_locals); - if (localblock->locals.back() != var) + if (localblock->m_locals.back() != var) parseerror(parser, "internal error: unexpected change in local variable handling (2)"); else - localblock->locals.pop_back(); + localblock->m_locals.pop_back(); /* push it to the to-be-generated globals */ parser->globals.push_back((ast_expression*)var); if (isvector) @@ -5726,7 +5730,7 @@ skipvar: if (folded_const || !localblock || is_static) { if (cval != parser->nil && - (!cval || ((!cval->hasvalue || cval->cvq != CV_CONST) && !cval->isfield)) + (!cval || ((!cval->m_hasvalue || cval->m_cvq != CV_CONST) && !cval->m_isfield)) ) { parseerror(parser, "initializer is non constant"); @@ -5737,30 +5741,30 @@ skipvar: !OPTS_FLAG(INITIALIZED_NONCONSTANTS) && qualifier != CV_VAR) { - var->cvq = CV_CONST; + var->m_cvq = CV_CONST; } if (cval == parser->nil) - var->expression.flags |= AST_FLAG_INITIALIZED; + var->m_flags |= AST_FLAG_INITIALIZED; else { - var->hasvalue = true; - if (cval->expression.vtype == TYPE_STRING) - var->constval.vstring = parser_strdup(cval->constval.vstring); - else if (cval->expression.vtype == TYPE_FIELD) - var->constval.vfield = cval; + var->m_hasvalue = true; + if (cval->m_vtype == TYPE_STRING) + var->m_constval.vstring = parser_strdup(cval->m_constval.vstring); + else if (cval->m_vtype == TYPE_FIELD) + var->m_constval.vfield = cval; else - memcpy(&var->constval, &cval->constval, sizeof(var->constval)); + memcpy(&var->m_constval, &cval->m_constval, sizeof(var->m_constval)); ast_unref(cval); } } } else { int cvq; shunt sy; - cvq = var->cvq; - var->cvq = CV_NONE; - sy.out.push_back(syexp(ast_ctx(var), (ast_expression*)var)); - sy.out.push_back(syexp(ast_ctx(cexp), (ast_expression*)cexp)); - sy.ops.push_back(syop(ast_ctx(var), parser->assign_op)); + cvq = var->m_cvq; + var->m_cvq = CV_NONE; + sy.out.push_back(syexp(var->m_context, (ast_expression*)var)); + sy.out.push_back(syexp(cexp->m_context, (ast_expression*)cexp)); + sy.ops.push_back(syop(var->m_context, parser->assign_op)); if (!parser_sy_apply_operator(parser, &sy)) ast_unref(cexp); else { @@ -5769,14 +5773,14 @@ skipvar: if (!ast_block_add_expr(localblock, (ast_expression*)sy.out[0].out)) break; } - var->cvq = cvq; + var->m_cvq = cvq; } /* a constant initialized to an inexact value should be marked inexact: * const float x = ; should propagate the inexact flag */ - if (var->cvq == CV_CONST && var->expression.vtype == TYPE_FLOAT) { - if (cval && cval->hasvalue && cval->cvq == CV_CONST) - var->inexact = cval->inexact; + if (var->m_cvq == CV_CONST && var->m_vtype == TYPE_FLOAT) { + if (cval && cval->m_hasvalue && cval->m_cvq == CV_CONST) + var->m_inexact = cval->m_inexact; } } @@ -5791,7 +5795,7 @@ another: parseerror(parser, "expected another variable"); break; } - var = ast_value_copy(basetype); + var = ast_value_from_type(basetype); cleanvar = true; ast_value_set_name(var, parser_tokval(parser)); if (!parser_next(parser)) { @@ -5929,7 +5933,7 @@ static void generate_checksum(parser_t *parser, ir_builder *ir) if (!ast_istype(parser->globals[i], ast_value)) continue; value = (ast_value*)(parser->globals[i]); - switch (value->expression.vtype) { + switch (value->m_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; @@ -5938,7 +5942,7 @@ static void generate_checksum(parser_t *parser, ir_builder *ir) crc = progdefs_crc_both(crc, "\tint\t"); break; } - crc = progdefs_crc_both(crc, value->name); + crc = progdefs_crc_both(crc, value->m_name); crc = progdefs_crc_both(crc, ";\n"); } crc = progdefs_crc_both(crc, "} globalvars_t;\n\ntypedef struct\n{\n"); @@ -5946,7 +5950,7 @@ static void generate_checksum(parser_t *parser, ir_builder *ir) if (!ast_istype(parser->fields[i], ast_value)) continue; value = (ast_value*)(parser->fields[i]); - switch (value->expression.next->vtype) { + switch (value->m_next->m_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; @@ -5955,11 +5959,11 @@ static void generate_checksum(parser_t *parser, ir_builder *ir) crc = progdefs_crc_both(crc, "\tint\t"); break; } - crc = progdefs_crc_both(crc, value->name); + crc = progdefs_crc_both(crc, value->m_name); crc = progdefs_crc_both(crc, ";\n"); } crc = progdefs_crc_both(crc, "} entvars_t;\n\n"); - ir->code->crc = crc; + ir->m_code->crc = crc; } parser_t *parser_create() @@ -6000,7 +6004,7 @@ parser_t *parser_create() empty_ctx.line = 0; empty_ctx.column = 0; parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL); - parser->nil->cvq = CV_CONST; + parser->nil->m_cvq = CV_CONST; if (OPTS_FLAG(UNTYPED_NIL)) util_htset(parser->htglobals, "nil", (void*)parser->nil); @@ -6012,10 +6016,10 @@ parser_t *parser_create() if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) { parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING); - parser->reserved_version->cvq = CV_CONST; - parser->reserved_version->hasvalue = true; - parser->reserved_version->expression.flags |= AST_FLAG_INCLUDE_DEF; - parser->reserved_version->constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING); + parser->reserved_version->m_cvq = CV_CONST; + parser->reserved_version->m_hasvalue = true; + parser->reserved_version->m_flags |= AST_FLAG_INCLUDE_DEF; + parser->reserved_version->m_constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING); } else { parser->reserved_version = nullptr; } @@ -6084,8 +6088,8 @@ static void parser_remove_ast(parser_t *parser) return; parser->ast_cleaned = true; for (auto &it : parser->accessors) { - ast_delete(it->constval.vfunc); - it->constval.vfunc = nullptr; + ast_delete(it->m_constval.vfunc); + it->m_constval.vfunc = nullptr; ast_delete(it); } for (auto &it : parser->functions) ast_delete(it); @@ -6123,6 +6127,7 @@ static void parser_remove_ast(parser_t *parser) void parser_cleanup(parser_t *parser) { parser_remove_ast(parser); + parser->~parser_t(); mem_d(parser); } @@ -6136,7 +6141,7 @@ static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) { func = nullptr; for (auto &it : parser->functions) { - if (!strcmp(it->name, "coverage")) { + if (!strcmp(it->m_name, "coverage")) { func = it; break; } @@ -6144,24 +6149,24 @@ static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) { if (!func) { if (OPTS_OPTION_BOOL(OPTION_COVERAGE)) { con_out("coverage support requested but no coverage() builtin declared\n"); - ir_builder_delete(ir); + delete ir; return false; } return true; } - cov = func->vtype; + cov = func->m_function_type; expr = (ast_expression*)cov; - if (expr->vtype != TYPE_FUNCTION || expr->params.size()) { + if (expr->m_vtype != TYPE_FUNCTION || expr->m_type_params.size()) { char ty[1024]; ast_type_to_string(expr, ty, sizeof(ty)); con_out("invalid type for coverage(): %s\n", ty); - ir_builder_delete(ir); + delete ir; return false; } - ir->coverage_func = func->ir_func->value; + ir->m_coverage_func = func->m_ir_func->m_value; return true; } @@ -6175,7 +6180,7 @@ bool parser_finish(parser_t *parser, const char *output) return false; } - ir = ir_builder_new("gmqcc_out"); + ir = new ir_builder("gmqcc_out"); if (!ir) { con_out("failed to allocate builder\n"); return false; @@ -6186,24 +6191,24 @@ bool parser_finish(parser_t *parser, const char *output) if (!ast_istype(it, ast_value)) continue; ast_value *field = (ast_value*)it; - hasvalue = field->hasvalue; - field->hasvalue = false; + hasvalue = field->m_hasvalue; + field->m_hasvalue = false; if (!ast_global_codegen((ast_value*)field, ir, true)) { - con_out("failed to generate field %s\n", field->name); - ir_builder_delete(ir); + con_out("failed to generate field %s\n", field->m_name); + delete ir; return false; } if (hasvalue) { ir_value *ifld; ast_expression *subtype; - field->hasvalue = true; - subtype = field->expression.next; - ifld = ir_builder_create_field(ir, field->name, subtype->vtype); - if (subtype->vtype == TYPE_FIELD) - ifld->fieldtype = subtype->next->vtype; - else if (subtype->vtype == TYPE_FUNCTION) - ifld->outtype = subtype->next->vtype; - (void)!ir_value_set_field(field->ir_v, ifld); + field->m_hasvalue = true; + subtype = field->m_next; + ifld = ir_builder_create_field(ir, field->m_name, subtype->m_vtype); + if (subtype->m_vtype == TYPE_FIELD) + ifld->m_fieldtype = subtype->m_next->m_vtype; + else if (subtype->m_vtype == TYPE_FUNCTION) + ifld->m_outtype = subtype->m_next->m_vtype; + (void)!ir_value_set_field(field->m_ir_v, ifld); } } for (auto &it : parser->globals) { @@ -6211,13 +6216,13 @@ bool parser_finish(parser_t *parser, const char *output) if (!ast_istype(it, ast_value)) continue; asvalue = (ast_value*)it; - if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) { - retval = retval && !compile_warning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE, - "unused global: `%s`", asvalue->name); + if (!asvalue->m_uses && !asvalue->m_hasvalue && asvalue->m_vtype != TYPE_FUNCTION) { + retval = retval && !compile_warning(asvalue->m_context, WARN_UNUSED_VARIABLE, + "unused global: `%s`", asvalue->m_name); } if (!ast_global_codegen(asvalue, ir, false)) { - con_out("failed to generate global %s\n", asvalue->name); - ir_builder_delete(ir); + con_out("failed to generate global %s\n", asvalue->m_name); + delete ir; return false; } } @@ -6225,22 +6230,22 @@ bool parser_finish(parser_t *parser, const char *output) * immediates, because the accessors may add new immediates */ for (auto &f : parser->functions) { - if (f->varargs) { - if (parser->max_param_count > f->vtype->expression.params.size()) { - f->varargs->expression.count = parser->max_param_count - f->vtype->expression.params.size(); - if (!parser_create_array_setter_impl(parser, f->varargs)) { - con_out("failed to generate vararg setter for %s\n", f->name); - ir_builder_delete(ir); + if (f->m_varargs) { + if (parser->max_param_count > f->m_function_type->m_type_params.size()) { + f->m_varargs->m_count = parser->max_param_count - f->m_function_type->m_type_params.size(); + if (!parser_create_array_setter_impl(parser, f->m_varargs)) { + con_out("failed to generate vararg setter for %s\n", f->m_name); + delete ir; return false; } - if (!parser_create_array_getter_impl(parser, f->varargs)) { - con_out("failed to generate vararg getter for %s\n", f->name); - ir_builder_delete(ir); + if (!parser_create_array_getter_impl(parser, f->m_varargs)) { + con_out("failed to generate vararg getter for %s\n", f->m_name); + delete ir; return false; } } else { - ast_delete(f->varargs); - f->varargs = nullptr; + ast_delete(f->m_varargs); + f->m_varargs = nullptr; } } } @@ -6255,30 +6260,30 @@ bool parser_finish(parser_t *parser, const char *output) if (!ast_istype(it, ast_value)) continue; ast_value *asvalue = (ast_value*)it; - if (!(asvalue->expression.flags & AST_FLAG_INITIALIZED)) + if (!(asvalue->m_flags & AST_FLAG_INITIALIZED)) { - if (asvalue->cvq == CV_CONST && !asvalue->hasvalue) - (void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_CONSTANT, + if (asvalue->m_cvq == CV_CONST && !asvalue->m_hasvalue) + (void)!compile_warning(asvalue->m_context, WARN_UNINITIALIZED_CONSTANT, "uninitialized constant: `%s`", - asvalue->name); - else if ((asvalue->cvq == CV_NONE || asvalue->cvq == CV_CONST) && !asvalue->hasvalue) - (void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_GLOBAL, + asvalue->m_name); + else if ((asvalue->m_cvq == CV_NONE || asvalue->m_cvq == CV_CONST) && !asvalue->m_hasvalue) + (void)!compile_warning(asvalue->m_context, WARN_UNINITIALIZED_GLOBAL, "uninitialized global: `%s`", - asvalue->name); + asvalue->m_name); } if (!ast_generate_accessors(asvalue, ir)) { - ir_builder_delete(ir); + delete ir; return false; } } for (auto &it : parser->fields) { - ast_value *asvalue = (ast_value*)it->next; + ast_value *asvalue = (ast_value*)it->m_next; if (!ast_istype((ast_expression*)asvalue, ast_value)) continue; - if (asvalue->expression.vtype != TYPE_ARRAY) + if (asvalue->m_vtype != TYPE_ARRAY) continue; if (!ast_generate_accessors(asvalue, ir)) { - ir_builder_delete(ir); + delete ir; return false; } } @@ -6286,13 +6291,13 @@ bool parser_finish(parser_t *parser, const char *output) !ast_global_codegen(parser->reserved_version, ir, false)) { con_out("failed to generate reserved::version"); - ir_builder_delete(ir); + delete ir; return false; } for (auto &f : parser->functions) { if (!ast_function_codegen(f, ir)) { - con_out("failed to generate function %s\n", f->name); - ir_builder_delete(ir); + con_out("failed to generate function %s\n", f->m_name); + delete ir; return false; } } @@ -6302,9 +6307,9 @@ bool parser_finish(parser_t *parser, const char *output) if (OPTS_OPTION_BOOL(OPTION_DUMP)) ir_builder_dump(ir, con_out); for (auto &it : parser->functions) { - if (!ir_function_finalize(it->ir_func)) { - con_out("failed to finalize function %s\n", it->name); - ir_builder_delete(ir); + if (!ir_function_finalize(it->m_ir_func)) { + con_out("failed to finalize function %s\n", it->m_name); + delete ir; return false; } } @@ -6322,10 +6327,10 @@ bool parser_finish(parser_t *parser, const char *output) if (!ir_builder_generate(ir, output)) { con_out("*** failed to generate output file\n"); - ir_builder_delete(ir); + delete ir; return false; } } - ir_builder_delete(ir); + delete ir; return retval; } diff --git a/test.cpp b/test.cpp index 840e6b6..6d783f7 100644 --- a/test.cpp +++ b/test.cpp @@ -76,7 +76,7 @@ static FILE **task_popen(const char *command, const char *mode) { dup2(errhandle[1], 2); execvp(argv[0], &argv[0]); - exit(EXIT_FAILURE); + exit(95); } else { /* fork failed */ goto task_popen_error_3; @@ -98,11 +98,17 @@ static int task_pclose(FILE **handles) { close(data->pipes[1]); /* stdout */ close(data->pipes[2]); /* stderr */ - waitpid(data->pid, &status, 0); + if (data->pid != waitpid(data->pid, &status, 0)) { + abort(); + } + if (!WIFEXITED(status)) + return -1; + if (WIFSIGNALED(status)) + con_out("got signaled!\n"); mem_d(data); - return status; + return status ? 1 : 0; } #define TASK_COMPILE 0 @@ -997,6 +1003,10 @@ static size_t task_schedualize(size_t *pad) { util_snprintf(space[1], sizeof(space[1]), "%d", (int)(i)); con_out("test #%u %*s", i, strlen(space[0]) - strlen(space[1]), ""); + //con_out("[[%*s]]", + // (pad[0] + pad[1] - strlen(it.tmpl->description)) + (strlen(it.tmpl->rulesfile) - pad[1]), + // it.tmpl->rulesfile); + //fflush(stdout); /* * Generate a task from thin air if it requires execution in @@ -1057,6 +1067,16 @@ static size_t task_schedualize(size_t *pad) { } status = task_pclose(it.runhandles); + if (status != 0 && status != 1) { + con_out("compiler failure (returned: %i): `%s` %*s\n", + status, + it.tmpl->description, + (pad[0] + pad[1] - strlen(it.tmpl->description)) + (strlen(it.tmpl->rulesfile) - pad[1]), + it.tmpl->rulesfile + ); + failed++; + continue; + } if ((!strcmp(it.tmpl->proceduretype, "-fail") && status == EXIT_SUCCESS) || ( strcmp(it.tmpl->proceduretype, "-fail") && status == EXIT_FAILURE)) { con_out("failure: `%s` %*s %*s\n", diff --git a/tests/fieldfuncs.qc b/tests/fieldfuncs.qc new file mode 100644 index 0000000..4228f33 --- /dev/null +++ b/tests/fieldfuncs.qc @@ -0,0 +1,13 @@ +.float field; + +.float getfield() { + return field; +} + +void() main = { + entity e = spawn(); + e.field = 42; + print(ftos(e.(getfield())), "\n"); + .float memptr = getfield(); + print(ftos(e.memptr), "\n"); +} diff --git a/tests/fieldfuncs.tmpl b/tests/fieldfuncs.tmpl new file mode 100644 index 0000000..1199b9b --- /dev/null +++ b/tests/fieldfuncs.tmpl @@ -0,0 +1,6 @@ +I: fieldfuncs.qc +D: test fields with functions +T: -compile +C: -std=fte +M: 42 +M: 42 diff --git a/tests/forloop.qc b/tests/forloop.qc new file mode 100644 index 0000000..17512bd --- /dev/null +++ b/tests/forloop.qc @@ -0,0 +1,13 @@ +void main() { + float j; + for (j = 0; j < 2; ++j) + print("+"); + + for (float i = 0; i < 5; ++i) + print("*"); + + for (;;) { + print("\n"); + break; + } +} diff --git a/tests/forloop.tmpl b/tests/forloop.tmpl new file mode 100644 index 0000000..2718dfc --- /dev/null +++ b/tests/forloop.tmpl @@ -0,0 +1,5 @@ +I: forloop.qc +D: test for loops +T: -execute +C: -std=gmqcc +M: ++*****