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;
+ }
}
}
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);
m_ir_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_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;
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;
m_ir_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_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)
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;
+ 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;
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,
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))
- return false;
+ 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);
+ } else {
+ if (!m_owner->codegen(func, false, &vec))
+ return false;
+ }
if (vec->m_vtype != TYPE_VECTOR &&
!(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR))
return false;
}
- *out = ir_value_vector_member(vec, m_field);
+ *out = vec->vectorMember(m_field);
m_outl = *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;
}