};
/* protos */
-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 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,
return false;
}
-static bool GMQCC_WARN vec_ir_block_find(ir_block **vec, ir_block *what, size_t *idx)
+static bool GMQCC_WARN vec_ir_block_find(std::vector<ir_block *> &vec, ir_block *what, size_t *idx)
{
- size_t i;
- size_t len = vec_size(vec);
- for (i = 0; i < len; ++i) {
- if (vec[i] == what) {
- if (idx) *idx = i;
- return true;
- }
+ for (auto &it : vec) {
+ if (it != what)
+ continue;
+ if (idx)
+ *idx = &it - &vec[0];
+ return true;
}
return false;
}
m_extparam_protos.clear();
}
-static ir_function* ir_builder_get_function(ir_builder *self, const char *name)
-{
- return (ir_function*)util_htget(self->m_htfunctions, name);
-}
-
-ir_function* ir_builder_create_function(ir_builder *self, const std::string& name, qc_type outtype)
+ir_function* ir_builder::createFunction(const std::string& name, qc_type outtype)
{
- ir_function *fn = ir_builder_get_function(self, name.c_str());
- if (fn) {
+ ir_function *fn = (ir_function*)util_htget(m_htfunctions, name.c_str());
+ if (fn)
return nullptr;
- }
- fn = new ir_function(self, outtype);
+ fn = new ir_function(this, outtype);
fn->m_name = name;
- self->m_functions.emplace_back(fn);
- util_htset(self->m_htfunctions, name.c_str(), fn);
+ m_functions.emplace_back(fn);
+ util_htset(m_htfunctions, name.c_str(), fn);
- fn->m_value = ir_builder_create_global(self, fn->m_name, TYPE_FUNCTION);
+ fn->m_value = createGlobal(fn->m_name, TYPE_FUNCTION);
if (!fn->m_value) {
delete fn;
return nullptr;
return fn;
}
-static ir_value* ir_builder_get_global(ir_builder *self, const char *name)
-{
- return (ir_value*)util_htget(self->m_htglobals, name);
-}
-
-ir_value* ir_builder_create_global(ir_builder *self, const std::string& name, qc_type vtype)
+ir_value* ir_builder::createGlobal(const std::string& name, qc_type vtype)
{
ir_value *ve;
if (name[0] != '#')
{
- ve = ir_builder_get_global(self, name.c_str());
+ ve = (ir_value*)util_htget(m_htglobals, name.c_str());
if (ve) {
return nullptr;
}
}
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);
+ m_globals.emplace_back(ve);
+ util_htset(m_htglobals, name.c_str(), ve);
return ve;
}
-ir_value* ir_builder_get_va_count(ir_builder *self)
-{
- 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)
+ir_value* ir_builder::get_va_count()
{
- return (ir_value*)util_htget(self->m_htfields, name);
+ if (m_reserved_va_count)
+ return m_reserved_va_count;
+ return (m_reserved_va_count = createGlobal("reserved:va_count", TYPE_FLOAT));
}
-
-ir_value* ir_builder_create_field(ir_builder *self, const std::string& name, qc_type vtype)
+ir_value* ir_builder::createField(const std::string& name, qc_type vtype)
{
- ir_value *ve = ir_builder_get_field(self, name.c_str());
+ ir_value *ve = (ir_value*)util_htget(m_htfields, name.c_str());
if (ve) {
return nullptr;
}
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);
+ m_fields.emplace_back(ve);
+ util_htset(m_htfields, name.c_str(), ve);
return ve;
}
{
for (auto& bp : self->m_blocks) {
ir_block *block = bp.get();
- for (size_t i = 0; i < vec_size(block->m_instr); ++i) {
+ for (size_t i = 0; i < block->m_instr.size(); ++i) {
ir_instr *inst;
inst = block->m_instr[i];
++opts_optimizationcount[OPTIM_PEEPHOLE];
(void)!ir_instr_op(oper, 0, store->_m_ops[0], true);
- vec_remove(block->m_instr, i, 1);
+ block->m_instr.erase(block->m_instr.begin() + i);
delete store;
}
else if (inst->m_opcode == VINSTR_COND)
(void)!ir_instr_op(inst, 0, inot->_m_ops[1], false);
/* remove NOT */
tmp = inot->m_owner;
- for (inotid = 0; inotid < vec_size(tmp->m_instr); ++inotid) {
+ for (inotid = 0; inotid < tmp->m_instr.size(); ++inotid) {
if (tmp->m_instr[inotid] == inot)
break;
}
- if (inotid >= vec_size(tmp->m_instr)) {
+ if (inotid >= tmp->m_instr.size()) {
compile_error(inst->m_context, "sanity-check failed: failed to find instruction to optimize out");
return false;
}
- vec_remove(tmp->m_instr, inotid, 1);
+ tmp->m_instr.erase(tmp->m_instr.begin() + inotid);
delete inot;
/* swap ontrue/onfalse */
tmp = inst->m_bops[0];
ir_value *funcval;
ir_instr *ret, *call, *store = nullptr;
- if (!block->m_final || vec_size(block->m_instr) < 2)
+ if (!block->m_final || block->m_instr.size() < 2)
continue;
- ret = block->m_instr[vec_size(block->m_instr)-1];
+ ret = block->m_instr.back();
if (ret->m_opcode != INSTR_DONE && ret->m_opcode != INSTR_RETURN)
continue;
- call = block->m_instr[vec_size(block->m_instr)-2];
+ call = block->m_instr[block->m_instr.size()-2];
if (call->m_opcode >= INSTR_STORE_F && call->m_opcode <= INSTR_STORE_FNC) {
/* account for the unoptimized
* CALL
* RETURN %tmp
* version
*/
- if (vec_size(block->m_instr) < 3)
+ if (block->m_instr.size() < 3)
continue;
store = call;
- call = block->m_instr[vec_size(block->m_instr)-3];
+ call = block->m_instr[block->m_instr.size()-3];
}
if (call->m_opcode < INSTR_CALL0 || call->m_opcode > INSTR_CALL8)
{
++opts_optimizationcount[OPTIM_PEEPHOLE];
call->_m_ops[0] = store->_m_ops[0];
- vec_remove(block->m_instr, vec_size(block->m_instr) - 2, 1);
+ block->m_instr.erase(block->m_instr.end()-2);
delete store;
}
else
continue;
++opts_optimizationcount[OPTIM_TAIL_RECURSION];
- vec_shrinkby(block->m_instr, 2);
+ block->m_instr.erase(block->m_instr.end()-2, block->m_instr.end());
block->m_final = false; /* open it back up */
if (self->m_builtin)
return true;
+ for (auto& lp : self->m_locals) {
+ ir_value *v = lp.get();
+ if (v->m_reads.empty() && v->m_writes.size() && !(v->m_flags & IR_FLAG_NOREF)) {
+ // if it's a vector check to ensure all it's members are unused before
+ // claiming it's unused, otherwise skip the vector entierly
+ if (v->m_vtype == TYPE_VECTOR)
+ {
+ size_t mask = (1 << 3) - 1, bits = 0;
+ for (size_t i = 0; i < 3; i++)
+ if (!v->m_members[i] || (v->m_members[i]->m_reads.empty()
+ && v->m_members[i]->m_writes.size()))
+ bits |= (1 << i);
+ // all components are unused so just report the vector
+ if (bits == mask && irwarning(v->m_context, WARN_UNUSED_VARIABLE,
+ "unused variable: `%s`", v->m_name.c_str()))
+ return false;
+ else if (bits != mask)
+ // individual components are unused so mention them
+ for (size_t i = 0; i < 3; i++)
+ if ((bits & (1 << i))
+ && irwarning(v->m_context, WARN_UNUSED_COMPONENT,
+ "unused vector component: `%s.%c`", v->m_name.c_str(), "xyz"[i]))
+ return false;
+ }
+ // just a standard variable
+ else if (irwarning(v->m_context, WARN_UNUSED_VARIABLE,
+ "unused variable: `%s`", v->m_name.c_str())) return false;
+ }
+ }
+
if (OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
if (!ir_function_pass_peephole(self)) {
irerror(self->m_context, "generic optimization pass broke something in `%s`", self->m_name.c_str());
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);
+ v->vectorMember(0);
+ v->vectorMember(1);
+ v->vectorMember(2);
}
}
for (auto& vp : self->m_values) {
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);
+ v->vectorMember(0);
+ v->vectorMember(1);
+ v->vectorMember(2);
}
}
ir_block::~ir_block()
{
- 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);
+ for (auto &i : m_instr)
+ delete i;
}
static void ir_block_delete_quick(ir_block* self)
{
- size_t i;
- for (i = 0; i != vec_size(self->m_instr); ++i)
- ir_instr_delete_quick(self->m_instr[i]);
- vec_free(self->m_instr);
+ for (auto &i : self->m_instr)
+ ir_instr_delete_quick(i);
+ self->m_instr.clear();
delete self;
}
{
self->m_phi.clear();
self->m_params.clear();
+ self->_m_ops[0] = nullptr;
+ self->_m_ops[1] = nullptr;
+ self->_m_ops[2] = nullptr;
delete self;
}
*IR Value
*/
-static void ir_value_code_setaddr(ir_value *self, int32_t gaddr)
+void ir_value::setCodeAddress(int32_t 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;
+ m_code.globaladdr = gaddr;
+ if (m_members[0]) m_members[0]->m_code.globaladdr = gaddr;
+ if (m_members[1]) m_members[1]->m_code.globaladdr = gaddr;
+ if (m_members[2]) m_members[2]->m_code.globaladdr = gaddr;
}
-static int32_t ir_value_code_addr(const ir_value *self)
+int32_t ir_value::codeAddress() const
{
- if (self->m_store == store_return)
- return OFS_RETURN + self->m_code.addroffset;
- return self->m_code.globaladdr + self->m_code.addroffset;
+ if (m_store == store_return)
+ return OFS_RETURN + m_code.addroffset;
+ return m_code.globaladdr + m_code.addroffset;
}
ir_value::ir_value(std::string&& name_, store_type store_, qc_type vtype_)
-: m_name(move(name_)),
- m_vtype(vtype_),
- m_store(store_)
+ : m_name(move(name_))
+ , m_vtype(vtype_)
+ , m_store(store_)
{
m_fieldtype = TYPE_VOID;
m_outtype = TYPE_VOID;
m_callparam = false;
}
+ir_value::ir_value(ir_function *owner, std::string&& name, store_type storetype, qc_type vtype)
+ : ir_value(move(name), storetype, vtype)
+{
+ ir_function_collect_value(owner, this);
+}
+
ir_value::~ir_value()
{
size_t i;
/* helper function */
-static ir_value* ir_builder_imm_float(ir_builder *self, float value, bool add_to_list) {
+ir_value* ir_builder::literalFloat(float value, bool add_to_list) {
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;
- self->m_globals.emplace_back(v);
+ m_globals.emplace_back(v);
if (add_to_list)
- self->m_const_floats.emplace_back(v);
+ m_const_floats.emplace_back(v);
return v;
}
-ir_value* ir_value_vector_member(ir_value *self, unsigned int member)
+ir_value* ir_value::vectorMember(unsigned int member)
{
std::string name;
ir_value *m;
if (member >= 3)
return nullptr;
- if (self->m_members[member])
- return self->m_members[member];
+ if (m_members[member])
+ return m_members[member];
- if (!self->m_name.empty()) {
+ if (!m_name.empty()) {
char member_name[3] = { '_', char('x' + member), 0 };
- name = self->m_name + member_name;
+ name = m_name + member_name;
}
- if (self->m_vtype == TYPE_VECTOR)
+ if (m_vtype == TYPE_VECTOR)
{
- m = new ir_value(move(name), self->m_store, TYPE_FLOAT);
+ m = new ir_value(move(name), m_store, TYPE_FLOAT);
if (!m)
return nullptr;
- m->m_context = self->m_context;
+ m->m_context = m_context;
- self->m_members[member] = m;
+ m_members[member] = m;
m->m_code.addroffset = member;
}
- else if (self->m_vtype == TYPE_FIELD)
+ else if (m_vtype == TYPE_FIELD)
{
- if (self->m_fieldtype != TYPE_VECTOR)
+ if (m_fieldtype != TYPE_VECTOR)
return nullptr;
- m = new ir_value(move(name), self->m_store, TYPE_FIELD);
+ m = new ir_value(move(name), m_store, TYPE_FIELD);
if (!m)
return nullptr;
m->m_fieldtype = TYPE_FLOAT;
- m->m_context = self->m_context;
+ m->m_context = m_context;
- self->m_members[member] = m;
+ m_members[member] = m;
m->m_code.addroffset = member;
}
else
{
- irerror(self->m_context, "invalid member access on %s", self->m_name.c_str());
+ irerror(m_context, "invalid member access on %s", m_name.c_str());
return nullptr;
}
- m->m_memberof = self;
+ m->m_memberof = this;
return m;
}
-static GMQCC_INLINE size_t ir_value_sizeof(const ir_value *self)
-{
- if (self->m_vtype == TYPE_FIELD && self->m_fieldtype == TYPE_VECTOR)
+size_t ir_value::size() const {
+ if (m_vtype == TYPE_FIELD && m_fieldtype == TYPE_VECTOR)
return type_sizeof_[TYPE_VECTOR];
- return type_sizeof_[self->m_vtype];
+ return type_sizeof_[m_vtype];
}
-static ir_value* ir_value_out(ir_function *owner, const char *name, store_type storetype, qc_type vtype)
+bool ir_value::setFloat(float f)
{
- 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;
-}
-
-bool ir_value_set_float(ir_value *self, float f)
-{
- if (self->m_vtype != TYPE_FLOAT)
+ if (m_vtype != TYPE_FLOAT)
return false;
- self->m_constval.vfloat = f;
- self->m_hasvalue = true;
+ m_constval.vfloat = f;
+ m_hasvalue = true;
return true;
}
-bool ir_value_set_func(ir_value *self, int f)
+bool ir_value::setFunc(int f)
{
- if (self->m_vtype != TYPE_FUNCTION)
+ if (m_vtype != TYPE_FUNCTION)
return false;
- self->m_constval.vint = f;
- self->m_hasvalue = true;
+ m_constval.vint = f;
+ m_hasvalue = true;
return true;
}
-bool ir_value_set_vector(ir_value *self, vec3_t v)
+bool ir_value::setVector(vec3_t v)
{
- if (self->m_vtype != TYPE_VECTOR)
+ if (m_vtype != TYPE_VECTOR)
return false;
- self->m_constval.vvec = v;
- self->m_hasvalue = true;
+ m_constval.vvec = v;
+ m_hasvalue = true;
return true;
}
-bool ir_value_set_field(ir_value *self, ir_value *fld)
+bool ir_value::setField(ir_value *fld)
{
- if (self->m_vtype != TYPE_FIELD)
+ if (m_vtype != TYPE_FIELD)
return false;
- self->m_constval.vpointer = fld;
- self->m_hasvalue = true;
+ m_constval.vpointer = fld;
+ m_hasvalue = true;
return true;
}
-bool ir_value_set_string(ir_value *self, const char *str)
+bool ir_value::setString(const char *str)
{
- if (self->m_vtype != TYPE_STRING)
+ if (m_vtype != TYPE_STRING)
return false;
- self->m_constval.vstring = util_strdupe(str);
- self->m_hasvalue = true;
+ m_constval.vstring = util_strdupe(str);
+ m_hasvalue = true;
return true;
}
#if 0
-bool ir_value_set_int(ir_value *self, int i)
+bool ir_value::setInt(int i)
{
- if (self->m_vtype != TYPE_INTEGER)
+ if (m_vtype != TYPE_INTEGER)
return false;
- self->m_constval.vint = i;
- self->m_hasvalue = true;
+ m_constval.vint = i;
+ m_hasvalue = true;
return true;
}
#endif
-bool ir_value_lives(ir_value *self, size_t at)
+bool ir_value::lives(size_t at)
{
- for (auto& l : self->m_life) {
+ for (auto& l : m_life) {
if (l.start <= at && at <= l.end)
return true;
if (l.start > at) /* since it's ordered */
return false;
}
-static bool ir_value_life_insert(ir_value *self, size_t idx, ir_life_entry_t e)
+bool ir_value::insertLife(size_t idx, ir_life_entry_t e)
{
- self->m_life.insert(self->m_life.begin() + idx, e);
+ m_life.insert(m_life.begin() + idx, e);
return true;
}
-static bool ir_value_life_merge(ir_value *self, size_t s)
+bool ir_value::setAlive(size_t s)
{
size_t i;
- const size_t vs = self->m_life.size();
+ const size_t vs = m_life.size();
ir_life_entry_t *life_found = nullptr;
ir_life_entry_t *before = nullptr;
ir_life_entry_t new_entry;
for (i = 0; i < vs; ++i)
{
before = life_found;
- life_found = &self->m_life[i];
+ life_found = &m_life[i];
if (life_found->start > s)
break;
}
if (life_found && life_found->end >= s)
return false;
e.start = e.end = s;
- self->m_life.emplace_back(e);
+ m_life.emplace_back(e);
return true;
}
/* found */
{
/* merge */
before->end = life_found->end;
- self->m_life.erase(self->m_life.begin()+i);
+ m_life.erase(m_life.begin()+i);
return true;
}
if (before->end + 1 == s)
}
/* insert a new entry */
new_entry.start = new_entry.end = s;
- return ir_value_life_insert(self, i, new_entry);
+ return insertLife(i, new_entry);
}
-static bool ir_value_life_merge_into(ir_value *self, const ir_value *other)
+bool ir_value::mergeLife(const ir_value *other)
{
size_t i, myi;
if (other->m_life.empty())
return true;
- if (self->m_life.empty()) {
- self->m_life = other->m_life;
+ if (m_life.empty()) {
+ m_life = other->m_life;
return true;
}
const ir_life_entry_t &otherlife = other->m_life[i];
while (true)
{
- ir_life_entry_t *entry = &self->m_life[myi];
+ ir_life_entry_t *entry = &m_life[myi];
if (otherlife.end+1 < entry->start)
{
/* adding an interval before entry */
- if (!ir_value_life_insert(self, myi, otherlife))
+ if (!insertLife(myi, otherlife))
return false;
++myi;
break;
}
/* see if our change combines it with the next ranges */
- while (myi+1 < self->m_life.size() &&
- entry->end+1 >= self->m_life[1+myi].start)
+ while (myi+1 < m_life.size() &&
+ entry->end+1 >= m_life[1+myi].start)
{
/* overlaps with (myi+1) */
- 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];
+ if (entry->end < m_life[1+myi].end)
+ entry->end = m_life[1+myi].end;
+ m_life.erase(m_life.begin() + (myi + 1));
+ entry = &m_life[myi];
}
/* see if we're after the entry */
{
++myi;
/* append if we're at the end */
- if (myi >= self->m_life.size()) {
- self->m_life.emplace_back(otherlife);
+ if (myi >= m_life.size()) {
+ m_life.emplace_back(otherlife);
break;
}
/* otherweise check the next range */
delete in;
return false;
}
- vec_push(self->m_instr, in);
+ self->m_instr.push_back(in);
return true;
}
delete in;
return false;
}
- vec_push(self->m_instr, in);
+ self->m_instr.push_back(in);
return true;
}
return false;
}
- vec_push(self->m_instr, in);
+ self->m_instr.push_back(in);
return true;
}
in->m_bops[0] = ontrue;
in->m_bops[1] = onfalse;
- vec_push(self->m_instr, in);
+ self->m_instr.push_back(in);
- vec_push(self->m_exits, ontrue);
- vec_push(self->m_exits, onfalse);
- vec_push(ontrue->m_entries, self);
- vec_push(onfalse->m_entries, self);
+ self->m_exits.push_back(ontrue);
+ self->m_exits.push_back(onfalse);
+ ontrue->m_entries.push_back(self);
+ onfalse->m_entries.push_back(self);
return true;
}
return false;
in->m_bops[0] = to;
- vec_push(self->m_instr, in);
+ self->m_instr.push_back(in);
- vec_push(self->m_exits, to);
- vec_push(to->m_entries, self);
+ self->m_exits.push_back(to);
+ to->m_entries.push_back(self);
return true;
}
in = new ir_instr(ctx, self, VINSTR_PHI);
if (!in)
return nullptr;
- out = ir_value_out(self->m_owner, label, store_value, ot);
+ out = new ir_value(self->m_owner, label ? label : "", store_value, ot);
if (!out) {
delete in;
return nullptr;
delete in;
return nullptr;
}
- vec_push(self->m_instr, in);
+ self->m_instr.push_back(in);
return in;
}
self->m_final = true;
self->m_is_return = true;
}
- out = ir_value_out(self->m_owner, label, (func->m_outtype == TYPE_VOID) ? store_return : store_value, func->m_outtype);
+ out = new ir_value(self->m_owner, label ? label : "", (func->m_outtype == TYPE_VOID) ? store_return : store_value, func->m_outtype);
if (!out) {
delete in;
return nullptr;
delete in;
return nullptr;
}
- vec_push(self->m_instr, in);
+ self->m_instr.push_back(in);
/*
if (noreturn) {
if (!ir_block_create_return(self, ctx, nullptr)) {
ir_instr *instr;
ir_value *out;
- out = ir_value_out(self->m_owner, label, store_value, outype);
+ out = new ir_value(self->m_owner, label ? label : "", store_value, outype);
if (!out)
return nullptr;
goto on_error;
}
- vec_push(self->m_instr, instr);
+ self->m_instr.push_back(instr);
return out;
on_error:
* to a list so we don't need to loop through blocks
* - anyway: "don't optimize YET"
*/
- for (i = 0; i < vec_size(self->m_instr); ++i)
+ for (i = 0; i < self->m_instr.size(); ++i)
{
ir_instr *instr = self->m_instr[i];
if (instr->m_opcode != VINSTR_PHI)
continue;
- vec_remove(self->m_instr, i, 1);
+ self->m_instr.erase(self->m_instr.begin()+i);
--i; /* NOTE: i+1 below */
for (auto &it : instr->m_phi) {
return false;
} else {
/* force a move instruction */
- ir_instr *prevjump = vec_last(b->m_instr);
- vec_pop(b->m_instr);
+ ir_instr *prevjump = b->m_instr.back();
+ b->m_instr.pop_back();
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->_m_ops[0]->m_store = store_value;
- vec_push(b->m_instr, prevjump);
+ b->m_instr.push_back(prevjump);
b->m_final = true;
}
}
*/
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->m_instr); ++i)
- {
- self->m_instr[i]->m_eid = eid++;
- }
+ for (auto &i : self->m_instr)
+ i->m_eid = eid++;
*_eid = eid;
}
* This is the counterpart to register-allocation in register machines.
*/
struct function_allocator {
- ir_value **locals;
- size_t *sizes;
- size_t *positions;
- bool *unique;
+ std::vector<std::unique_ptr<ir_value>> locals;
+ std::vector<size_t> sizes;
+ std::vector<size_t> positions;
+ std::vector<bool> unique;
};
static bool function_allocator_alloc(function_allocator *alloc, ir_value *var)
{
ir_value *slot;
- size_t vsize = ir_value_sizeof(var);
+ size_t vsize = var->size();
- var->m_code.local = vec_size(alloc->locals);
+ var->m_code.local = alloc->locals.size();
slot = new ir_value("reg", store_global, var->m_vtype);
if (!slot)
return false;
- if (!ir_value_life_merge_into(slot, var))
+ if (!slot->mergeLife(var))
goto localerror;
- vec_push(alloc->locals, slot);
- vec_push(alloc->sizes, vsize);
- vec_push(alloc->unique, var->m_unique_life);
+ alloc->locals.emplace_back(slot);
+ alloc->sizes.push_back(vsize);
+ alloc->unique.push_back(var->m_unique_life);
return true;
static bool ir_function_allocator_assign(ir_function *self, function_allocator *alloc, ir_value *v)
{
size_t a;
- ir_value *slot;
if (v->m_unique_life)
return function_allocator_alloc(alloc, v);
- for (a = 0; a < vec_size(alloc->locals); ++a)
+ for (a = 0; a < alloc->locals.size(); ++a)
{
/* if it's reserved for a unique liferange: skip */
if (alloc->unique[a])
continue;
- slot = alloc->locals[a];
+ ir_value *slot = alloc->locals[a].get();
/* never resize parameters
* will be required later when overlapping temps + locals
*/
if (a < vec_size(self->m_params) &&
- alloc->sizes[a] < ir_value_sizeof(v))
+ alloc->sizes[a] < v->size())
{
continue;
}
if (ir_values_overlap(v, slot))
continue;
- if (!ir_value_life_merge_into(slot, v))
+ if (!slot->mergeLife(v))
return false;
/* adjust size for this slot */
- if (alloc->sizes[a] < ir_value_sizeof(v))
- alloc->sizes[a] = ir_value_sizeof(v);
+ if (alloc->sizes[a] < v->size())
+ alloc->sizes[a] = v->size();
v->m_code.local = a;
return true;
}
- if (a >= vec_size(alloc->locals)) {
+ if (a >= alloc->locals.size()) {
if (!function_allocator_alloc(alloc, v))
return false;
}
bool ir_function_allocate_locals(ir_function *self)
{
- bool retval = true;
size_t pos;
bool opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS);
if (self->m_locals.empty() && self->m_values.empty())
return true;
- globalloc.locals = nullptr;
- globalloc.sizes = nullptr;
- globalloc.positions = nullptr;
- globalloc.unique = nullptr;
- lockalloc.locals = nullptr;
- lockalloc.sizes = nullptr;
- lockalloc.positions = nullptr;
- lockalloc.unique = nullptr;
-
size_t i;
for (i = 0; i < self->m_locals.size(); ++i)
{
else
v->m_locked = true; /* lock parameters locals */
if (!function_allocator_alloc((v->m_locked || !opt_gt ? &lockalloc : &globalloc), v))
- goto error;
+ return false;
}
for (; i < self->m_locals.size(); ++i)
{
if (v->m_life.empty())
continue;
if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v))
- goto error;
+ return false;
}
/* Allocate a slot for any value that still exists */
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;
+ return false;
}
++opts_optimizationcount[OPTIM_CALL_STORES];
v->m_callparam = true;
if (param < 8)
- ir_value_code_setaddr(v, OFS_PARM0 + 3*param);
+ v->setCodeAddress(OFS_PARM0 + 3*param);
else {
size_t nprotos = self->m_owner->m_extparam_protos.size();
ir_value *ep;
ep = self->m_owner->m_extparam_protos[param].get();
else
{
- ep = ir_gen_extparam_proto(self->m_owner);
+ ep = self->m_owner->generateExtparamProto();
while (++nprotos <= param)
- ep = ir_gen_extparam_proto(self->m_owner);
+ ep = self->m_owner->generateExtparamProto();
}
ir_instr_op(v->m_writes[0], 0, ep, true);
call->m_params[param+8] = ep;
}
if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v))
- goto error;
+ return false;
}
- if (!lockalloc.sizes && !globalloc.sizes) {
- goto cleanup;
- }
- vec_push(lockalloc.positions, 0);
- vec_push(globalloc.positions, 0);
+ if (lockalloc.sizes.empty() && globalloc.sizes.empty())
+ return true;
+
+ lockalloc.positions.push_back(0);
+ globalloc.positions.push_back(0);
/* Adjust slot positions based on sizes */
- if (lockalloc.sizes) {
- pos = (vec_size(lockalloc.sizes) ? lockalloc.positions[0] : 0);
- for (i = 1; i < vec_size(lockalloc.sizes); ++i)
+ if (!lockalloc.sizes.empty()) {
+ pos = (lockalloc.sizes.size() ? lockalloc.positions[0] : 0);
+ for (i = 1; i < lockalloc.sizes.size(); ++i)
{
pos = lockalloc.positions[i-1] + lockalloc.sizes[i-1];
- vec_push(lockalloc.positions, pos);
+ lockalloc.positions.push_back(pos);
}
- self->m_allocated_locals = pos + vec_last(lockalloc.sizes);
+ self->m_allocated_locals = pos + lockalloc.sizes.back();
}
- if (globalloc.sizes) {
- pos = (vec_size(globalloc.sizes) ? globalloc.positions[0] : 0);
- for (i = 1; i < vec_size(globalloc.sizes); ++i)
+ if (!globalloc.sizes.empty()) {
+ pos = (globalloc.sizes.size() ? globalloc.positions[0] : 0);
+ for (i = 1; i < globalloc.sizes.size(); ++i)
{
pos = globalloc.positions[i-1] + globalloc.sizes[i-1];
- vec_push(globalloc.positions, pos);
+ globalloc.positions.push_back(pos);
}
- self->m_globaltemps = pos + vec_last(globalloc.sizes);
+ self->m_globaltemps = pos + globalloc.sizes.back();
}
/* Locals need to know their new position */
value->m_code.local = globalloc.positions[value->m_code.local];
}
- goto cleanup;
-
-error:
- retval = false;
-cleanup:
- for (i = 0; i < vec_size(lockalloc.locals); ++i)
- delete lockalloc.locals[i];
- for (i = 0; i < vec_size(globalloc.locals); ++i)
- delete globalloc.locals[i];
- vec_free(globalloc.unique);
- vec_free(globalloc.locals);
- vec_free(globalloc.sizes);
- vec_free(globalloc.positions);
- vec_free(lockalloc.unique);
- vec_free(lockalloc.locals);
- vec_free(lockalloc.sizes);
- vec_free(lockalloc.positions);
- return retval;
+ return true;
}
/* Get information about which operand
static bool ir_block_living_add_instr(ir_block *self, size_t eid) {
bool changed = false;
for (auto &it : self->m_living)
- if (ir_value_life_merge(it, eid))
+ if (it->setAlive(eid))
changed = true;
return changed;
}
{
ir_instr *instr;
ir_value *value;
- size_t i, o, p, mem;
+ size_t i, o, mem;
// bitmasks which operands are read from or written to
size_t read, write;
self->m_living.clear();
- p = vec_size(self->m_exits);
- for (i = 0; i < p; ++i) {
- ir_block *prev = self->m_exits[i];
+ for (auto &prev : self->m_exits) {
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->m_instr);
+ i = self->m_instr.size();
while (i)
{ --i;
instr = self->m_instr[i];
* since this function is run multiple times.
*/
/* con_err( "Value only written %s\n", value->m_name); */
- if (ir_value_life_merge(value, instr->m_eid))
+ if (value->setAlive(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->m_eid))
+ if (value->setAlive(instr->m_eid))
*changed = true;
// Then remove
self->m_living.erase(self->m_living.begin() + idx);
/* Removing a vector removes all members */
for (mem = 0; mem < 3; ++mem) {
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))
+ if (value->m_members[mem]->setAlive(instr->m_eid))
*changed = true;
self->m_living.erase(self->m_living.begin() + idx);
}
break;
}
if (mem == 3 && vec_ir_value_find(self->m_living, value, &idx)) {
- if (ir_value_life_merge(value, instr->m_eid))
+ if (value->setAlive(instr->m_eid))
*changed = true;
self->m_living.erase(self->m_living.begin() + idx);
}
{
value = instr->_m_ops[2];
/* the float source will get an additional lifetime */
- if (ir_value_life_merge(value, instr->m_eid+1))
+ if (value->setAlive(instr->m_eid+1))
*changed = true;
- if (value->m_memberof && ir_value_life_merge(value->m_memberof, instr->m_eid+1))
+ if (value->m_memberof && value->m_memberof->setAlive(instr->m_eid+1))
*changed = true;
}
{
value = instr->_m_ops[1];
/* the float source will get an additional lifetime */
- if (ir_value_life_merge(value, instr->m_eid+1))
+ if (value->setAlive(instr->m_eid+1))
*changed = true;
- if (value->m_memberof && ir_value_life_merge(value->m_memberof, instr->m_eid+1))
+ if (value->m_memberof && value->m_memberof->setAlive(instr->m_eid+1))
*changed = true;
}
{
/* parameters live at 0 */
for (size_t i = 0; i < vec_size(self->m_params); ++i)
- if (!ir_value_life_merge(self->m_locals[i].get(), 0))
+ if (!self->m_locals[i].get()->setAlive(0))
compile_error(self->m_context, "internal error: failed value-life merging");
bool changed;
*
* Breaking conventions is annoying...
*/
-static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal);
-
static bool gen_global_field(code_t *code, ir_value *global)
{
if (global->m_hasvalue)
}
/* copy the field's value */
- ir_value_code_setaddr(global, code->globals.size());
+ global->setCodeAddress(code->globals.size());
code->globals.push_back(fld->m_code.fieldaddr);
if (global->m_fieldtype == TYPE_VECTOR) {
code->globals.push_back(fld->m_code.fieldaddr+1);
}
else
{
- ir_value_code_setaddr(global, code->globals.size());
+ global->setCodeAddress(code->globals.size());
code->globals.push_back(0);
if (global->m_fieldtype == TYPE_VECTOR) {
code->globals.push_back(0);
return false;
}
- ir_value_code_setaddr(global, code->globals.size());
+ global->setCodeAddress(code->globals.size());
code->globals.push_back(target->m_code.globaladdr);
}
else
{
- ir_value_code_setaddr(global, code->globals.size());
+ global->setCodeAddress(code->globals.size());
code->globals.push_back(0);
}
if (global->m_code.globaladdr < 0)
block->m_generated = true;
block->m_code_start = code->statements.size();
- for (i = 0; i < vec_size(block->m_instr); ++i)
+ for (i = 0; i < block->m_instr.size(); ++i)
{
instr = block->m_instr[i];
if (instr->m_opcode == VINSTR_BITXOR) {
stmt.opcode = INSTR_BITOR;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress();
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
stmt.opcode = INSTR_BITAND;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress();
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
stmt.opcode = INSTR_SUB_F;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[0]->codeAddress();
+ stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
/* instruction generated */
if (instr->m_opcode == VINSTR_BITAND_V) {
stmt.opcode = INSTR_BITAND;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress();
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
++stmt.o1.s1;
++stmt.o2.s1;
if (instr->m_opcode == VINSTR_BITOR_V) {
stmt.opcode = INSTR_BITOR;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress();
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
++stmt.o1.s1;
++stmt.o2.s1;
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->_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;
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j;
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress() + j;
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress() + j;
code_push_statement(code, &stmt, instr->m_context);
stmt.opcode = INSTR_BITAND;
- 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;
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j;
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress() + j;
+ stmt.o3.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress() + j;
code_push_statement(code, &stmt, instr->m_context);
}
stmt.opcode = INSTR_SUB_V;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[0]->codeAddress();
+ stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
/* instruction generated */
if (instr->m_opcode == VINSTR_BITAND_VF) {
stmt.opcode = INSTR_BITAND;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress();
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
++stmt.o1.s1;
++stmt.o3.s1;
if (instr->m_opcode == VINSTR_BITOR_VF) {
stmt.opcode = INSTR_BITOR;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress();
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
++stmt.o1.s1;
++stmt.o3.s1;
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->_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;
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j;
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress() + j;
code_push_statement(code, &stmt, instr->m_context);
stmt.opcode = INSTR_BITAND;
- 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;
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + j;
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress();
+ stmt.o3.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress() + j;
code_push_statement(code, &stmt, instr->m_context);
}
stmt.opcode = INSTR_SUB_V;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[0]->codeAddress();
+ stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
/* instruction generated */
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->_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;
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + (j + 1) % 3;
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress() + (j + 2) % 3;
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress() + 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;
+ stmt.o1.s1 = instr->_m_ops[1]->codeAddress() + (j + 2) % 3;
+ stmt.o2.s1 = instr->_m_ops[2]->codeAddress() + (j + 1) % 3;
+ stmt.o3.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress() + j;
code_push_statement(code, &stmt, instr->m_context);
}
stmt.opcode = INSTR_SUB_V;
- 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]);
+ stmt.o1.s1 = instr->_m_ops[0]->codeAddress();
+ stmt.o2.s1 = func->m_owner->m_vinstr_temp[0]->codeAddress();
+ stmt.o3.s1 = instr->_m_ops[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
/* instruction generated */
* come first: eg. optimize IFs without ELSE...
*/
- stmt.o1.u1 = ir_value_code_addr(instr->_m_ops[0]);
+ stmt.o1.u1 = instr->_m_ops[0]->codeAddress();
stmt.o2.u1 = 0;
stmt.o3.s1 = 0;
stmt.opcode = INSTR_STORE_V;
else
stmt.opcode = type_store_instr[param->m_vtype];
- stmt.o1.u1 = ir_value_code_addr(param);
+ stmt.o1.u1 = param->codeAddress();
stmt.o2.u1 = OFS_PARM0 + 3 * p;
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->m_members[0]);
+ stmt.o1.u1 = param->m_members[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
stmt.o2.u1++;
- stmt.o1.u1 = ir_value_code_addr(param->m_members[1]);
+ stmt.o1.u1 = param->m_members[1]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
stmt.o2.u1++;
- stmt.o1.u1 = ir_value_code_addr(param->m_members[2]);
+ stmt.o1.u1 = param->m_members[2]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
}
else
continue;
if (p-8 >= ir->m_extparams.size())
- ir_gen_extparam(ir);
+ ir->generateExtparam();
targetparam = ir->m_extparams[p-8];
stmt.opcode = INSTR_STORE_V;
else
stmt.opcode = type_store_instr[param->m_vtype];
- stmt.o1.u1 = ir_value_code_addr(param);
- stmt.o2.u1 = ir_value_code_addr(targetparam);
+ stmt.o1.u1 = param->codeAddress();
+ stmt.o2.u1 = targetparam->codeAddress();
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->m_members[0]);
+ stmt.o1.u1 = param->m_members[0]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
stmt.o2.u1++;
- stmt.o1.u1 = ir_value_code_addr(param->m_members[1]);
+ stmt.o1.u1 = param->m_members[1]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
stmt.o2.u1++;
- stmt.o1.u1 = ir_value_code_addr(param->m_members[2]);
+ stmt.o1.u1 = param->m_members[2]->codeAddress();
code_push_statement(code, &stmt, instr->m_context);
}
else
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->_m_ops[1]);
+ stmt.o1.u1 = instr->_m_ops[1]->codeAddress();
stmt.o2.u1 = 0;
stmt.o3.u1 = 0;
code_push_statement(code, &stmt, instr->m_context);
else
stmt.opcode = type_store_instr[retvalue->m_vtype];
stmt.o1.u1 = OFS_RETURN;
- stmt.o2.u1 = ir_value_code_addr(retvalue);
+ stmt.o2.u1 = retvalue->codeAddress();
stmt.o3.u1 = 0;
code_push_statement(code, &stmt, instr->m_context);
}
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]);
+ stmt.o1.u1 = instr->_m_ops[0]->codeAddress();
if (instr->_m_ops[1])
- stmt.o2.u1 = ir_value_code_addr(instr->_m_ops[1]);
+ stmt.o2.u1 = instr->_m_ops[1]->codeAddress();
stmt.o3.u1 = 0;
code_push_statement(code, &stmt, instr->m_context);
continue;
/* This is the general order of operands */
if (instr->_m_ops[0])
- stmt.o3.u1 = ir_value_code_addr(instr->_m_ops[0]);
+ stmt.o3.u1 = instr->_m_ops[0]->codeAddress();
if (instr->_m_ops[1])
- stmt.o1.u1 = ir_value_code_addr(instr->_m_ops[1]);
+ stmt.o1.u1 = instr->_m_ops[1]->codeAddress();
if (instr->_m_ops[2])
- stmt.o2.u1 = ir_value_code_addr(instr->_m_ops[2]);
+ stmt.o2.u1 = instr->_m_ops[2]->codeAddress();
if (stmt.opcode == INSTR_RETURN || stmt.opcode == INSTR_DONE)
{
return true;
}
-static qcint_t ir_builder_filestring(ir_builder *ir, const char *filename)
+qcint_t ir_builder::filestring(const char *filename)
{
/* NOTE: filename pointers are copied, we never strdup them,
* thus we can use pointer-comparison to find the string.
*/
qcint_t str;
- for (size_t i = 0; i != ir->m_filenames.size(); ++i) {
- if (!strcmp(ir->m_filenames[i], filename))
+ for (size_t i = 0; i != m_filenames.size(); ++i) {
+ if (!strcmp(m_filenames[i], filename))
return i;
}
- str = code_genstring(ir->m_code.get(), filename);
- ir->m_filenames.push_back(filename);
- ir->m_filestrings.push_back(str);
+ str = code_genstring(m_code.get(), filename);
+ m_filenames.push_back(filename);
+ m_filestrings.push_back(str);
return str;
}
-static bool gen_global_function(ir_builder *ir, ir_value *global)
+bool ir_builder::generateGlobalFunction(ir_value *global)
{
prog_section_function_t fun;
ir_function *irfun;
irfun = global->m_constval.vfunc;
fun.name = global->m_code.name;
- fun.file = ir_builder_filestring(ir, global->m_context.file);
+ fun.file = filestring(global->m_context.file);
fun.profile = 0; /* always 0 */
fun.nargs = vec_size(irfun->m_params);
if (fun.nargs > 8)
if (irfun->m_builtin)
fun.entry = irfun->m_builtin+1;
else {
- irfun->m_code_function_def = ir->m_code->functions.size();
- fun.entry = ir->m_code->statements.size();
+ irfun->m_code_function_def = m_code->functions.size();
+ fun.entry = m_code->statements.size();
}
- ir->m_code->functions.push_back(fun);
+ m_code->functions.push_back(fun);
return true;
}
-static ir_value* ir_gen_extparam_proto(ir_builder *ir)
+ir_value* ir_builder::generateExtparamProto()
{
char name[128];
- util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(ir->m_extparam_protos.size()));
+ util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(m_extparam_protos.size()));
ir_value *global = new ir_value(name, store_global, TYPE_VECTOR);
- ir->m_extparam_protos.emplace_back(global);
+ m_extparam_protos.emplace_back(global);
return global;
}
-static void ir_gen_extparam(ir_builder *ir)
+void ir_builder::generateExtparam()
{
prog_section_def_t def;
ir_value *global;
- if (ir->m_extparam_protos.size() < ir->m_extparams.size()+1)
- global = ir_gen_extparam_proto(ir);
+ if (m_extparam_protos.size() < m_extparams.size()+1)
+ global = generateExtparamProto();
else
- global = ir->m_extparam_protos[ir->m_extparams.size()].get();
+ global = m_extparam_protos[m_extparams.size()].get();
- def.name = code_genstring(ir->m_code.get(), global->m_name.c_str());
+ def.name = code_genstring(m_code.get(), global->m_name.c_str());
def.type = TYPE_VECTOR;
- def.offset = ir->m_code->globals.size();
+ def.offset = m_code->globals.size();
- ir->m_code->defs.push_back(def);
+ m_code->defs.push_back(def);
- ir_value_code_setaddr(global, def.offset);
+ global->setCodeAddress(def.offset);
- ir->m_code->globals.push_back(0);
- ir->m_code->globals.push_back(0);
- ir->m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
- ir->m_extparams.emplace_back(global);
+ m_extparams.emplace_back(global);
}
static bool gen_function_extparam_copy(code_t *code, ir_function *self)
for (size_t i = 8; i < numparams; ++i) {
size_t ext = i - 8;
if (ext >= ir->m_extparams.size())
- ir_gen_extparam(ir);
+ ir->generateExtparam();
ir_value *ep = ir->m_extparams[ext];
{
stmt.opcode = INSTR_STORE_V;
}
- stmt.o1.u1 = ir_value_code_addr(ep);
- stmt.o2.u1 = ir_value_code_addr(self->m_locals[i].get());
+ stmt.o1.u1 = ep->codeAddress();
+ stmt.o2.u1 = self->m_locals[i].get()->codeAddress();
code_push_statement(code, &stmt, self->m_context);
}
for (i = numparams; i < maxparams; ++i) {
if (i < 8) {
stmt.o1.u1 = OFS_PARM0 + 3*i;
- stmt.o2.u1 = ir_value_code_addr(self->m_locals[i].get());
+ stmt.o2.u1 = self->m_locals[i].get()->codeAddress();
code_push_statement(code, &stmt, self->m_context);
continue;
}
ext = i - 8;
while (ext >= ir->m_extparams.size())
- ir_gen_extparam(ir);
+ ir->generateExtparam();
ep = ir->m_extparams[ext];
- stmt.o1.u1 = ir_value_code_addr(ep);
- stmt.o2.u1 = ir_value_code_addr(self->m_locals[i].get());
+ stmt.o1.u1 = ep->codeAddress();
+ stmt.o2.u1 = self->m_locals[i].get()->codeAddress();
code_push_statement(code, &stmt, self->m_context);
}
return true;
}
-static bool gen_function_locals(ir_builder *ir, ir_value *global)
+bool ir_builder::generateFunctionLocals(ir_value *global)
{
prog_section_function_t *def;
ir_function *irfun;
uint32_t firstlocal, firstglobal;
irfun = global->m_constval.vfunc;
- def = &ir->m_code->functions[0] + irfun->m_code_function_def;
+ def = &m_code->functions[0] + irfun->m_code_function_def;
if (OPTS_OPTION_BOOL(OPTION_G) ||
!OPTS_OPTIMIZATION(OPTIM_OVERLAP_LOCALS) ||
(irfun->m_flags & IR_FLAG_MASK_NO_OVERLAP))
{
- firstlocal = def->firstlocal = ir->m_code->globals.size();
+ firstlocal = def->firstlocal = m_code->globals.size();
} else {
- firstlocal = def->firstlocal = ir->m_first_common_local;
+ firstlocal = def->firstlocal = m_first_common_local;
++opts_optimizationcount[OPTIM_OVERLAP_LOCALS];
}
- firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? ir->m_first_common_globaltemp : firstlocal);
+ firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? 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 (size_t i = m_code->globals.size(); i < firstlocal + irfun->m_allocated_locals; ++i)
+ m_code->globals.push_back(0);
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)) {
+ v->setCodeAddress(firstlocal + v->m_code.local);
+ if (!generateGlobal(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->m_code.local);
+ v->setCodeAddress(firstglobal + v->m_code.local);
}
for (auto& vp : irfun->m_values) {
ir_value *v = vp.get();
if (v->m_callparam)
continue;
if (v->m_locked)
- ir_value_code_setaddr(v, firstlocal + v->m_code.local);
+ v->setCodeAddress(firstlocal + v->m_code.local);
else
- ir_value_code_setaddr(v, firstglobal + v->m_code.local);
+ v->setCodeAddress(firstglobal + v->m_code.local);
}
return true;
}
-static bool gen_global_function_code(ir_builder *ir, ir_value *global)
+bool ir_builder::generateGlobalFunctionCode(ir_value *global)
{
prog_section_function_t *fundef;
ir_function *irfun;
- (void)ir;
-
irfun = global->m_constval.vfunc;
if (!irfun) {
if (global->m_cvq == CV_NONE) {
irerror(irfun->m_context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->m_name.c_str());
return false;
}
- fundef = &ir->m_code->functions[irfun->m_code_function_def];
+ fundef = &m_code->functions[irfun->m_code_function_def];
- fundef->entry = ir->m_code->statements.size();
- if (!gen_function_locals(ir, global)) {
+ fundef->entry = m_code->statements.size();
+ if (!generateFunctionLocals(global)) {
irerror(irfun->m_context, "Failed to generate locals for function %s", irfun->m_name.c_str());
return false;
}
- if (!gen_function_extparam_copy(ir->m_code.get(), irfun)) {
+ if (!gen_function_extparam_copy(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->m_max_varargs && !gen_function_varargs_copy(ir->m_code.get(), irfun)) {
+ if (irfun->m_max_varargs && !gen_function_varargs_copy(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->m_code.get(), irfun)) {
+ if (!gen_function_code(m_code.get(), irfun)) {
irerror(irfun->m_context, "Failed to generate code for function %s", irfun->m_name.c_str());
return false;
}
mem_d(component);
}
-static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal)
+bool ir_builder::generateGlobal(ir_value *global, bool islocal)
{
size_t i;
int32_t *iptr;
return true;
def.type = global->m_vtype;
- def.offset = self->m_code->globals.size();
+ def.offset = m_code->globals.size();
def.name = 0;
if (OPTS_OPTION_BOOL(OPTION_G) || !islocal)
{
if (pushdef) {
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;
+ if (!m_str_immediate)
+ m_str_immediate = code_genstring(m_code.get(), "IMMEDIATE");
+ def.name = global->m_code.name = m_str_immediate;
}
else
- def.name = global->m_code.name = code_genstring(self->m_code.get(), global->m_name.c_str());
+ def.name = global->m_code.name = code_genstring(m_code.get(), global->m_name.c_str());
}
else
def.name = 0;
if (islocal) {
- def.offset = ir_value_code_addr(global);
- self->m_code->defs.push_back(def);
+ def.offset = global->codeAddress();
+ 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());
+ gen_vector_defs(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());
+ gen_vector_defs(m_code.get(), def, global->m_name.c_str());
return true;
}
}
* 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->m_code->globals.size());
- self->m_code->globals.push_back(0);
+ global->setCodeAddress(m_code->globals.size());
+ m_code->globals.push_back(0);
/* Add the def */
- if (pushdef) self->m_code->defs.push_back(def);
+ if (pushdef)
+ m_code->defs.push_back(def);
return true;
case TYPE_POINTER:
- if (pushdef) self->m_code->defs.push_back(def);
- return gen_global_pointer(self->m_code.get(), global);
+ if (pushdef)
+ m_code->defs.push_back(def);
+ return gen_global_pointer(m_code.get(), global);
case TYPE_FIELD:
if (pushdef) {
- self->m_code->defs.push_back(def);
+ 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());
+ gen_vector_defs(m_code.get(), def, global->m_name.c_str());
}
- return gen_global_field(self->m_code.get(), global);
+ return gen_global_field(m_code.get(), global);
case TYPE_ENTITY:
/* fall through */
case TYPE_FLOAT:
{
- ir_value_code_setaddr(global, self->m_code->globals.size());
+ global->setCodeAddress(m_code->globals.size());
if (global->m_hasvalue) {
+ if (global->m_cvq == CV_CONST && global->m_reads.empty())
+ return true;
iptr = (int32_t*)&global->m_constval.ivec[0];
- self->m_code->globals.push_back(*iptr);
+ m_code->globals.push_back(*iptr);
} else {
- self->m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
}
if (!islocal && global->m_cvq != CV_CONST)
def.type |= DEF_SAVEGLOBAL;
- if (pushdef) self->m_code->defs.push_back(def);
+ if (pushdef)
+ m_code->defs.push_back(def);
return global->m_code.globaladdr >= 0;
}
case TYPE_STRING:
{
- ir_value_code_setaddr(global, self->m_code->globals.size());
+ global->setCodeAddress(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);
+ if (global->m_cvq == CV_CONST && global->m_reads.empty())
+ return true;
+ uint32_t load = code_genstring(m_code.get(), global->m_constval.vstring);
+ m_code->globals.push_back(load);
} else {
- self->m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
}
if (!islocal && global->m_cvq != CV_CONST)
def.type |= DEF_SAVEGLOBAL;
- if (pushdef) self->m_code->defs.push_back(def);
+ if (pushdef)
+ m_code->defs.push_back(def);
return global->m_code.globaladdr >= 0;
}
case TYPE_VECTOR:
{
size_t d;
- ir_value_code_setaddr(global, self->m_code->globals.size());
+ global->setCodeAddress(m_code->globals.size());
if (global->m_hasvalue) {
iptr = (int32_t*)&global->m_constval.ivec[0];
- self->m_code->globals.push_back(iptr[0]);
+ m_code->globals.push_back(iptr[0]);
if (global->m_code.globaladdr < 0)
return false;
for (d = 1; d < type_sizeof_[global->m_vtype]; ++d) {
- self->m_code->globals.push_back(iptr[d]);
+ m_code->globals.push_back(iptr[d]);
}
} else {
- self->m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
if (global->m_code.globaladdr < 0)
return false;
for (d = 1; d < type_sizeof_[global->m_vtype]; ++d) {
- self->m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
}
}
if (!islocal && global->m_cvq != CV_CONST)
def.type |= DEF_SAVEGLOBAL;
if (pushdef) {
- self->m_code->defs.push_back(def);
+ m_code->defs.push_back(def);
def.type &= ~DEF_SAVEGLOBAL;
- gen_vector_defs(self->m_code.get(), def, global->m_name.c_str());
+ gen_vector_defs(m_code.get(), def, global->m_name.c_str());
}
return global->m_code.globaladdr >= 0;
}
case TYPE_FUNCTION:
- ir_value_code_setaddr(global, self->m_code->globals.size());
+ global->setCodeAddress(m_code->globals.size());
if (!global->m_hasvalue) {
- self->m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
if (global->m_code.globaladdr < 0)
return false;
} else {
- self->m_code->globals.push_back(self->m_code->functions.size());
- if (!gen_global_function(self, global))
+ m_code->globals.push_back(m_code->functions.size());
+ if (!generateGlobalFunction(global))
return false;
}
if (!islocal && global->m_cvq != CV_CONST)
def.type |= DEF_SAVEGLOBAL;
- if (pushdef) self->m_code->defs.push_back(def);
+ if (pushdef)
+ m_code->defs.push_back(def);
return true;
case TYPE_VARIANT:
/* assume biggest type */
- ir_value_code_setaddr(global, self->m_code->globals.size());
- self->m_code->globals.push_back(0);
+ global->setCodeAddress(m_code->globals.size());
+ m_code->globals.push_back(0);
for (i = 1; i < type_sizeof_[TYPE_VARIANT]; ++i)
- self->m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
return true;
default:
/* refuse to create 'void' type or any other fancy business. */
self->m_code->fields.push_back(fld);
- ir_value_code_setaddr(field, self->m_code->globals.size());
+ field->setCodeAddress(self->m_code->globals.size());
self->m_code->globals.push_back(fld.offset);
if (fld.type == TYPE_VECTOR) {
self->m_code->globals.push_back(fld.offset+1);
// generate floats for not yet found components
if (!found[0])
- found[0] = ir_builder_imm_float(self, vec->m_constval.vvec.x, true);
+ found[0] = self->literalFloat(vec->m_constval.vvec.x, true);
if (!found[1]) {
if (vec->m_constval.vvec.y == vec->m_constval.vvec.x)
found[1] = found[0];
else
- found[1] = ir_builder_imm_float(self, vec->m_constval.vvec.y, true);
+ found[1] = self->literalFloat(vec->m_constval.vvec.y, true);
}
if (!found[2]) {
if (vec->m_constval.vvec.z == vec->m_constval.vvec.x)
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->m_constval.vvec.z, true);
+ found[2] = self->literalFloat(vec->m_constval.vvec.z, true);
}
// the .members array should be safe to use here
}
}
-bool ir_builder_generate(ir_builder *self, const char *filename)
+bool ir_builder::generate(const char *filename)
{
prog_section_statement_t stmt;
char *lnofile = nullptr;
if (OPTS_FLAG(SPLIT_VECTOR_PARAMETERS)) {
- ir_builder_collect_reusables(self);
- if (!self->m_const_floats.empty())
- ir_builder_split_vectors(self);
+ ir_builder_collect_reusables(this);
+ if (!m_const_floats.empty())
+ ir_builder_split_vectors(this);
}
- for (auto& fp : self->m_fields)
- ir_builder_prepare_field(self->m_code.get(), fp.get());
+ for (auto& fp : m_fields)
+ ir_builder_prepare_field(m_code.get(), fp.get());
- for (auto& gp : self->m_globals) {
+ for (auto& gp : m_globals) {
ir_value *global = gp.get();
- if (!ir_builder_gen_global(self, global, false)) {
+ if (!generateGlobal(global, false)) {
return false;
}
if (global->m_vtype == TYPE_FUNCTION) {
ir_function *func = global->m_constval.vfunc;
- if (func && self->m_max_locals < func->m_allocated_locals &&
+ if (func && m_max_locals < func->m_allocated_locals &&
!(func->m_flags & IR_FLAG_MASK_NO_OVERLAP))
{
- self->m_max_locals = func->m_allocated_locals;
+ m_max_locals = func->m_allocated_locals;
}
- if (func && self->m_max_globaltemps < func->m_globaltemps)
- self->m_max_globaltemps = func->m_globaltemps;
+ if (func && m_max_globaltemps < func->m_globaltemps)
+ m_max_globaltemps = func->m_globaltemps;
}
}
- for (auto& fp : self->m_fields) {
- if (!ir_builder_gen_field(self, fp.get()))
+ for (auto& fp : m_fields) {
+ if (!ir_builder_gen_field(this, fp.get()))
return false;
}
// 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);
+ m_nil->setCodeAddress(m_code->globals.size());
+ m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
+ 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);
+ m_vinstr_temp[i]->setCodeAddress(m_code->globals.size());
+ m_code->globals.push_back(0);
+ m_code->globals.push_back(0);
+ 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);
+ m_first_common_globaltemp = m_code->globals.size();
+ m_code->globals.insert(m_code->globals.end(), m_max_globaltemps, 0);
// FIXME:DELME:
- //for (size_t i = 0; i < self->m_max_globaltemps; ++i) {
- // self->m_code->globals.push_back(0);
+ //for (size_t i = 0; i < m_max_globaltemps; ++i) {
+ // 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);
+ m_first_common_local = m_code->globals.size();
+ m_code->globals.insert(m_code->globals.end(), m_max_locals, 0);
// FIXME:DELME:
- //for (i = 0; i < self->m_max_locals; ++i) {
- // self->m_code->globals.push_back(0);
+ //for (i = 0; i < m_max_locals; ++i) {
+ // m_code->globals.push_back(0);
//}
// generate function code
- for (auto& gp : self->m_globals) {
+ for (auto& gp : m_globals) {
ir_value *global = gp.get();
if (global->m_vtype == TYPE_FUNCTION) {
- if (!gen_global_function_code(self, global)) {
+ if (!this->generateGlobalFunctionCode(global))
return false;
- }
}
}
- if (self->m_code->globals.size() >= 65536) {
- irerror(self->m_globals.back()->m_context,
+ if (m_code->globals.size() >= 65536) {
+ irerror(m_globals.back()->m_context,
"This progs file would require more globals than the metadata can handle (%zu). Bailing out.",
- self->m_code->globals.size());
+ m_code->globals.size());
return false;
}
/* DP errors if the last instruction is not an INSTR_DONE. */
- if (self->m_code->statements.back().opcode != INSTR_DONE)
+ if (m_code->statements.back().opcode != INSTR_DONE)
{
lex_ctx_t last;
stmt.o1.u1 = 0;
stmt.o2.u1 = 0;
stmt.o3.u1 = 0;
- last.line = self->m_code->linenums.back();
- last.column = self->m_code->columnnums.back();
+ last.line = m_code->linenums.back();
+ last.column = m_code->columnnums.back();
- code_push_statement(self->m_code.get(), &stmt, last);
+ code_push_statement(m_code.get(), &stmt, last);
}
if (OPTS_OPTION_BOOL(OPTION_PP_ONLY))
return true;
- if (self->m_code->statements.size() != self->m_code->linenums.size()) {
+ if (m_code->statements.size() != m_code->linenums.size()) {
con_err("Linecounter wrong: %lu != %lu\n",
- self->m_code->statements.size(),
- self->m_code->linenums.size());
+ m_code->statements.size(),
+ m_code->linenums.size());
} else if (OPTS_FLAG(LNO)) {
char *dot;
size_t filelen = strlen(filename);
memcpy(vec_add(lnofile, 5), ".lno", 5);
}
- if (!code_write(self->m_code.get(), filename, lnofile)) {
+ if (!code_write(m_code.get(), filename, lnofile)) {
vec_free(lnofile);
return false;
}
}
}
-void ir_builder_dump(ir_builder *b, int (*oprintf)(const char*, ...))
+void ir_builder::dump(int (*oprintf)(const char*, ...)) const
{
size_t i;
char indent[IND_BUFSZ];
indent[0] = '\t';
indent[1] = 0;
- oprintf("module %s\n", b->m_name.c_str());
- for (i = 0; i < b->m_globals.size(); ++i)
+ oprintf("module %s\n", m_name.c_str());
+ for (i = 0; i < m_globals.size(); ++i)
{
oprintf("global ");
- 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);
+ if (m_globals[i]->m_hasvalue)
+ oprintf("%s = ", m_globals[i]->m_name.c_str());
+ m_globals[i].get()->dump(oprintf);
oprintf("\n");
}
- 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());
+ for (i = 0; i < m_functions.size(); ++i)
+ ir_function_dump(m_functions[i].get(), indent, oprintf);
+ oprintf("endmodule %s\n", m_name.c_str());
}
static const char *storenames[] = {
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->m_locals[i].get(), oprintf);
+ f->m_locals[i].get()->dump(oprintf);
oprintf("\n");
}
}
void ir_block_dump(ir_block* b, char *ind,
int (*oprintf)(const char*, ...))
{
- size_t i;
oprintf("%s:%s\n", ind, b->m_label.c_str());
util_strncat(ind, "\t", IND_BUFSZ-1);
- if (b->m_instr && b->m_instr[0])
+ if (!b->m_instr.empty() && 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);
+ for (auto &i : b->m_instr)
+ ir_instr_dump(i, ind, oprintf);
ind[strlen(ind)-1] = 0;
}
util_strncat(ind, "\t", IND_BUFSZ-1);
if (in->_m_ops[0] && (in->_m_ops[1] || in->_m_ops[2])) {
- ir_value_dump(in->_m_ops[0], oprintf);
+ in->_m_ops[0]->dump(oprintf);
if (in->_m_ops[1] || in->_m_ops[2])
oprintf(" <- ");
}
oprintf("%s\t", qc_opname(in->m_opcode));
if (in->_m_ops[0] && !(in->_m_ops[1] || in->_m_ops[2])) {
- ir_value_dump(in->_m_ops[0], oprintf);
+ in->_m_ops[0]->dump(oprintf);
comma = ",\t";
}
else
if (in->_m_ops[i]) {
if (comma)
oprintf(comma);
- ir_value_dump(in->_m_ops[i], oprintf);
+ in->_m_ops[i]->dump(oprintf);
comma = ",\t";
}
}
oprintf("\"");
}
-void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
+void ir_value::dump(int (*oprintf)(const char*, ...)) const
{
- if (v->m_hasvalue) {
- switch (v->m_vtype) {
+ if (m_hasvalue) {
+ switch (m_vtype) {
default:
case TYPE_VOID:
oprintf("(void)");
break;
case TYPE_FUNCTION:
- oprintf("fn:%s", v->m_name.c_str());
+ oprintf("fn:%s", m_name.c_str());
break;
case TYPE_FLOAT:
- oprintf("%g", v->m_constval.vfloat);
+ oprintf("%g", m_constval.vfloat);
break;
case TYPE_VECTOR:
oprintf("'%g %g %g'",
- v->m_constval.vvec.x,
- v->m_constval.vvec.y,
- v->m_constval.vvec.z);
+ m_constval.vvec.x,
+ m_constval.vvec.y,
+ m_constval.vvec.z);
break;
case TYPE_ENTITY:
oprintf("(entity)");
break;
case TYPE_STRING:
- ir_value_dump_string(v->m_constval.vstring, oprintf);
+ ir_value_dump_string(m_constval.vstring, oprintf);
break;
#if 0
case TYPE_INTEGER:
- oprintf("%i", v->m_constval.vint);
+ oprintf("%i", m_constval.vint);
break;
#endif
case TYPE_POINTER:
oprintf("&%s",
- v->m_constval.vpointer->m_name.c_str());
+ m_constval.vpointer->m_name.c_str());
break;
}
} else {
- oprintf("%s", v->m_name.c_str());
+ oprintf("%s", m_name.c_str());
}
}
-void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...))
+void ir_value::dumpLife(int (*oprintf)(const char*,...)) const
{
- oprintf("Life of %12s:", self->m_name.c_str());
- for (size_t i = 0; i < self->m_life.size(); ++i)
+ oprintf("Life of %12s:", m_name.c_str());
+ for (size_t i = 0; i < m_life.size(); ++i)
{
- oprintf(" + [%i, %i]\n", self->m_life[i].start, self->m_life[i].end);
+ oprintf(" + [%i, %i]\n", m_life[i].start, m_life[i].end);
}
}