}
/* weight and side effects */
-void ast_node::propagateSideEffects(ast_node *other) const
+void ast_node::propagateSideEffects(const ast_node *other)
{
- other->m_side_effects = m_side_effects;
+ if (other->m_side_effects)
+ m_side_effects = true;
}
/* General expression initialization */
{
if (OPTS_OPTION_BOOL(OPTION_COVERAGE))
m_flags |= AST_FLAG_BLOCK_COVERAGE;
+ if (OPTS_FLAG(DEFAULT_ERASEABLE))
+ m_flags |= AST_FLAG_ERASEABLE;
}
ast_expression::ast_expression(lex_ctx_t ctx, int nodetype)
: ast_expression(ctx, nodetype, TYPE_VOID)
ast_unary* ast_unary::make(lex_ctx_t ctx, int op, ast_expression *expr)
{
- if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
- ast_unary *prev = (ast_unary*)((ast_unary*)expr)->m_operand;
-
- /* Handle for double negation */
- if (((ast_unary*)expr)->m_op == op)
- prev = (ast_unary*)((ast_unary*)expr)->m_operand;
-
- if (ast_istype(prev, ast_unary)) {
- ++opts_optimizationcount[OPTIM_PEEPHOLE];
- return prev;
+ // handle double negation, double bitwise or logical not
+ if (op == opid2('!','P') ||
+ op == opid2('~','P') ||
+ op == opid2('-','P'))
+ {
+ if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
+ ast_unary *unary = reinterpret_cast<ast_unary*>(expr);
+ if (unary->m_op == op) {
+ auto out = reinterpret_cast<ast_unary*>(unary->m_operand);
+ unary->m_operand = nullptr;
+ delete unary;
+ ++opts_optimizationcount[OPTIM_PEEPHOLE];
+ return out;
+ }
}
}
ast_unref(m_fixedparams);
if (m_return_value)
ast_unref(m_return_value);
+
+ // force this to be cleared before m_varargs/m_argc as blocks might
+ // try to access them via ast_unref()
+ m_blocks.clear();
}
const char* ast_function::makeLabel(const char *prefix)
for (i = 0; i != count; ++i) {
switch (m_next->m_vtype) {
case TYPE_FLOAT:
- if (!ir_value_set_float(m_ir_values[i], m_initlist[i].vfloat))
+ if (!m_ir_values[i]->setFloat(m_initlist[i].vfloat))
return false;
break;
case TYPE_VECTOR:
- if (!ir_value_set_vector(m_ir_values[i], m_initlist[i].vvec))
+ if (!m_ir_values[i]->setVector(m_initlist[i].vvec))
return false;
break;
case TYPE_STRING:
- if (!ir_value_set_string(m_ir_values[i], m_initlist[i].vstring))
+ if (!m_ir_values[i]->setString(m_initlist[i].vstring))
return false;
break;
case TYPE_ARRAY:
compile_error(m_context, "field constant generated before its field");
return false;
}
- if (!ir_value_set_field(m_ir_values[i], m_initlist[i].vfield->m_ir_v))
+ if (!m_ir_values[i]->setField(m_initlist[i].vfield->m_ir_v))
return false;
break;
default:
} else {
// Arrays don't do this since there's no "array" value which spans across the
// whole thing.
- v = ir_builder_create_global(ir, m_name, m_vtype);
+ v = ir->createGlobal(m_name, m_vtype);
if (!v) {
- compile_error(m_context, "ir_builder_create_global failed on `%s`", m_name);
+ compile_error(m_context, "ir_builder::createGlobal failed on `%s`", m_name);
return false;
}
codegen_output_type(this, v);
if (m_flags & AST_FLAG_INCLUDE_DEF)
m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
- if (m_flags & AST_FLAG_ERASEABLE)
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_v->m_flags |= IR_FLAG_NOREF;
/* initialize */
if (m_hasvalue) {
switch (m_vtype)
{
case TYPE_FLOAT:
- if (!ir_value_set_float(v, m_constval.vfloat))
+ if (!v->setFloat(m_constval.vfloat))
return false;
break;
case TYPE_VECTOR:
- if (!ir_value_set_vector(v, m_constval.vvec))
+ if (!v->setVector(m_constval.vvec))
return false;
break;
case TYPE_STRING:
- if (!ir_value_set_string(v, m_constval.vstring))
+ if (!v->setString(m_constval.vstring))
return false;
break;
case TYPE_ARRAY:
compile_error(m_context, "field constant generated before its field");
return false;
}
- if (!ir_value_set_field(v, m_constval.vfield->m_ir_v))
+ if (!v->setField(m_constval.vfield->m_ir_v))
return false;
break;
default:
bool ast_value::generateGlobalFunction(ir_builder *ir)
{
- ir_function *func = ir_builder_create_function(ir, m_name, m_next->m_vtype);
+ ir_function *func = ir->createFunction(m_name, m_next->m_vtype);
if (!func)
return false;
func->m_context = m_context;
m_ir_v = func->m_value;
if (m_flags & AST_FLAG_INCLUDE_DEF)
m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
- if (m_flags & AST_FLAG_ERASEABLE)
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
m_ir_v->m_flags |= IR_FLAG_ERASABLE;
if (m_flags & AST_FLAG_BLOCK_COVERAGE)
func->m_flags |= IR_FLAG_BLOCK_COVERAGE;
ast_expression *elemtype = array->m_next;
qc_type vtype = elemtype->m_vtype;
- ir_value *v = ir_builder_create_field(ir, m_name, vtype);
+ ir_value *v = ir->createField(m_name, vtype);
if (!v) {
- compile_error(m_context, "ir_builder_create_global failed on `%s`", m_name);
+ compile_error(m_context, "ir_builder::createGlobal failed on `%s`", m_name);
return false;
}
v->m_context = m_context;
if (m_flags & AST_FLAG_INCLUDE_DEF)
m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
- if (m_flags & AST_FLAG_ERASEABLE)
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_v->m_flags |= IR_FLAG_NOREF;
const size_t namelen = m_name.length();
std::unique_ptr<char[]> name(new char[namelen+16]);
array->m_ir_values[0] = v;
for (size_t ai = 1; ai < array->m_count; ++ai) {
util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
- array->m_ir_values[ai] = ir_builder_create_field(ir, name.get(), vtype);
+ array->m_ir_values[ai] = ir->createField(name.get(), vtype);
if (!array->m_ir_values[ai]) {
- compile_error(m_context, "ir_builder_create_global failed on `%s`", name.get());
+ compile_error(m_context, "ir_builder::createGlobal failed on `%s`", name.get());
return false;
}
array->m_ir_values[ai]->m_context = m_context;
array->m_ir_values[ai]->m_unique_life = true;
array->m_ir_values[ai]->m_locked = true;
if (m_flags & AST_FLAG_INCLUDE_DEF)
- m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+ array->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+ if (m_flags & AST_FLAG_NOREF)
+ array->m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
}
}
else
{
- ir_value *v = ir_builder_create_field(ir, m_name, m_next->m_vtype);
+ ir_value *v = ir->createField(m_name, m_next->m_vtype);
if (!v)
return false;
v->m_context = m_context;
m_ir_v = v;
if (m_flags & AST_FLAG_INCLUDE_DEF)
m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
-
- if (m_flags & AST_FLAG_ERASEABLE)
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_v->m_flags |= IR_FLAG_NOREF;
}
return true;
}
if (!checkArray(*this))
return nullptr;
- ir_value *v = ir_builder_create_global(ir, m_name, vtype);
+ ir_value *v = ir->createGlobal(m_name, vtype);
if (!v) {
- compile_error(m_context, "ir_builder_create_global failed `%s`", m_name);
+ compile_error(m_context, "ir_builder::createGlobal failed `%s`", m_name);
return nullptr;
}
v->m_context = m_context;
if (m_flags & AST_FLAG_INCLUDE_DEF)
v->m_flags |= IR_FLAG_INCLUDE_DEF;
- if (m_flags & AST_FLAG_ERASEABLE)
- m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
+ v->m_flags |= IR_FLAG_ERASABLE;
+ if (m_flags & AST_FLAG_NOREF)
+ v->m_flags |= IR_FLAG_NOREF;
const size_t namelen = m_name.length();
std::unique_ptr<char[]> name(new char[namelen+16]);
m_ir_values[0] = v;
for (size_t ai = 1; ai < m_count; ++ai) {
util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
- m_ir_values[ai] = ir_builder_create_global(ir, name.get(), vtype);
+ m_ir_values[ai] = ir->createGlobal(name.get(), vtype);
if (!m_ir_values[ai]) {
- compile_error(m_context, "ir_builder_create_global failed `%s`", name.get());
+ compile_error(m_context, "ir_builder::createGlobal failed `%s`", name.get());
return nullptr;
}
m_ir_values[ai]->m_context = m_context;
m_ir_values[ai]->m_locked = true;
if (m_flags & AST_FLAG_INCLUDE_DEF)
m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
}
return v;
v->m_unique_life = true;
v->m_locked = true;
+ if (m_flags & AST_FLAG_NOREF)
+ v->m_flags |= IR_FLAG_NOREF;
+
const size_t namelen = m_name.length();
std::unique_ptr<char[]> name(new char[namelen+16]);
util_strncpy(name.get(), m_name.c_str(), namelen);
util_snprintf(name.get() + namelen, 16, "[%u]", (unsigned int)ai);
m_ir_values[ai] = ir_function_create_local(func, name.get(), vtype, param);
if (!m_ir_values[ai]) {
- compile_error(m_context, "internal_error: ir_builder_create_global failed on `%s`", name.get());
+ compile_error(m_context, "internal_error: ir_builder::createGlobal failed on `%s`", name.get());
return false;
}
m_ir_values[ai]->m_context = m_context;
m_ir_values[ai]->m_unique_life = true;
- m_ir_values[ai]->m_locked = true;
+ m_ir_values[ai]->m_locked = true;
+
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
}
}
else
switch (m_vtype)
{
case TYPE_FLOAT:
- if (!ir_value_set_float(v, m_constval.vfloat))
+ if (!v->setFloat(m_constval.vfloat))
goto error;
break;
case TYPE_VECTOR:
- if (!ir_value_set_vector(v, m_constval.vvec))
+ if (!v->setVector(m_constval.vvec))
goto error;
break;
case TYPE_STRING:
- if (!ir_value_set_string(v, m_constval.vstring))
+ if (!v->setString(m_constval.vstring))
goto error;
break;
default:
v->m_cvq = m_cvq;
m_ir_v = v;
+ if (m_flags & AST_FLAG_NOREF)
+ m_ir_v->m_flags |= IR_FLAG_NOREF;
+
if (!generateAccessors(func->m_owner))
return false;
return true;
/* fill the parameter list */
for (auto &it : m_function_type->m_type_params) {
if (it->m_vtype == TYPE_FIELD)
- vec_push(irf->m_params, it->m_next->m_vtype);
+ irf->m_params.push_back(it->m_next->m_vtype);
else
- vec_push(irf->m_params, it->m_vtype);
+ irf->m_params.push_back(it->m_vtype);
if (!m_builtin) {
if (!it->generateLocal(m_ir_func, true))
return false;
return false;
sub = ir_block_create_binop(m_curblock, m_context,
makeLabel("va_count"), INSTR_SUB_F,
- ir_builder_get_va_count(ir), fixed);
+ ir->get_va_count(), fixed);
if (!sub)
return false;
if (!ir_block_create_store_op(m_curblock, m_context, INSTR_STORE_F,
{
return ir_block_create_return(m_curblock, m_context, nullptr);
}
- else if (vec_size(m_curblock->m_entries) || m_curblock == irf->m_first)
+ else if (m_curblock->m_entries.size() || m_curblock == irf->m_first)
{
if (m_return_value) {
if (!m_return_value->codegen(this, false, &dummy))
return false;
}
/* use the likely flag */
- vec_last(func->m_curblock->m_instr)->m_likely = true;
+ func->m_curblock->m_instr.back()->m_likely = true;
/* enter the right-expression's block */
func->m_curblock = other;
if (!idx->codegen(func, false, &iridx))
return false;
}
+
if (!m_dest->codegen(func, false, &leftr))
return false;
compile_error(m_context, "not an l-value (member access)");
return false;
}
- if (m_outl) {
+ if (lvalue && m_outl) {
*out = m_outl;
return true;
}
+ if (!lvalue && m_outr) {
+ *out = m_outr;
+ return true;
+ }
- if (!m_owner->codegen(func, false, &vec))
+ if (ast_istype(m_owner, ast_entfield)) {
+ ir_value *ent, *field;
+ auto entfield = reinterpret_cast<ast_entfield*>(m_owner);
+ if (!entfield->m_entity->codegen(func, false, &ent))
+ return false;
+ if (!entfield->m_field->codegen(func, false, &vec))
+ return false;
+ field = vec->vectorMember(m_field);
+ if (lvalue) {
+ *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("mefa"),
+ ent, field);
+ } else {
+ *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("mefv"),
+ ent, field, m_vtype);
+ }
+ if (!*out) {
+ compile_error(m_context, "failed to create %s instruction (output type %s)",
+ (lvalue ? "ADDRESS" : "FIELD"),
+ type_name[m_vtype]);
+ return false;
+ }
+ if (lvalue)
+ m_outl = *out;
+ else
+ m_outr = *out;
+ return (*out != nullptr);
+ }
+
+ // Vector member access
+ if (!m_owner->codegen(func, lvalue, &vec))
return false;
if (vec->m_vtype != TYPE_VECTOR &&
!(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR))
{
+ compile_error(m_context, "vector member produced neither vector nor field");
return false;
}
- *out = ir_value_vector_member(vec, m_field);
- m_outl = *out;
+ *out = vec->vectorMember(m_field);
+ if (!*out) {
+ compile_error(m_context, "internal error: failed to create vector member access");
+ return false;
+ }
+ if (lvalue)
+ m_outl = *out;
+ else
+ m_outr = *out;
return (*out != nullptr);
}
if (!m_va_count->codegen(func, false, &va_count))
return false;
if (!ir_block_create_store_op(func->m_curblock, m_context, INSTR_STORE_F,
- ir_builder_get_va_count(builder), va_count))
+ builder->get_va_count(), va_count))
{
return false;
}