2021-01-17 18:08:18 -05:00
|
|
|
#include "Form.h"
|
2021-01-19 21:45:17 -05:00
|
|
|
|
2021-03-17 19:26:35 -04:00
|
|
|
#include <algorithm>
|
2021-01-19 21:45:17 -05:00
|
|
|
#include <utility>
|
2022-06-22 23:37:46 -04:00
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
#include "common/goos/PrettyPrinter.h"
|
2021-02-13 11:32:52 -05:00
|
|
|
#include "common/type_system/TypeSystem.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
#include "common/util/print_float.h"
|
|
|
|
|
|
|
|
#include "decompiler/ObjectFile/LinkedObjectFile.h"
|
2021-03-17 19:26:35 -04:00
|
|
|
#include "decompiler/util/DecompilerTypeSystem.h"
|
2021-07-01 21:38:19 -04:00
|
|
|
#include "decompiler/util/data_decompile.h"
|
2022-01-15 20:01:38 -05:00
|
|
|
#include "decompiler/util/sparticle_decompile.h"
|
2021-01-17 18:08:18 -05:00
|
|
|
|
|
|
|
namespace decompiler {
|
|
|
|
|
|
|
|
///////////////////
|
|
|
|
// FormPool
|
|
|
|
///////////////////
|
|
|
|
|
|
|
|
FormPool::~FormPool() {
|
|
|
|
for (auto& x : m_forms) {
|
|
|
|
delete x;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& x : m_elements) {
|
|
|
|
delete x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 20:50:37 -05:00
|
|
|
///////////////////
|
|
|
|
// FormElement
|
|
|
|
///////////////////
|
|
|
|
|
|
|
|
std::string FormElement::to_string(const Env& env) const {
|
|
|
|
return to_form(env).print();
|
|
|
|
}
|
|
|
|
|
2021-01-23 16:32:56 -05:00
|
|
|
void FormElement::push_to_stack(const Env& env, FormPool&, FormStack&) {
|
2021-07-05 16:07:07 -04:00
|
|
|
throw std::runtime_error(fmt::format("push_to_stack not implemented for {}: {}", to_string(env),
|
|
|
|
typeid(*this).name()));
|
2021-01-22 20:50:37 -05:00
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object FormElement::to_form_as_condition_internal(const Env& env) const {
|
2021-01-27 15:39:50 -05:00
|
|
|
return to_form(env);
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
bool FormElement::active() const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object FormElement::to_form(const Env& env) const {
|
|
|
|
if (active()) {
|
|
|
|
return to_form_internal(env);
|
|
|
|
} else {
|
|
|
|
return pretty_print::build_list("empty-form");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
///////////////////
|
|
|
|
// Form
|
|
|
|
//////////////////
|
|
|
|
|
|
|
|
goos::Object Form::to_form(const Env& env) const {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(!m_elements.empty());
|
2021-01-17 18:08:18 -05:00
|
|
|
if (m_elements.size() == 1) {
|
|
|
|
return m_elements.front()->to_form(env);
|
|
|
|
} else {
|
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
forms.push_back(pretty_print::to_symbol("begin"));
|
|
|
|
for (auto& x : m_elements) {
|
2021-02-11 14:35:28 -05:00
|
|
|
if (x->active()) {
|
|
|
|
forms.push_back(x->to_form_internal(env));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (forms.size() == 2) {
|
|
|
|
return forms.at(1);
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-27 15:39:50 -05:00
|
|
|
goos::Object Form::to_form_as_condition(const Env& env) const {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(!m_elements.empty());
|
2021-01-27 15:39:50 -05:00
|
|
|
if (m_elements.size() == 1) {
|
2021-02-11 14:35:28 -05:00
|
|
|
return m_elements.front()->to_form_as_condition_internal(env);
|
2021-01-27 15:39:50 -05:00
|
|
|
} else {
|
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
forms.push_back(pretty_print::to_symbol("begin"));
|
|
|
|
for (size_t i = 0; i < m_elements.size(); i++) {
|
|
|
|
const auto& x = m_elements.at(i);
|
|
|
|
if (i == m_elements.size() - 1) {
|
2021-02-11 14:35:28 -05:00
|
|
|
forms.push_back(x->to_form_as_condition_internal(env));
|
2021-01-27 15:39:50 -05:00
|
|
|
} else {
|
2021-02-11 14:35:28 -05:00
|
|
|
if (x->active()) {
|
|
|
|
forms.push_back(x->to_form_internal(env));
|
|
|
|
}
|
2021-01-27 15:39:50 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 20:50:37 -05:00
|
|
|
std::string Form::to_string(const Env& env) const {
|
|
|
|
return to_form(env).print();
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
void Form::inline_forms(std::vector<goos::Object>& forms, const Env& env) const {
|
|
|
|
for (auto& x : m_elements) {
|
2021-02-11 14:35:28 -05:00
|
|
|
if (x->active()) {
|
|
|
|
forms.push_back(x->to_form_internal(env));
|
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Form::apply(const std::function<void(FormElement*)>& f) {
|
2021-01-27 13:47:54 -05:00
|
|
|
for (size_t i = 0; i < m_elements.size(); i++) {
|
|
|
|
m_elements.at(i)->apply(f);
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Form::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& x : m_elements) {
|
|
|
|
x->apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void Form::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
for (auto e : m_elements) {
|
2021-03-05 18:48:01 -05:00
|
|
|
e->collect_vars(vars, recursive);
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void Form::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto e : m_elements) {
|
|
|
|
e->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// SimpleExpressionElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-01-23 16:32:56 -05:00
|
|
|
SimpleExpressionElement::SimpleExpressionElement(SimpleExpression expr, int my_idx)
|
|
|
|
: m_expr(std::move(expr)), m_my_idx(my_idx) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object SimpleExpressionElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return m_expr.to_form(env.file->labels, env);
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleExpressionElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleExpressionElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
|
|
|
bool SimpleExpressionElement::is_sequence_point() const {
|
|
|
|
throw std::runtime_error("Should not check if a SimpleExpressionElement is a sequence point");
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void SimpleExpressionElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
m_expr.collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void SimpleExpressionElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
(void)regs;
|
|
|
|
}
|
|
|
|
|
2021-01-19 21:45:17 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// StoreElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
StoreElement::StoreElement(const StoreOp* op) : m_op(op) {}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object StoreElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return m_op->to_form(env.file->labels, env);
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void StoreElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void StoreElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
return m_op->collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void StoreElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
(void)regs;
|
|
|
|
}
|
|
|
|
|
2021-01-19 21:45:17 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// LoadSourceElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2022-09-11 14:17:55 -04:00
|
|
|
LoadSourceElement::LoadSourceElement(Form* addr,
|
|
|
|
int size,
|
|
|
|
LoadVarOp::Kind kind,
|
|
|
|
const std::optional<IR2_RegOffset>& load_source_ro,
|
|
|
|
const TP_Type& ro_reg_type)
|
|
|
|
: m_addr(addr),
|
|
|
|
m_size(size),
|
|
|
|
m_kind(kind),
|
|
|
|
m_load_source_ro(load_source_ro),
|
|
|
|
m_ro_reg_type(ro_reg_type) {
|
2021-01-19 21:45:17 -05:00
|
|
|
m_addr->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object LoadSourceElement::to_form_internal(const Env& env) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case LoadVarOp::Kind::FLOAT:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(m_size == 4);
|
2021-01-19 21:45:17 -05:00
|
|
|
return pretty_print::build_list("l.f", m_addr->to_form(env));
|
|
|
|
case LoadVarOp::Kind::UNSIGNED:
|
|
|
|
switch (m_size) {
|
|
|
|
case 1:
|
|
|
|
return pretty_print::build_list("l.bu", m_addr->to_form(env));
|
|
|
|
case 2:
|
|
|
|
return pretty_print::build_list("l.hu", m_addr->to_form(env));
|
|
|
|
case 4:
|
|
|
|
return pretty_print::build_list("l.wu", m_addr->to_form(env));
|
|
|
|
case 8:
|
|
|
|
return pretty_print::build_list("l.d", m_addr->to_form(env));
|
2021-03-27 15:18:59 -04:00
|
|
|
case 16:
|
|
|
|
return pretty_print::build_list("l.q", m_addr->to_form(env));
|
2021-01-19 21:45:17 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return {};
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LoadVarOp::Kind::SIGNED:
|
|
|
|
switch (m_size) {
|
|
|
|
case 1:
|
|
|
|
return pretty_print::build_list("l.b", m_addr->to_form(env));
|
|
|
|
case 2:
|
|
|
|
return pretty_print::build_list("l.h", m_addr->to_form(env));
|
|
|
|
case 4:
|
|
|
|
return pretty_print::build_list("l.w", m_addr->to_form(env));
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return {};
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
break;
|
2021-03-27 15:18:59 -04:00
|
|
|
case LoadVarOp::Kind::VECTOR_FLOAT:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(m_size == 16);
|
2021-03-27 15:18:59 -04:00
|
|
|
return pretty_print::build_list("l.vf", m_addr->to_form(env));
|
|
|
|
break;
|
2021-01-19 21:45:17 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return {};
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadSourceElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_addr->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadSourceElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_addr->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void LoadSourceElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_addr->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void LoadSourceElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_addr->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-01-19 21:45:17 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// SimpleAtomElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-09-28 19:24:09 -04:00
|
|
|
SimpleAtomElement::SimpleAtomElement(const SimpleAtom& atom, bool omit_var_cast)
|
|
|
|
: m_atom(atom), m_omit_var_cast(omit_var_cast) {
|
|
|
|
if (m_omit_var_cast) {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(atom.is_var());
|
2021-09-28 19:24:09 -04:00
|
|
|
}
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object SimpleAtomElement::to_form_internal(const Env& env) const {
|
2021-09-28 19:24:09 -04:00
|
|
|
if (m_omit_var_cast) {
|
|
|
|
return m_atom.var().to_form(env, RegisterAccess::Print::AS_VARIABLE_NO_CAST);
|
|
|
|
}
|
2021-02-01 20:41:37 -05:00
|
|
|
return m_atom.to_form(env.file->labels, env);
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAtomElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAtomElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void SimpleAtomElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
return m_atom.collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void SimpleAtomElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
(void)regs;
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// SetVarElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-28 12:38:29 -05:00
|
|
|
SetVarElement::SetVarElement(const RegisterAccess& var,
|
2021-02-11 16:13:03 -05:00
|
|
|
Form* value,
|
|
|
|
bool is_sequence_point,
|
2021-03-13 16:10:39 -05:00
|
|
|
TypeSpec src_type,
|
2021-02-11 16:13:03 -05:00
|
|
|
const SetVarInfo& info)
|
2021-03-13 16:10:39 -05:00
|
|
|
: m_dst(var),
|
|
|
|
m_src(value),
|
|
|
|
m_is_sequence_point(is_sequence_point),
|
2021-03-17 19:26:35 -04:00
|
|
|
m_src_type(std::move(src_type)),
|
2021-03-13 16:10:39 -05:00
|
|
|
m_var_info(info) {
|
2021-01-17 18:08:18 -05:00
|
|
|
value->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object SetVarElement::to_form_internal(const Env& env) const {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(active());
|
2021-03-17 19:26:35 -04:00
|
|
|
auto reg_kind = m_dst.reg().get_kind();
|
2021-03-22 20:04:00 -04:00
|
|
|
if ((reg_kind == Reg::FPR || reg_kind == Reg::GPR) && env.has_type_analysis() &&
|
|
|
|
env.has_local_vars()) {
|
2021-03-17 19:26:35 -04:00
|
|
|
auto expected_type = env.get_variable_type(m_dst, true);
|
|
|
|
if (!env.dts->ts.tc(expected_type, m_src_type)) {
|
|
|
|
return pretty_print::build_list(
|
2021-04-18 12:08:08 -04:00
|
|
|
"set!", m_dst.to_form(env, RegisterAccess::Print::AS_VARIABLE_NO_CAST),
|
2021-03-17 19:26:35 -04:00
|
|
|
pretty_print::build_list("the-as", expected_type.print(), m_src->to_form(env)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-14 20:46:54 -04:00
|
|
|
return pretty_print::build_list(
|
|
|
|
"set!", m_dst.to_form(env, RegisterAccess::Print::AS_VARIABLE_NO_CAST), m_src->to_form(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
2021-05-30 19:57:11 -04:00
|
|
|
std::optional<TypeSpec> SetVarElement::required_cast(const Env& env) const {
|
|
|
|
auto expected_type = env.get_variable_type(m_dst, true);
|
|
|
|
if (!env.dts->ts.tc(expected_type, m_src_type)) {
|
|
|
|
return expected_type;
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
void SetVarElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_src->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetVarElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_src->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SetVarElement::is_sequence_point() const {
|
|
|
|
return m_is_sequence_point;
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void SetVarElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-02-22 09:36:30 -05:00
|
|
|
if (m_var_info.is_dead_set || m_var_info.is_dead_false) {
|
|
|
|
return;
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
vars.insert(m_dst);
|
2021-03-05 18:48:01 -05:00
|
|
|
if (recursive) {
|
|
|
|
m_src->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void SetVarElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
regs.insert(m_dst.reg());
|
|
|
|
m_src->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
bool SetVarElement::active() const {
|
|
|
|
if (is_eliminated_coloring_move() || is_dead_false_set()) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 20:52:25 -05:00
|
|
|
StoreInSymbolElement::StoreInSymbolElement(std::string sym_name,
|
|
|
|
SimpleExpression value,
|
|
|
|
std::optional<TypeSpec> cast_for_set,
|
|
|
|
std::optional<TypeSpec> cast_for_define,
|
|
|
|
int my_idx)
|
|
|
|
: m_sym_name(std::move(sym_name)),
|
|
|
|
m_value(std::move(value)),
|
|
|
|
m_cast_for_set(std::move(cast_for_set)),
|
|
|
|
m_cast_for_define(std::move(cast_for_define)),
|
|
|
|
m_my_idx(my_idx) {}
|
2021-02-18 11:35:45 -05:00
|
|
|
|
|
|
|
goos::Object StoreInSymbolElement::to_form_internal(const Env& env) const {
|
2021-03-03 20:52:25 -05:00
|
|
|
if (m_cast_for_set) {
|
|
|
|
return pretty_print::build_list(
|
|
|
|
"set!", m_sym_name,
|
|
|
|
pretty_print::build_list(fmt::format("the-as {}", m_cast_for_set->print()),
|
|
|
|
m_value.to_form(env.file->labels, env)));
|
|
|
|
} else {
|
|
|
|
return pretty_print::build_list("set!", m_sym_name, m_value.to_form(env.file->labels, env));
|
|
|
|
}
|
2021-02-18 11:35:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void StoreInSymbolElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreInSymbolElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void StoreInSymbolElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-02-18 11:35:45 -05:00
|
|
|
m_value.collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreInSymbolElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
|
|
|
StoreInPairElement::StoreInPairElement(bool is_car,
|
2021-02-28 12:38:29 -05:00
|
|
|
RegisterAccess pair,
|
2021-02-18 11:35:45 -05:00
|
|
|
SimpleExpression value,
|
|
|
|
int my_idx)
|
|
|
|
: m_is_car(is_car), m_pair(pair), m_value(value), m_my_idx(my_idx) {}
|
|
|
|
|
|
|
|
goos::Object StoreInPairElement::to_form_internal(const Env& env) const {
|
|
|
|
return pretty_print::build_list(
|
|
|
|
"set!", pretty_print::build_list(m_is_car ? "car" : "cdr", m_pair.to_form(env)),
|
|
|
|
m_value.to_form(env.file->labels, env));
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreInPairElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreInPairElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void StoreInPairElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-02-18 11:35:45 -05:00
|
|
|
m_value.collect_vars(vars);
|
|
|
|
vars.insert(m_pair);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreInPairElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// SetFormFormElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-03-03 20:52:25 -05:00
|
|
|
SetFormFormElement::SetFormFormElement(Form* dst,
|
|
|
|
Form* src,
|
|
|
|
std::optional<TypeSpec> cast_for_set,
|
|
|
|
std::optional<TypeSpec> cast_for_define)
|
|
|
|
: m_dst(dst),
|
|
|
|
m_src(src),
|
|
|
|
m_cast_for_set(std::move(cast_for_set)),
|
|
|
|
m_cast_for_define(std::move(cast_for_define)) {
|
2021-02-09 20:59:14 -05:00
|
|
|
m_dst->parent_element = this;
|
|
|
|
m_src->parent_element = this;
|
|
|
|
}
|
2021-01-27 13:47:54 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object SetFormFormElement::to_form_internal(const Env& env) const {
|
2021-03-03 20:52:25 -05:00
|
|
|
if (m_cast_for_set) {
|
|
|
|
return pretty_print::build_list(
|
|
|
|
fmt::format("set!"), m_dst->to_form(env),
|
|
|
|
pretty_print::build_list(fmt::format("the-as {}", m_cast_for_set->print()),
|
|
|
|
m_src->to_form(env)));
|
|
|
|
} else {
|
|
|
|
std::vector<goos::Object> forms = {pretty_print::to_symbol("set!"), m_dst->to_form(env),
|
|
|
|
m_src->to_form(env)};
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-23 00:32:07 -04:00
|
|
|
goos::Object SetFormFormElement::to_form_for_define(
|
|
|
|
const Env& env,
|
|
|
|
const std::optional<std::string>& docstring) const {
|
|
|
|
std::vector<goos::Object> forms = {pretty_print::to_symbol("define"), m_dst->to_form(env)};
|
|
|
|
if (docstring) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format("\"{}\"", docstring.value())));
|
|
|
|
}
|
2021-03-03 20:52:25 -05:00
|
|
|
if (m_cast_for_define) {
|
2021-07-26 20:02:16 -04:00
|
|
|
// for vu-function, we just put a 0. These aren't supported
|
|
|
|
if (*m_cast_for_define == TypeSpec("vu-function")) {
|
2022-08-23 00:32:07 -04:00
|
|
|
forms.push_back(pretty_print::build_list(fmt::format("the-as {}", m_cast_for_define->print()),
|
|
|
|
pretty_print::to_symbol("0")));
|
|
|
|
return pretty_print::build_list(forms);
|
2021-07-26 20:02:16 -04:00
|
|
|
}
|
2022-08-23 00:32:07 -04:00
|
|
|
forms.push_back(pretty_print::build_list(fmt::format("the-as {}", m_cast_for_define->print()),
|
|
|
|
m_src->to_form(env)));
|
|
|
|
return pretty_print::build_list(forms);
|
2021-03-03 20:52:25 -05:00
|
|
|
} else {
|
2022-08-23 00:32:07 -04:00
|
|
|
forms.push_back(m_src->to_form(env));
|
2021-03-03 20:52:25 -05:00
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
2021-01-27 13:47:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetFormFormElement::apply(const std::function<void(FormElement*)>& f) {
|
2021-02-18 11:35:45 -05:00
|
|
|
f(this);
|
2021-01-27 13:47:54 -05:00
|
|
|
m_src->apply(f);
|
|
|
|
m_dst->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetFormFormElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_src->apply_form(f);
|
|
|
|
m_dst->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SetFormFormElement::is_sequence_point() const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void SetFormFormElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_src->collect_vars(vars, recursive);
|
|
|
|
m_dst->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-27 13:47:54 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void SetFormFormElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
(void)regs;
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// AtomicOpElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-07-05 16:07:07 -04:00
|
|
|
AtomicOpElement::AtomicOpElement(AtomicOp* op) : m_op(op) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object AtomicOpElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return m_op->to_form(env.file->labels, env);
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void AtomicOpElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AtomicOpElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void AtomicOpElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
m_op->collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void AtomicOpElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto r : m_op->write_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_op->clobber_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-05 16:07:07 -04:00
|
|
|
/////////////////////////////
|
|
|
|
// AsmBranchElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
AsmBranchElement::AsmBranchElement(AsmBranchOp* branch_op, Form* branch_delay, bool likely)
|
|
|
|
: m_branch_op(branch_op), m_branch_delay(branch_delay), m_likely(likely) {
|
|
|
|
m_branch_delay->parent_element = this;
|
2021-07-09 22:20:37 -04:00
|
|
|
for (auto& elt : m_branch_delay->elts()) {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(elt->parent_form == m_branch_delay);
|
2021-07-09 22:20:37 -04:00
|
|
|
}
|
2021-07-05 16:07:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object AsmBranchElement::to_form_internal(const Env& env) const {
|
|
|
|
auto f = m_branch_op->to_form(env.file->labels, env);
|
|
|
|
return pretty_print::build_list(f, m_branch_delay->to_form(env)); // temp hack
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsmBranchElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_branch_delay->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsmBranchElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_branch_delay->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsmBranchElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_branch_delay->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
m_branch_op->collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsmBranchElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_branch_delay->get_modified_regs(regs);
|
|
|
|
for (auto r : m_branch_op->write_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_branch_op->clobber_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
// TranslatedAsmBranch
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
TranslatedAsmBranch::TranslatedAsmBranch(Form* branch_condition,
|
|
|
|
Form* branch_delay,
|
|
|
|
int label_id,
|
|
|
|
bool likely)
|
|
|
|
: m_branch_condition(branch_condition),
|
|
|
|
m_branch_delay(branch_delay),
|
|
|
|
m_label_id(label_id),
|
|
|
|
m_likely(likely) {
|
|
|
|
if (m_branch_delay) {
|
|
|
|
m_branch_delay->parent_element = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_branch_condition->parent_element = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object TranslatedAsmBranch::to_form_internal(const Env& env) const {
|
|
|
|
// auto& cfg = env.func->cfg;
|
|
|
|
auto& label = env.file->labels.at(m_label_id);
|
|
|
|
int instr_in_function = (label.offset / 4 - env.func->start_word);
|
|
|
|
|
|
|
|
int block_id = -20;
|
|
|
|
if (instr_in_function == env.func->basic_blocks.back().end_word) {
|
|
|
|
block_id = env.func->basic_blocks.size() - 1;
|
|
|
|
} else {
|
|
|
|
int atomic_op_in_function =
|
|
|
|
env.func->ir2.atomic_ops->instruction_to_atomic_op.at(instr_in_function);
|
|
|
|
auto& ao = env.func->ir2.atomic_ops;
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)ao->block_id_to_first_atomic_op.size(); i++) {
|
|
|
|
if (ao->block_id_to_first_atomic_op.at(i) == atomic_op_in_function) {
|
|
|
|
block_id = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(block_id >= 0);
|
2021-07-05 16:07:07 -04:00
|
|
|
|
|
|
|
if (m_branch_delay) {
|
2021-07-09 22:20:37 -04:00
|
|
|
if (m_branch_delay->parent_element != this) {
|
2022-04-12 18:48:27 -04:00
|
|
|
ASSERT_MSG(false, fmt::format("bad ptr. Parent is {}",
|
|
|
|
m_branch_delay->parent_element->to_string(env)));
|
2021-07-09 22:20:37 -04:00
|
|
|
}
|
|
|
|
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(m_branch_delay->parent_element->parent_form);
|
2021-07-05 16:07:07 -04:00
|
|
|
std::vector<goos::Object> list = {
|
|
|
|
pretty_print::to_symbol("b!"), m_branch_condition->to_form(env),
|
|
|
|
pretty_print::to_symbol(fmt::format("cfg-{}", block_id)),
|
|
|
|
pretty_print::to_symbol(m_likely ? ":likely-delay" : ":delay"),
|
|
|
|
m_branch_delay->to_form(env)};
|
|
|
|
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
} else {
|
|
|
|
std::vector<goos::Object> list = {pretty_print::to_symbol("b!"),
|
|
|
|
m_branch_condition->to_form(env),
|
|
|
|
pretty_print::to_symbol(fmt::format("cfg-{}", block_id))};
|
|
|
|
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TranslatedAsmBranch::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_branch_condition->apply(f);
|
|
|
|
if (m_branch_delay) {
|
|
|
|
m_branch_delay->apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TranslatedAsmBranch::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_branch_condition->apply_form(f);
|
|
|
|
if (m_branch_delay) {
|
|
|
|
m_branch_delay->apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TranslatedAsmBranch::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_branch_condition->collect_vars(vars, recursive);
|
|
|
|
if (m_branch_delay) {
|
2021-07-09 22:20:37 -04:00
|
|
|
if (m_branch_delay->parent_element != this) {
|
2022-04-12 18:48:27 -04:00
|
|
|
ASSERT_MSG(false,
|
|
|
|
fmt::format("bad ptr. Parent is {}", (void*)m_branch_delay->parent_element));
|
2021-07-09 22:20:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& elt : m_branch_delay->elts()) {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(elt->parent_form == m_branch_delay);
|
2021-07-09 22:20:37 -04:00
|
|
|
}
|
|
|
|
|
2021-07-05 16:07:07 -04:00
|
|
|
m_branch_delay->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TranslatedAsmBranch::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_branch_condition->get_modified_regs(regs);
|
|
|
|
if (m_branch_delay) {
|
|
|
|
m_branch_delay->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-07 18:21:00 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// AsmOpElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
AsmOpElement::AsmOpElement(const AsmOp* op) : m_op(op) {}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object AsmOpElement::to_form_internal(const Env& env) const {
|
2021-02-07 18:21:00 -05:00
|
|
|
return m_op->to_form(env.file->labels, env);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsmOpElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsmOpElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void AsmOpElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-02-07 18:21:00 -05:00
|
|
|
m_op->collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AsmOpElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto r : m_op->write_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_op->clobber_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-06 10:46:26 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// OpenGoalAsmOpElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
OpenGoalAsmOpElement::OpenGoalAsmOpElement(const AsmOp* op) : m_op(op) {}
|
|
|
|
|
|
|
|
goos::Object OpenGoalAsmOpElement::to_form_internal(const Env& env) const {
|
|
|
|
return m_op->to_open_goal_form(env.file->labels, env);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGoalAsmOpElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGoalAsmOpElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
|
|
|
void OpenGoalAsmOpElement::collect_vars(RegAccessSet& vars, bool) const {
|
|
|
|
m_op->collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGoalAsmOpElement::collect_vf_regs(RegSet& regs) const {
|
|
|
|
for (auto r : m_op->read_regs()) {
|
2021-06-18 21:10:00 -04:00
|
|
|
if (r.is_vu_float()) {
|
2021-03-06 10:46:26 -05:00
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_op->write_regs()) {
|
2021-06-18 21:10:00 -04:00
|
|
|
if (r.is_vu_float()) {
|
2021-03-06 10:46:26 -05:00
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_op->clobber_regs()) {
|
2021-06-18 21:10:00 -04:00
|
|
|
if (r.is_vu_float()) {
|
2021-03-06 10:46:26 -05:00
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OpenGoalAsmOpElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto r : m_op->write_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_op->clobber_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// ConditionElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
ConditionElement::ConditionElement(IR2_Condition::Kind kind,
|
|
|
|
std::optional<SimpleAtom> src0,
|
|
|
|
std::optional<SimpleAtom> src1,
|
2021-02-05 19:41:09 -05:00
|
|
|
RegSet consumed,
|
|
|
|
bool flipped)
|
|
|
|
: m_kind(kind), m_consumed(std::move(consumed)), m_flipped(flipped) {
|
2021-01-17 18:08:18 -05:00
|
|
|
m_src[0] = src0;
|
|
|
|
m_src[1] = src1;
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object ConditionElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
forms.push_back(pretty_print::to_symbol(get_condition_kind_name(m_kind)));
|
|
|
|
for (int i = 0; i < get_condition_num_args(m_kind); i++) {
|
2021-02-01 20:41:37 -05:00
|
|
|
forms.push_back(m_src[i]->to_form(env.file->labels, env));
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
if (forms.size() > 1) {
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
} else {
|
|
|
|
return forms.front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object ConditionElement::to_form_as_condition_internal(const Env& env) const {
|
2021-01-27 15:39:50 -05:00
|
|
|
if (m_kind == IR2_Condition::Kind::TRUTHY) {
|
2021-02-01 20:41:37 -05:00
|
|
|
return m_src[0]->to_form(env.file->labels, env);
|
2021-01-27 15:39:50 -05:00
|
|
|
} else {
|
2021-02-11 14:35:28 -05:00
|
|
|
return to_form_internal(env);
|
2021-01-27 15:39:50 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
void ConditionElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
void ConditionElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
|
|
|
void ConditionElement::invert() {
|
|
|
|
m_kind = get_condition_opposite(m_kind);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void ConditionElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
for (auto src : m_src) {
|
2021-01-24 16:39:15 -05:00
|
|
|
if (src.has_value() && src->is_var()) {
|
|
|
|
vars.insert(src->var());
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void ConditionElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
(void)regs;
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// FunctionCallElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
FunctionCallElement::FunctionCallElement(const CallOp* op) : m_op(op) {}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object FunctionCallElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return m_op->to_form(env.file->labels, env);
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void FunctionCallElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FunctionCallElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void FunctionCallElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
return m_op->collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void FunctionCallElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto r : m_op->write_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_op->clobber_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// BranchElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
BranchElement::BranchElement(const BranchOp* op) : m_op(op) {}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object BranchElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return m_op->to_form(env.file->labels, env);
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void BranchElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BranchElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void BranchElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
return m_op->collect_vars(vars);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void BranchElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto r : m_op->write_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto r : m_op->clobber_regs()) {
|
|
|
|
regs.insert(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// ReturnElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
ReturnElement::ReturnElement(Form* _return_code, Form* _dead_code)
|
|
|
|
: return_code(_return_code), dead_code(_dead_code) {
|
|
|
|
return_code->parent_element = this;
|
|
|
|
if (dead_code) {
|
|
|
|
dead_code->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object ReturnElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
forms.push_back(pretty_print::to_symbol("return"));
|
2021-01-25 22:08:58 -05:00
|
|
|
forms.push_back(return_code->to_form(env));
|
2021-02-07 18:21:00 -05:00
|
|
|
if (dead_code) {
|
|
|
|
forms.push_back(dead_code->to_form(env));
|
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReturnElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
return_code->apply(f);
|
2021-02-07 18:21:00 -05:00
|
|
|
if (dead_code) {
|
|
|
|
dead_code->apply(f);
|
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void ReturnElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
return_code->apply_form(f);
|
2021-02-07 18:21:00 -05:00
|
|
|
if (dead_code) {
|
|
|
|
dead_code->apply_form(f);
|
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void ReturnElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
return_code->collect_vars(vars, recursive);
|
|
|
|
if (dead_code) {
|
|
|
|
dead_code->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-02-07 18:21:00 -05:00
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void ReturnElement::get_modified_regs(RegSet& regs) const {
|
2021-02-07 18:21:00 -05:00
|
|
|
return_code->get_modified_regs(regs);
|
|
|
|
if (dead_code) {
|
|
|
|
dead_code->get_modified_regs(regs);
|
2021-02-01 20:41:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// BreakElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-05-23 20:16:34 -04:00
|
|
|
BreakElement::BreakElement(Form* _return_code, Form* _dead_code, int _lid)
|
|
|
|
: return_code(_return_code), dead_code(_dead_code), lid(_lid) {
|
2021-03-05 18:48:01 -05:00
|
|
|
return_code->parent_element = this;
|
2021-05-23 20:16:34 -04:00
|
|
|
if (dead_code) {
|
|
|
|
dead_code->parent_element = this;
|
|
|
|
}
|
2021-03-05 18:48:01 -05:00
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object BreakElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
std::vector<goos::Object> forms;
|
2021-05-23 20:16:34 -04:00
|
|
|
if (dead_code) {
|
|
|
|
forms.push_back(pretty_print::to_symbol("break"));
|
|
|
|
forms.push_back(pretty_print::build_list(return_code->to_form(env)));
|
|
|
|
forms.push_back(pretty_print::build_list(dead_code->to_form(env)));
|
|
|
|
} else {
|
2021-07-11 21:59:27 -04:00
|
|
|
if (return_code->try_as_element<EmptyElement>()) {
|
|
|
|
return pretty_print::build_list(fmt::format("goto cfg-{}", lid));
|
|
|
|
} else {
|
|
|
|
forms.push_back(pretty_print::to_symbol("begin"));
|
|
|
|
return_code->inline_forms(forms, env);
|
|
|
|
forms.push_back(pretty_print::build_list(fmt::format("goto cfg-{}", lid)));
|
|
|
|
}
|
2021-05-23 20:16:34 -04:00
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
return_code->apply(f);
|
2021-05-23 20:16:34 -04:00
|
|
|
if (dead_code) {
|
|
|
|
dead_code->apply(f);
|
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void BreakElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
return_code->apply_form(f);
|
2021-05-23 20:16:34 -04:00
|
|
|
if (dead_code) {
|
|
|
|
dead_code->apply_form(f);
|
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void BreakElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
return_code->collect_vars(vars, recursive);
|
2021-05-23 20:16:34 -04:00
|
|
|
if (dead_code) {
|
|
|
|
dead_code->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-03-05 18:48:01 -05:00
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void BreakElement::get_modified_regs(RegSet& regs) const {
|
2021-05-23 20:16:34 -04:00
|
|
|
return_code->get_modified_regs(regs);
|
|
|
|
if (dead_code) {
|
|
|
|
dead_code->get_modified_regs(regs);
|
2021-02-01 20:41:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// CondWithElseElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
CondWithElseElement::CondWithElseElement(std::vector<Entry> _entries, Form* _else_ir)
|
|
|
|
: entries(std::move(_entries)), else_ir(_else_ir) {
|
|
|
|
for (auto& e : entries) {
|
|
|
|
e.condition->parent_element = this;
|
|
|
|
e.body->parent_element = this;
|
|
|
|
}
|
|
|
|
else_ir->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object CondWithElseElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
// for now we only turn it into an if statement if both cases won't require a begin at the top
|
|
|
|
// level. I think it is more common to write these as a two-case cond instead of an if with begin.
|
2021-05-12 19:46:17 -04:00
|
|
|
if (entries.size() == 1 && entries.front().body->is_reasonable_for_if() &&
|
|
|
|
else_ir->is_reasonable_for_if()) {
|
2021-01-17 18:08:18 -05:00
|
|
|
std::vector<goos::Object> list;
|
|
|
|
list.push_back(pretty_print::to_symbol("if"));
|
2021-01-27 15:39:50 -05:00
|
|
|
list.push_back(entries.front().condition->to_form_as_condition(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
list.push_back(entries.front().body->to_form(env));
|
|
|
|
list.push_back(else_ir->to_form(env));
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
} else {
|
|
|
|
std::vector<goos::Object> list;
|
|
|
|
list.push_back(pretty_print::to_symbol("cond"));
|
|
|
|
for (auto& e : entries) {
|
|
|
|
std::vector<goos::Object> entry;
|
2021-01-27 15:39:50 -05:00
|
|
|
entry.push_back(e.condition->to_form_as_condition(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
e.body->inline_forms(entry, env);
|
|
|
|
list.push_back(pretty_print::build_list(entry));
|
|
|
|
}
|
|
|
|
std::vector<goos::Object> else_form;
|
|
|
|
else_form.push_back(pretty_print::to_symbol("else"));
|
|
|
|
else_ir->inline_forms(else_form, env);
|
|
|
|
list.push_back(pretty_print::build_list(else_form));
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CondWithElseElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& entry : entries) {
|
|
|
|
entry.condition->apply(f);
|
|
|
|
entry.body->apply(f);
|
|
|
|
}
|
|
|
|
else_ir->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CondWithElseElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
for (auto& entry : entries) {
|
|
|
|
entry.condition->apply_form(f);
|
|
|
|
entry.body->apply_form(f);
|
|
|
|
}
|
|
|
|
else_ir->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void CondWithElseElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
for (auto& entry : entries) {
|
|
|
|
entry.condition->collect_vars(vars, recursive);
|
|
|
|
entry.body->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
else_ir->collect_vars(vars, recursive);
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void CondWithElseElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto& e : entries) {
|
|
|
|
e.condition->get_modified_regs(regs);
|
|
|
|
e.body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
else_ir->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// EmptyElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object EmptyElement::to_form_internal(const Env&) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
return pretty_print::build_list("empty");
|
|
|
|
}
|
|
|
|
|
|
|
|
void EmptyElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EmptyElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-03-05 18:48:01 -05:00
|
|
|
void EmptyElement::collect_vars(RegAccessSet&, bool) const {}
|
2021-02-01 20:41:37 -05:00
|
|
|
void EmptyElement::get_modified_regs(RegSet&) const {}
|
2021-01-19 21:45:17 -05:00
|
|
|
|
2021-03-06 10:46:26 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// RLetElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
bool cmp(Register x, Register y) {
|
|
|
|
int comparison = x.to_string().compare(y.to_string());
|
|
|
|
if (comparison <= 0)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RLetElement::RLetElement(Form* _body, RegSet _regs) : body(_body) {
|
|
|
|
for (auto& reg : _regs) {
|
|
|
|
sorted_regs.push_back(reg);
|
|
|
|
}
|
|
|
|
std::sort(sorted_regs.begin(), sorted_regs.end(), cmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RLetElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
body->apply(f);
|
|
|
|
}
|
|
|
|
|
2021-05-31 18:14:18 -04:00
|
|
|
goos::Object RLetElement::reg_list() const {
|
2021-03-06 10:46:26 -05:00
|
|
|
std::vector<goos::Object> regs;
|
|
|
|
for (auto& reg : sorted_regs) {
|
2021-06-18 21:10:00 -04:00
|
|
|
if (reg.is_vu_float()) {
|
2021-03-06 10:46:26 -05:00
|
|
|
std::string reg_name = reg.to_string() == "ACC" ? "acc" : reg.to_string();
|
|
|
|
regs.push_back(
|
|
|
|
pretty_print::build_list(pretty_print::to_symbol(fmt::format("{} :class vf", reg_name))));
|
|
|
|
}
|
|
|
|
}
|
2021-05-31 18:14:18 -04:00
|
|
|
return pretty_print::build_list(regs);
|
|
|
|
}
|
2021-03-06 10:46:26 -05:00
|
|
|
|
2021-05-31 18:14:18 -04:00
|
|
|
bool RLetElement::needs_vf0_init() const {
|
|
|
|
for (auto& reg : sorted_regs) {
|
|
|
|
if (reg.get_kind() == Reg::RegisterKind::VF && reg.to_string() == "vf0") {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object RLetElement::to_form_internal(const Env& env) const {
|
2021-03-06 10:46:26 -05:00
|
|
|
std::vector<goos::Object> rletForm;
|
|
|
|
rletForm.push_back(pretty_print::to_symbol("rlet"));
|
2021-05-31 18:14:18 -04:00
|
|
|
rletForm.push_back(reg_list());
|
2021-03-06 10:46:26 -05:00
|
|
|
|
|
|
|
// NOTE - initialize any relevant registers in the body first
|
2021-05-31 18:14:18 -04:00
|
|
|
if (needs_vf0_init()) {
|
|
|
|
rletForm.push_back(pretty_print::to_symbol("(init-vf0-vector)")); // Defined in vector-h.gc
|
2021-03-06 10:46:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
body->inline_forms(rletForm, env);
|
|
|
|
return pretty_print::build_list(rletForm);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RLetElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
body->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RLetElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
body->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RLetElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// WhileElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
WhileElement::WhileElement(Form* _condition, Form* _body) : condition(_condition), body(_body) {
|
|
|
|
condition->parent_element = this;
|
|
|
|
body->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
void WhileElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
// note - this is done in program order, rather than print order. Not sure if this makes sense.
|
|
|
|
f(this);
|
|
|
|
body->apply(f);
|
|
|
|
condition->apply(f);
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object WhileElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
std::vector<goos::Object> list;
|
2022-05-19 21:30:14 -04:00
|
|
|
auto cond = condition->to_form_as_condition(env);
|
|
|
|
if (cond == pretty_print::to_symbol("#t")) {
|
|
|
|
list.push_back(pretty_print::to_symbol("loop"));
|
|
|
|
} else {
|
|
|
|
list.push_back(pretty_print::to_symbol("while"));
|
|
|
|
list.push_back(condition->to_form_as_condition(env));
|
|
|
|
}
|
2021-01-17 18:08:18 -05:00
|
|
|
body->inline_forms(list, env);
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WhileElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
body->apply_form(f);
|
|
|
|
condition->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void WhileElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
body->collect_vars(vars, recursive);
|
|
|
|
condition->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void WhileElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
condition->get_modified_regs(regs);
|
|
|
|
body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// UntilElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
UntilElement::UntilElement(Form* _condition, Form* _body) : condition(_condition), body(_body) {
|
|
|
|
condition->parent_element = this;
|
|
|
|
body->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
void UntilElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
// note - this is done in program order, rather than print order. Not sure if this makes sense.
|
|
|
|
f(this);
|
|
|
|
body->apply(f);
|
|
|
|
condition->apply(f);
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object UntilElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
std::vector<goos::Object> list;
|
|
|
|
list.push_back(pretty_print::to_symbol("until"));
|
2021-01-27 15:39:50 -05:00
|
|
|
list.push_back(condition->to_form_as_condition(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
body->inline_forms(list, env);
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UntilElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
body->apply_form(f);
|
|
|
|
condition->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void UntilElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
body->collect_vars(vars, recursive);
|
|
|
|
condition->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void UntilElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
condition->get_modified_regs(regs);
|
|
|
|
body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// ShortCircuitElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
ShortCircuitElement::ShortCircuitElement(std::vector<Entry> _entries)
|
|
|
|
: entries(std::move(_entries)) {
|
|
|
|
for (auto& entry : entries) {
|
|
|
|
entry.condition->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
void ShortCircuitElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& x : entries) {
|
|
|
|
x.condition->apply(f);
|
|
|
|
// if (x.output) {
|
|
|
|
// // not sure about this...
|
|
|
|
// x.output->apply(f);
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShortCircuitElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
for (auto& x : entries) {
|
|
|
|
x.condition->apply_form(f);
|
|
|
|
// if (x.output) {
|
|
|
|
// // not sure about this...
|
|
|
|
// x.output->apply(f);
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object ShortCircuitElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
switch (kind) {
|
|
|
|
case UNKNOWN:
|
|
|
|
forms.push_back(pretty_print::to_symbol("unknown-sc"));
|
|
|
|
break;
|
|
|
|
case AND:
|
|
|
|
forms.push_back(pretty_print::to_symbol("and"));
|
|
|
|
break;
|
|
|
|
case OR:
|
|
|
|
forms.push_back(pretty_print::to_symbol("or"));
|
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
for (auto& x : entries) {
|
2021-01-27 15:39:50 -05:00
|
|
|
forms.push_back(x.condition->to_form_as_condition(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void ShortCircuitElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-02-09 20:59:14 -05:00
|
|
|
// vars.insert(final_result); // todo - this might be unused.
|
2021-03-05 18:48:01 -05:00
|
|
|
if (recursive) {
|
|
|
|
for (auto& entry : entries) {
|
|
|
|
entry.condition->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void ShortCircuitElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto& e : entries) {
|
|
|
|
e.condition->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
2021-01-19 21:45:17 -05:00
|
|
|
// CondNoElseElement
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
CondNoElseElement::CondNoElseElement(std::vector<Entry> _entries) : entries(std::move(_entries)) {
|
|
|
|
for (auto& entry : entries) {
|
|
|
|
entry.condition->parent_element = this;
|
|
|
|
entry.body->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object CondNoElseElement::to_form_internal(const Env& env) const {
|
2021-05-12 19:46:17 -04:00
|
|
|
if (entries.size() == 1 && entries.front().body->is_reasonable_for_if()) {
|
2021-01-17 18:08:18 -05:00
|
|
|
// print as an if statement if we can put the body in a single form.
|
|
|
|
std::vector<goos::Object> list;
|
|
|
|
list.push_back(pretty_print::to_symbol("if"));
|
2021-01-27 15:39:50 -05:00
|
|
|
list.push_back(entries.front().condition->to_form_as_condition(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
list.push_back(entries.front().body->to_form(env));
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
} else if (entries.size() == 1) {
|
|
|
|
// turn into a when if the body requires multiple forms
|
|
|
|
// todo check to see if the condition starts with a NOT and this can be simplified to an
|
|
|
|
// unless.
|
|
|
|
std::vector<goos::Object> list;
|
|
|
|
list.push_back(pretty_print::to_symbol("when"));
|
2021-01-27 15:39:50 -05:00
|
|
|
list.push_back(entries.front().condition->to_form_as_condition(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
entries.front().body->inline_forms(list, env);
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
} else {
|
|
|
|
std::vector<goos::Object> list;
|
|
|
|
list.push_back(pretty_print::to_symbol("cond"));
|
|
|
|
for (auto& e : entries) {
|
|
|
|
std::vector<goos::Object> entry;
|
2021-01-27 15:39:50 -05:00
|
|
|
entry.push_back(e.condition->to_form_as_condition(env));
|
2021-02-05 19:41:09 -05:00
|
|
|
e.body->inline_forms(entry, env);
|
2021-01-17 18:08:18 -05:00
|
|
|
list.push_back(pretty_print::build_list(entry));
|
|
|
|
}
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CondNoElseElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& e : entries) {
|
|
|
|
e.condition->apply(f);
|
|
|
|
e.body->apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CondNoElseElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
for (auto& e : entries) {
|
|
|
|
e.condition->apply_form(f);
|
|
|
|
e.body->apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void CondNoElseElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
for (auto& e : entries) {
|
|
|
|
e.condition->collect_vars(vars, recursive);
|
|
|
|
e.body->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
}
|
2021-02-01 20:41:37 -05:00
|
|
|
|
|
|
|
void CondNoElseElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto& e : entries) {
|
|
|
|
e.condition->get_modified_regs(regs);
|
|
|
|
e.body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-11 16:35:25 -04:00
|
|
|
CaseElement::CaseElement(Form* value, const std::vector<Entry>& entries, Form* else_body)
|
|
|
|
: m_value(value), m_entries(entries), m_else_body(else_body) {
|
|
|
|
m_value->parent_element = this;
|
|
|
|
for (auto& entry : m_entries) {
|
|
|
|
for (auto& val : entry.vals) {
|
|
|
|
val->parent_element = this;
|
|
|
|
}
|
|
|
|
entry.body->parent_element = this;
|
|
|
|
}
|
|
|
|
if (m_else_body) {
|
|
|
|
m_else_body->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object CaseElement::to_form_internal(const Env& env) const {
|
|
|
|
std::vector<goos::Object> list;
|
|
|
|
list.push_back(pretty_print::to_symbol("case"));
|
|
|
|
list.push_back(m_value->to_form(env));
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
std::vector<goos::Object> entry;
|
|
|
|
|
|
|
|
// cases
|
|
|
|
std::vector<goos::Object> cases;
|
|
|
|
for (auto& val : e.vals) {
|
|
|
|
cases.push_back(val->to_form(env));
|
|
|
|
}
|
|
|
|
entry.push_back(pretty_print::build_list(cases));
|
|
|
|
|
|
|
|
// body
|
|
|
|
e.body->inline_forms(entry, env);
|
|
|
|
list.push_back(pretty_print::build_list(entry));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_else_body) {
|
|
|
|
std::vector<goos::Object> entry;
|
|
|
|
entry.push_back(pretty_print::to_symbol("else"));
|
|
|
|
m_else_body->inline_forms(entry, env);
|
|
|
|
list.push_back(pretty_print::build_list(entry));
|
|
|
|
}
|
|
|
|
return pretty_print::build_list(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CaseElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_value->apply(f);
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
for (auto& val : e.vals) {
|
|
|
|
val->apply(f);
|
|
|
|
}
|
|
|
|
e.body->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_else_body) {
|
|
|
|
m_else_body->apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CaseElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_value->apply_form(f);
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
for (auto& val : e.vals) {
|
|
|
|
val->apply_form(f);
|
|
|
|
}
|
|
|
|
e.body->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_else_body) {
|
|
|
|
m_else_body->apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CaseElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_value->collect_vars(vars, recursive);
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
for (auto& val : e.vals) {
|
|
|
|
val->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
e.body->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_else_body) {
|
|
|
|
m_else_body->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CaseElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_value->get_modified_regs(regs);
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
for (auto& val : e.vals) {
|
|
|
|
val->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
e.body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_else_body) {
|
|
|
|
m_else_body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// AbsElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-28 12:38:29 -05:00
|
|
|
AbsElement::AbsElement(RegisterAccess _source, RegSet _consumed)
|
2021-01-24 16:39:15 -05:00
|
|
|
: source(_source), consumed(std::move(_consumed)) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object AbsElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return pretty_print::build_list("abs", source.to_form(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void AbsElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
void AbsElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void AbsElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-24 16:39:15 -05:00
|
|
|
vars.insert(source);
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void AbsElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// AshElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-28 12:38:29 -05:00
|
|
|
AshElement::AshElement(RegisterAccess _shift_amount,
|
|
|
|
RegisterAccess _value,
|
|
|
|
std::optional<RegisterAccess> _clobber,
|
2021-01-24 16:39:15 -05:00
|
|
|
bool _is_signed,
|
|
|
|
RegSet _consumed)
|
|
|
|
: shift_amount(_shift_amount),
|
|
|
|
value(_value),
|
|
|
|
clobber(_clobber),
|
|
|
|
is_signed(_is_signed),
|
|
|
|
consumed(_consumed) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object AshElement::to_form_internal(const Env& env) const {
|
2021-01-17 18:08:18 -05:00
|
|
|
return pretty_print::build_list(pretty_print::to_symbol(is_signed ? "ash.si" : "ash.ui"),
|
2021-02-01 20:41:37 -05:00
|
|
|
value.to_form(env), shift_amount.to_form(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void AshElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
void AshElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void AshElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-24 16:39:15 -05:00
|
|
|
vars.insert(value);
|
|
|
|
vars.insert(shift_amount);
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void AshElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// TypeOfElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2022-07-05 20:39:24 -04:00
|
|
|
TypeOfElement::TypeOfElement(Form* _value) : value(_value) {
|
2021-01-17 18:08:18 -05:00
|
|
|
value->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object TypeOfElement::to_form_internal(const Env& env) const {
|
2021-02-07 18:21:00 -05:00
|
|
|
return pretty_print::build_list("rtype-of", value->to_form(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void TypeOfElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
value->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TypeOfElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
value->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void TypeOfElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
value->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void TypeOfElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// ConditionalMoveFalseElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-28 12:38:29 -05:00
|
|
|
ConditionalMoveFalseElement::ConditionalMoveFalseElement(RegisterAccess _dest,
|
|
|
|
RegisterAccess _old_value,
|
|
|
|
RegisterAccess _source,
|
2021-01-17 18:08:18 -05:00
|
|
|
bool _on_zero)
|
2021-02-14 18:50:45 -05:00
|
|
|
: dest(_dest), old_value(_old_value), source(_source), on_zero(_on_zero) {}
|
2021-01-17 18:08:18 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object ConditionalMoveFalseElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return pretty_print::build_list(on_zero ? "cmove-#f-zero" : "cmove-#f-nonzero", dest.to_form(env),
|
2021-02-14 18:50:45 -05:00
|
|
|
source.to_form(env), old_value.to_form(env));
|
2021-01-17 18:08:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void ConditionalMoveFalseElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
2021-02-14 18:50:45 -05:00
|
|
|
void ConditionalMoveFalseElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-01-19 21:45:17 -05:00
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void ConditionalMoveFalseElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-19 21:45:17 -05:00
|
|
|
vars.insert(dest);
|
2021-02-14 18:50:45 -05:00
|
|
|
vars.insert(old_value);
|
|
|
|
vars.insert(source);
|
2021-01-19 21:45:17 -05:00
|
|
|
}
|
2021-01-23 16:32:56 -05:00
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void ConditionalMoveFalseElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
regs.insert(dest.reg());
|
|
|
|
}
|
|
|
|
|
2021-01-23 16:32:56 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// GenericElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
GenericOperator GenericOperator::make_fixed(FixedOperatorKind kind) {
|
|
|
|
GenericOperator op;
|
|
|
|
op.m_kind = Kind::FIXED_OPERATOR;
|
|
|
|
op.m_fixed_kind = kind;
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
GenericOperator GenericOperator::make_function(Form* value) {
|
|
|
|
GenericOperator op;
|
|
|
|
op.m_kind = Kind::FUNCTION_EXPR;
|
|
|
|
op.m_function = value;
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericOperator GenericOperator::make_compare(IR2_Condition::Kind kind) {
|
|
|
|
GenericOperator op;
|
|
|
|
op.m_kind = Kind::CONDITION_OPERATOR;
|
|
|
|
op.m_condition_kind = kind;
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void GenericOperator::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-01-23 16:32:56 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::FIXED_OPERATOR:
|
2021-01-24 16:39:15 -05:00
|
|
|
case Kind::CONDITION_OPERATOR:
|
|
|
|
return;
|
|
|
|
case Kind::FUNCTION_EXPR:
|
2021-03-05 18:48:01 -05:00
|
|
|
if (recursive) {
|
|
|
|
m_function->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-23 16:32:56 -05:00
|
|
|
return;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
goos::Object GenericOperator::to_form(const Env& env) const {
|
2021-01-23 16:32:56 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::FIXED_OPERATOR:
|
|
|
|
return pretty_print::to_symbol(fixed_operator_to_string(m_fixed_kind));
|
2021-01-24 16:39:15 -05:00
|
|
|
case Kind::CONDITION_OPERATOR:
|
|
|
|
return pretty_print::to_symbol(get_condition_kind_name(m_condition_kind));
|
|
|
|
case Kind::FUNCTION_EXPR:
|
|
|
|
return m_function->to_form(env);
|
2021-01-23 16:32:56 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return {};
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
void GenericOperator::apply(const std::function<void(FormElement*)>& f) {
|
2021-01-23 16:32:56 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::FIXED_OPERATOR:
|
2021-01-24 16:39:15 -05:00
|
|
|
case Kind::CONDITION_OPERATOR:
|
|
|
|
break;
|
|
|
|
case Kind::FUNCTION_EXPR:
|
|
|
|
m_function->apply(f);
|
2021-01-23 16:32:56 -05:00
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
void GenericOperator::apply_form(const std::function<void(Form*)>& f) {
|
2021-01-23 16:32:56 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::FIXED_OPERATOR:
|
2021-01-24 16:39:15 -05:00
|
|
|
case Kind::CONDITION_OPERATOR:
|
|
|
|
break;
|
|
|
|
case Kind::FUNCTION_EXPR:
|
|
|
|
m_function->apply_form(f);
|
2021-01-23 16:32:56 -05:00
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-25 22:08:58 -05:00
|
|
|
bool GenericOperator::operator==(const GenericOperator& other) const {
|
|
|
|
if (m_kind != other.m_kind) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::FIXED_OPERATOR:
|
|
|
|
return m_fixed_kind == other.m_fixed_kind;
|
|
|
|
case Kind::CONDITION_OPERATOR:
|
|
|
|
return m_condition_kind == other.m_condition_kind;
|
|
|
|
case Kind::FUNCTION_EXPR:
|
|
|
|
return false;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return false;
|
2021-01-25 22:08:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GenericOperator::operator!=(const GenericOperator& other) const {
|
|
|
|
return !((*this) == other);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void GenericOperator::get_modified_regs(RegSet& regs) const {
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::FIXED_OPERATOR:
|
|
|
|
case Kind::CONDITION_OPERATOR:
|
|
|
|
break;
|
|
|
|
case Kind::FUNCTION_EXPR:
|
|
|
|
m_function->get_modified_regs(regs);
|
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-02-01 20:41:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 16:32:56 -05:00
|
|
|
std::string fixed_operator_to_string(FixedOperatorKind kind) {
|
|
|
|
switch (kind) {
|
|
|
|
case FixedOperatorKind::GPR_TO_FPR:
|
|
|
|
return "gpr->fpr";
|
|
|
|
case FixedOperatorKind::DIVISION:
|
|
|
|
return "/";
|
|
|
|
case FixedOperatorKind::ADDITION:
|
|
|
|
return "+";
|
2021-02-22 09:36:30 -05:00
|
|
|
case FixedOperatorKind::ADDITION_IN_PLACE:
|
|
|
|
return "+!";
|
|
|
|
case FixedOperatorKind::ADDITION_PTR:
|
|
|
|
return "&+";
|
|
|
|
case FixedOperatorKind::ADDITION_PTR_IN_PLACE:
|
|
|
|
return "&+!";
|
2021-01-24 16:39:15 -05:00
|
|
|
case FixedOperatorKind::SUBTRACTION:
|
|
|
|
return "-";
|
2021-03-14 16:11:42 -04:00
|
|
|
case FixedOperatorKind::SUBTRACTION_PTR:
|
|
|
|
return "&-";
|
2021-01-24 16:39:15 -05:00
|
|
|
case FixedOperatorKind::MULTIPLICATION:
|
|
|
|
return "*";
|
2021-02-07 18:21:00 -05:00
|
|
|
case FixedOperatorKind::SQRT:
|
2021-04-02 11:35:14 -04:00
|
|
|
return "sqrtf";
|
2021-01-24 16:39:15 -05:00
|
|
|
case FixedOperatorKind::ARITH_SHIFT:
|
|
|
|
return "ash";
|
|
|
|
case FixedOperatorKind::MOD:
|
|
|
|
return "mod";
|
|
|
|
case FixedOperatorKind::ABS:
|
|
|
|
return "abs";
|
|
|
|
case FixedOperatorKind::MIN:
|
|
|
|
return "min";
|
|
|
|
case FixedOperatorKind::MAX:
|
|
|
|
return "max";
|
2021-02-13 11:32:52 -05:00
|
|
|
case FixedOperatorKind::FABS:
|
|
|
|
return "fabs";
|
|
|
|
case FixedOperatorKind::FMIN:
|
|
|
|
return "fmin";
|
|
|
|
case FixedOperatorKind::FMAX:
|
|
|
|
return "fmax";
|
2021-01-24 16:39:15 -05:00
|
|
|
case FixedOperatorKind::LOGAND:
|
|
|
|
return "logand";
|
2021-07-23 20:51:26 -04:00
|
|
|
case FixedOperatorKind::LOGAND_IN_PLACE:
|
|
|
|
return "logand!";
|
2021-01-24 16:39:15 -05:00
|
|
|
case FixedOperatorKind::LOGIOR:
|
|
|
|
return "logior";
|
2021-07-23 20:51:26 -04:00
|
|
|
case FixedOperatorKind::LOGIOR_IN_PLACE:
|
|
|
|
return "logior!";
|
2021-01-24 16:39:15 -05:00
|
|
|
case FixedOperatorKind::LOGXOR:
|
|
|
|
return "logxor";
|
2022-05-21 15:47:41 -04:00
|
|
|
case FixedOperatorKind::LOGXOR_IN_PLACE:
|
|
|
|
return "logxor!";
|
2021-01-24 16:39:15 -05:00
|
|
|
case FixedOperatorKind::LOGNOR:
|
|
|
|
return "lognor";
|
|
|
|
case FixedOperatorKind::LOGNOT:
|
|
|
|
return "lognot";
|
2021-07-23 20:51:26 -04:00
|
|
|
case FixedOperatorKind::LOGCLEAR:
|
|
|
|
return "logclear";
|
|
|
|
case FixedOperatorKind::LOGCLEAR_IN_PLACE:
|
|
|
|
return "logclear!";
|
|
|
|
case FixedOperatorKind::LOGTEST:
|
|
|
|
return "logtest?";
|
|
|
|
case FixedOperatorKind::LOGTESTA:
|
|
|
|
return "logtesta?";
|
2021-02-05 19:41:09 -05:00
|
|
|
case FixedOperatorKind::SHL:
|
|
|
|
return "shl";
|
|
|
|
case FixedOperatorKind::SHR:
|
|
|
|
return "shr";
|
|
|
|
case FixedOperatorKind::SAR:
|
|
|
|
return "sar";
|
2021-01-27 13:47:54 -05:00
|
|
|
case FixedOperatorKind::CAR:
|
|
|
|
return "car";
|
|
|
|
case FixedOperatorKind::CDR:
|
|
|
|
return "cdr";
|
|
|
|
case FixedOperatorKind::NEW:
|
|
|
|
return "new";
|
2021-02-01 20:41:37 -05:00
|
|
|
case FixedOperatorKind::OBJECT_NEW:
|
|
|
|
return "object-new";
|
2021-02-05 19:41:09 -05:00
|
|
|
case FixedOperatorKind::TYPE_NEW:
|
|
|
|
return "type-new";
|
2021-02-11 14:35:28 -05:00
|
|
|
case FixedOperatorKind::CONS:
|
|
|
|
return "cons";
|
2021-02-05 19:41:09 -05:00
|
|
|
case FixedOperatorKind::LT:
|
|
|
|
return "<";
|
|
|
|
case FixedOperatorKind::GT:
|
|
|
|
return ">";
|
|
|
|
case FixedOperatorKind::LEQ:
|
|
|
|
return "<=";
|
|
|
|
case FixedOperatorKind::GEQ:
|
|
|
|
return ">=";
|
|
|
|
case FixedOperatorKind::EQ:
|
|
|
|
return "=";
|
|
|
|
case FixedOperatorKind::NEQ:
|
|
|
|
return "!=";
|
2021-02-13 11:32:52 -05:00
|
|
|
case FixedOperatorKind::METHOD_OF_OBJECT:
|
|
|
|
return "method-of-object";
|
2021-05-06 00:42:49 -04:00
|
|
|
case FixedOperatorKind::METHOD_OF_TYPE:
|
|
|
|
return "method-of-type";
|
2021-03-06 20:16:48 -05:00
|
|
|
case FixedOperatorKind::NULLP:
|
|
|
|
return "null?";
|
|
|
|
case FixedOperatorKind::PAIRP:
|
|
|
|
return "pair?";
|
2021-03-14 16:11:42 -04:00
|
|
|
case FixedOperatorKind::NONE:
|
|
|
|
return "none";
|
2021-04-26 21:40:08 -04:00
|
|
|
case FixedOperatorKind::PCPYLD:
|
2021-05-05 17:38:16 -04:00
|
|
|
return "make-u128";
|
2021-05-23 20:16:34 -04:00
|
|
|
case FixedOperatorKind::SYMBOL_TO_STRING:
|
|
|
|
return "symbol->string";
|
2021-06-04 13:43:19 -04:00
|
|
|
case FixedOperatorKind::ADDRESS_OF:
|
|
|
|
return "&";
|
2021-06-05 16:58:32 -04:00
|
|
|
case FixedOperatorKind::ASM_SLLV_R0:
|
|
|
|
return ".asm.sllv.r0";
|
2021-06-05 20:22:03 -04:00
|
|
|
case FixedOperatorKind::ASM_MADDS:
|
|
|
|
return ".asm.madd.s";
|
2021-06-27 17:24:35 -04:00
|
|
|
case FixedOperatorKind::VECTOR_MINUS:
|
|
|
|
return "vector-!";
|
|
|
|
case FixedOperatorKind::VECTOR_PLUS:
|
|
|
|
return "vector+!";
|
2021-07-23 20:51:26 -04:00
|
|
|
case FixedOperatorKind::VECTOR_CROSS:
|
|
|
|
return "vector-cross!";
|
2021-06-27 17:24:35 -04:00
|
|
|
case FixedOperatorKind::VECTOR_FLOAT_PRODUCT:
|
|
|
|
return "vector-float*!";
|
2021-07-03 16:18:41 -04:00
|
|
|
case FixedOperatorKind::L32_NOT_FALSE_CBOOL:
|
|
|
|
return "l32-false-check";
|
2021-07-05 16:07:07 -04:00
|
|
|
case FixedOperatorKind::VECTOR_3_DOT:
|
|
|
|
return "vector-dot";
|
2021-09-01 10:02:20 -04:00
|
|
|
case FixedOperatorKind::VECTOR_4_DOT:
|
|
|
|
return "vector4-dot";
|
2021-08-22 20:12:47 -04:00
|
|
|
case FixedOperatorKind::PROCESS_TO_PPOINTER:
|
|
|
|
return "process->ppointer";
|
|
|
|
case FixedOperatorKind::PPOINTER_TO_HANDLE:
|
|
|
|
return "ppointer->handle";
|
|
|
|
case FixedOperatorKind::PROCESS_TO_HANDLE:
|
|
|
|
return "process->handle";
|
|
|
|
case FixedOperatorKind::PPOINTER_TO_PROCESS:
|
|
|
|
return "ppointer->process";
|
2021-10-16 15:12:01 -04:00
|
|
|
case FixedOperatorKind::SEND_EVENT:
|
|
|
|
return "send-event";
|
2021-12-01 19:41:49 -05:00
|
|
|
case FixedOperatorKind::CPAD_PRESSED_P:
|
|
|
|
return "cpad-pressed?";
|
|
|
|
case FixedOperatorKind::CPAD_HOLD_P:
|
|
|
|
return "cpad-hold?";
|
2022-08-22 18:53:51 -04:00
|
|
|
case FixedOperatorKind::VECTOR_LENGTH:
|
|
|
|
return "vector-length";
|
2022-09-26 20:57:44 -04:00
|
|
|
case FixedOperatorKind::VECTOR_PLUS_FLOAT_TIMES:
|
|
|
|
return "vector+float*!";
|
2021-01-23 16:32:56 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return "";
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
GenericElement::GenericElement(GenericOperator op) : m_head(op) {
|
|
|
|
if (op.kind() == GenericOperator::Kind::FUNCTION_EXPR) {
|
|
|
|
op.m_function->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericElement::GenericElement(GenericOperator op, Form* arg) : m_head(op), m_elts({arg}) {
|
|
|
|
if (op.kind() == GenericOperator::Kind::FUNCTION_EXPR) {
|
|
|
|
op.m_function->parent_element = this;
|
|
|
|
}
|
|
|
|
for (auto x : m_elts) {
|
|
|
|
x->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 16:32:56 -05:00
|
|
|
GenericElement::GenericElement(GenericOperator op, Form* arg0, Form* arg1)
|
2021-02-09 20:59:14 -05:00
|
|
|
: m_head(op), m_elts({arg0, arg1}) {
|
|
|
|
if (op.kind() == GenericOperator::Kind::FUNCTION_EXPR) {
|
|
|
|
op.m_function->parent_element = this;
|
|
|
|
}
|
|
|
|
for (auto x : m_elts) {
|
|
|
|
x->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 16:32:56 -05:00
|
|
|
GenericElement::GenericElement(GenericOperator op, std::vector<Form*> forms)
|
2021-02-09 20:59:14 -05:00
|
|
|
: m_head(op), m_elts(std::move(forms)) {
|
|
|
|
if (op.kind() == GenericOperator::Kind::FUNCTION_EXPR) {
|
|
|
|
op.m_function->parent_element = this;
|
|
|
|
}
|
|
|
|
for (auto x : m_elts) {
|
|
|
|
x->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
2021-01-23 16:32:56 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object GenericElement::to_form_internal(const Env& env) const {
|
2021-01-27 15:39:50 -05:00
|
|
|
if (m_head.kind() == GenericOperator::Kind::CONDITION_OPERATOR &&
|
|
|
|
m_head.condition_kind() == IR2_Condition::Kind::TRUTHY) {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(m_elts.size() == 1);
|
2021-01-27 15:39:50 -05:00
|
|
|
return m_elts.front()->to_form_as_condition(env);
|
2021-03-22 20:04:00 -04:00
|
|
|
} else if (m_head.kind() == GenericOperator::Kind::CONDITION_OPERATOR &&
|
|
|
|
m_head.condition_kind() == IR2_Condition::Kind::ALWAYS) {
|
|
|
|
return pretty_print::to_symbol("#t");
|
2021-01-27 15:39:50 -05:00
|
|
|
} else {
|
|
|
|
std::vector<goos::Object> result;
|
|
|
|
result.push_back(m_head.to_form(env));
|
|
|
|
for (auto x : m_elts) {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(x->parent_element);
|
2021-01-27 15:39:50 -05:00
|
|
|
result.push_back(x->to_form(env));
|
|
|
|
}
|
|
|
|
return pretty_print::build_list(result);
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GenericElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_head.apply(f);
|
|
|
|
for (auto x : m_elts) {
|
|
|
|
x->apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GenericElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_head.apply_form(f);
|
|
|
|
for (auto x : m_elts) {
|
|
|
|
x->apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void GenericElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_head.collect_vars(vars, recursive);
|
|
|
|
for (auto x : m_elts) {
|
|
|
|
x->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void GenericElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_head.get_modified_regs(regs);
|
|
|
|
for (auto x : m_elts) {
|
|
|
|
x->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 16:32:56 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// CastElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
CastElement::CastElement(TypeSpec type, Form* source, bool numeric)
|
|
|
|
: m_type(std::move(type)), m_source(source), m_numeric(numeric) {
|
2021-07-17 13:41:05 -04:00
|
|
|
m_source->parent_element = this;
|
2021-02-09 20:59:14 -05:00
|
|
|
}
|
2021-01-23 16:32:56 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object CastElement::to_form_internal(const Env& env) const {
|
2022-02-08 19:02:47 -05:00
|
|
|
// ASSERT(m_source->parent_element == this);
|
2021-06-09 21:35:13 -04:00
|
|
|
auto atom = form_as_atom(m_source);
|
|
|
|
if (atom && atom->is_var()) {
|
|
|
|
return pretty_print::build_list(
|
|
|
|
m_numeric ? "the" : "the-as", m_type.print(),
|
|
|
|
atom->var().to_form(env, RegisterAccess::Print::AS_VARIABLE_NO_CAST));
|
|
|
|
}
|
2021-02-09 20:59:14 -05:00
|
|
|
return pretty_print::build_list(m_numeric ? "the" : "the-as", m_type.print(),
|
|
|
|
m_source->to_form(env));
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void CastElement::apply(const std::function<void(FormElement*)>& f) {
|
2022-02-08 19:02:47 -05:00
|
|
|
// ASSERT(m_source->parent_element == this);
|
2021-01-23 16:32:56 -05:00
|
|
|
f(this);
|
|
|
|
m_source->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CastElement::apply_form(const std::function<void(Form*)>& f) {
|
2022-02-08 19:02:47 -05:00
|
|
|
// ASSERT(m_source->parent_element == this);
|
2021-01-23 16:32:56 -05:00
|
|
|
m_source->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void CastElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2022-02-08 19:02:47 -05:00
|
|
|
// ASSERT(m_source->parent_element == this);
|
2021-03-05 18:48:01 -05:00
|
|
|
if (recursive) {
|
|
|
|
m_source->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-23 16:32:56 -05:00
|
|
|
}
|
2021-01-24 16:39:15 -05:00
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void CastElement::get_modified_regs(RegSet& regs) const {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(m_source->parent_element == this);
|
2021-02-01 20:41:37 -05:00
|
|
|
m_source->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// DerefElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
DerefToken DerefToken::make_int_constant(s64 int_constant) {
|
|
|
|
DerefToken x;
|
|
|
|
x.m_kind = Kind::INTEGER_CONSTANT;
|
|
|
|
x.m_int_constant = int_constant;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
DerefToken DerefToken::make_int_expr(Form* expr) {
|
|
|
|
DerefToken x;
|
|
|
|
x.m_kind = Kind::INTEGER_EXPRESSION;
|
|
|
|
x.m_expr = expr;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
DerefToken DerefToken::make_field_name(const std::string& name) {
|
|
|
|
DerefToken x;
|
|
|
|
x.m_kind = Kind::FIELD_NAME;
|
|
|
|
x.m_name = name;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
DerefToken DerefToken::make_expr_placeholder() {
|
|
|
|
DerefToken x;
|
|
|
|
x.m_kind = Kind::EXPRESSION_PLACEHOLDER;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void DerefToken::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-01-24 16:39:15 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::INTEGER_CONSTANT:
|
|
|
|
case Kind::FIELD_NAME:
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::EXPRESSION_PLACEHOLDER:
|
2021-01-24 16:39:15 -05:00
|
|
|
break;
|
|
|
|
case Kind::INTEGER_EXPRESSION:
|
2021-03-05 18:48:01 -05:00
|
|
|
if (recursive) {
|
|
|
|
m_expr->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-24 16:39:15 -05:00
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-01-24 16:39:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object DerefToken::to_form(const Env& env) const {
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::INTEGER_CONSTANT:
|
|
|
|
return pretty_print::to_symbol(fmt::format("{}", m_int_constant));
|
|
|
|
case Kind::INTEGER_EXPRESSION:
|
|
|
|
return m_expr->to_form(env);
|
|
|
|
case Kind::FIELD_NAME:
|
|
|
|
return pretty_print::to_symbol(m_name);
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::EXPRESSION_PLACEHOLDER:
|
|
|
|
return pretty_print::to_symbol("PLACEHOLDER");
|
2021-01-24 16:39:15 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return {};
|
2021-01-24 16:39:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DerefToken::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::INTEGER_CONSTANT:
|
|
|
|
case Kind::FIELD_NAME:
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::EXPRESSION_PLACEHOLDER:
|
2021-01-24 16:39:15 -05:00
|
|
|
break;
|
|
|
|
case Kind::INTEGER_EXPRESSION:
|
|
|
|
m_expr->apply(f);
|
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-01-24 16:39:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DerefToken::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::INTEGER_CONSTANT:
|
|
|
|
case Kind::FIELD_NAME:
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::EXPRESSION_PLACEHOLDER:
|
2021-01-24 16:39:15 -05:00
|
|
|
break;
|
|
|
|
case Kind::INTEGER_EXPRESSION:
|
|
|
|
m_expr->apply_form(f);
|
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-01-24 16:39:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void DerefToken::get_modified_regs(RegSet& regs) const {
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::INTEGER_CONSTANT:
|
|
|
|
case Kind::FIELD_NAME:
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::EXPRESSION_PLACEHOLDER:
|
2021-02-01 20:41:37 -05:00
|
|
|
break;
|
|
|
|
case Kind::INTEGER_EXPRESSION:
|
|
|
|
m_expr->get_modified_regs(regs);
|
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-02-01 20:41:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-13 11:32:52 -05:00
|
|
|
DerefToken to_token(const FieldReverseLookupOutput::Token& in) {
|
|
|
|
switch (in.kind) {
|
|
|
|
case FieldReverseLookupOutput::Token::Kind::FIELD:
|
|
|
|
return DerefToken::make_field_name(in.name);
|
|
|
|
case FieldReverseLookupOutput::Token::Kind::CONSTANT_IDX:
|
|
|
|
return DerefToken::make_int_constant(in.idx);
|
|
|
|
case FieldReverseLookupOutput::Token::Kind::VAR_IDX:
|
|
|
|
return DerefToken::make_expr_placeholder();
|
|
|
|
default:
|
|
|
|
// temp
|
|
|
|
throw std::runtime_error("Cannot convert rd lookup token to deref token");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:39:15 -05:00
|
|
|
DerefElement::DerefElement(Form* base, bool is_addr_of, DerefToken token)
|
2021-02-09 20:59:14 -05:00
|
|
|
: m_base(base), m_is_addr_of(is_addr_of), m_tokens({std::move(token)}) {
|
|
|
|
m_base->parent_element = this;
|
|
|
|
for (auto& x : m_tokens) {
|
|
|
|
if (x.kind() == DerefToken::Kind::INTEGER_EXPRESSION) {
|
|
|
|
x.expr()->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
2021-06-25 20:13:22 -04:00
|
|
|
inline_nested();
|
2021-02-09 20:59:14 -05:00
|
|
|
}
|
2021-01-24 16:39:15 -05:00
|
|
|
|
|
|
|
DerefElement::DerefElement(Form* base, bool is_addr_of, std::vector<DerefToken> tokens)
|
2021-02-09 20:59:14 -05:00
|
|
|
: m_base(base), m_is_addr_of(is_addr_of), m_tokens(std::move(tokens)) {
|
|
|
|
m_base->parent_element = this;
|
|
|
|
for (auto& x : m_tokens) {
|
|
|
|
if (x.kind() == DerefToken::Kind::INTEGER_EXPRESSION) {
|
|
|
|
x.expr()->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
2021-06-25 20:13:22 -04:00
|
|
|
inline_nested();
|
2021-02-09 20:59:14 -05:00
|
|
|
}
|
2021-01-24 16:39:15 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object DerefElement::to_form_internal(const Env& env) const {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(m_base->parent_element);
|
2021-01-24 16:39:15 -05:00
|
|
|
std::vector<goos::Object> forms = {pretty_print::to_symbol(m_is_addr_of ? "&->" : "->"),
|
|
|
|
m_base->to_form(env)};
|
|
|
|
for (auto& tok : m_tokens) {
|
|
|
|
forms.push_back(tok.to_form(env));
|
|
|
|
}
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DerefElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_base->apply(f);
|
|
|
|
for (auto& tok : m_tokens) {
|
|
|
|
tok.apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DerefElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_base->apply_form(f);
|
|
|
|
for (auto& tok : m_tokens) {
|
|
|
|
tok.apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void DerefElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_base->collect_vars(vars, recursive);
|
|
|
|
for (auto& tok : m_tokens) {
|
|
|
|
tok.collect_vars(vars, recursive);
|
|
|
|
}
|
2021-01-24 16:39:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void DerefElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_base->get_modified_regs(regs);
|
|
|
|
for (auto& tok : m_tokens) {
|
|
|
|
tok.get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void DerefElement::set_base(Form* new_base) {
|
|
|
|
m_base = new_base;
|
|
|
|
m_base->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-01-25 22:08:58 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// DynamicMethodAccess
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-28 12:38:29 -05:00
|
|
|
DynamicMethodAccess::DynamicMethodAccess(RegisterAccess source) : m_source(source) {}
|
2021-01-25 22:08:58 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object DynamicMethodAccess::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return pretty_print::build_list("dyn-method-access", m_source.to_form(env));
|
2021-01-25 22:08:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DynamicMethodAccess::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DynamicMethodAccess::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void DynamicMethodAccess::collect_vars(RegAccessSet& vars, bool) const {
|
2021-01-25 22:08:58 -05:00
|
|
|
vars.insert(m_source);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
void DynamicMethodAccess::get_modified_regs(RegSet&) const {}
|
|
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
// ArrayFieldAccess
|
|
|
|
/////////////////////////////
|
2021-02-28 12:38:29 -05:00
|
|
|
ArrayFieldAccess::ArrayFieldAccess(RegisterAccess source,
|
2021-02-01 20:41:37 -05:00
|
|
|
const std::vector<DerefToken>& deref_tokens,
|
2021-02-05 19:41:09 -05:00
|
|
|
int expected_stride,
|
2021-06-26 20:02:21 -04:00
|
|
|
int constant_offset,
|
|
|
|
bool flipped)
|
2021-02-05 19:41:09 -05:00
|
|
|
: m_source(source),
|
|
|
|
m_deref_tokens(deref_tokens),
|
|
|
|
m_expected_stride(expected_stride),
|
2021-06-26 20:02:21 -04:00
|
|
|
m_constant_offset(constant_offset),
|
|
|
|
m_flipped(flipped) {
|
2021-03-05 18:48:01 -05:00
|
|
|
for (auto& token : m_deref_tokens) {
|
|
|
|
if (token.kind() == DerefToken::Kind::INTEGER_EXPRESSION) {
|
|
|
|
token.expr()->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-01 20:41:37 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object ArrayFieldAccess::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
std::vector<goos::Object> elts;
|
|
|
|
elts.push_back(pretty_print::to_symbol("dynamic-array-field-access"));
|
|
|
|
elts.push_back(m_source.to_form(env));
|
|
|
|
for (auto& tok : m_deref_tokens) {
|
|
|
|
elts.push_back(tok.to_form(env));
|
|
|
|
}
|
|
|
|
return pretty_print::build_list(elts);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArrayFieldAccess::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& tok : m_deref_tokens) {
|
|
|
|
tok.apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArrayFieldAccess::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
for (auto& tok : m_deref_tokens) {
|
|
|
|
tok.apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void ArrayFieldAccess::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
vars.insert(m_source);
|
2021-03-05 18:48:01 -05:00
|
|
|
if (recursive) {
|
|
|
|
for (auto& tok : m_deref_tokens) {
|
|
|
|
tok.collect_vars(vars, recursive);
|
|
|
|
}
|
2021-02-01 20:41:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArrayFieldAccess::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto& tok : m_deref_tokens) {
|
|
|
|
tok.get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
// GetMethodElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
GetMethodElement::GetMethodElement(Form* in, std::string name, bool is_object)
|
2021-02-09 20:59:14 -05:00
|
|
|
: m_in(in), m_name(std::move(name)), m_is_object(is_object) {
|
|
|
|
in->parent_element = this;
|
|
|
|
}
|
2021-02-01 20:41:37 -05:00
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object GetMethodElement::to_form_internal(const Env& env) const {
|
2021-02-01 20:41:37 -05:00
|
|
|
return pretty_print::build_list(m_is_object ? "method-of-object" : "method-of-type",
|
|
|
|
m_in->to_form(env), m_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetMethodElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_in->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetMethodElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_in->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void GetMethodElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_in->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-02-01 20:41:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void GetMethodElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_in->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// StringConstantElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
StringConstantElement::StringConstantElement(const std::string& value) : m_value(value) {}
|
|
|
|
|
2021-02-11 14:35:28 -05:00
|
|
|
goos::Object StringConstantElement::to_form_internal(const Env&) const {
|
2021-02-09 20:59:14 -05:00
|
|
|
return goos::StringObject::make_new(m_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StringConstantElement::apply(const std::function<void(FormElement*)>&) {}
|
|
|
|
void StringConstantElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-03-05 18:48:01 -05:00
|
|
|
void StringConstantElement::collect_vars(RegAccessSet&, bool) const {}
|
2021-02-09 20:59:14 -05:00
|
|
|
void StringConstantElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-02-13 11:32:52 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// ConstantTokenElement
|
|
|
|
/////////////////////////////
|
|
|
|
ConstantTokenElement::ConstantTokenElement(const std::string& value) : m_value(value) {}
|
|
|
|
|
|
|
|
goos::Object ConstantTokenElement::to_form_internal(const Env&) const {
|
|
|
|
return pretty_print::to_symbol(m_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConstantTokenElement::apply(const std::function<void(FormElement*)>&) {}
|
|
|
|
void ConstantTokenElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-03-05 18:48:01 -05:00
|
|
|
void ConstantTokenElement::collect_vars(RegAccessSet&, bool) const {}
|
2021-02-13 11:32:52 -05:00
|
|
|
void ConstantTokenElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-02-20 11:42:46 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// ConstantFloatElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
ConstantFloatElement::ConstantFloatElement(float value) : m_value(value) {}
|
|
|
|
|
|
|
|
void ConstantFloatElement::apply(const std::function<void(FormElement*)>&) {}
|
|
|
|
void ConstantFloatElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-03-05 18:48:01 -05:00
|
|
|
void ConstantFloatElement::collect_vars(RegAccessSet&, bool) const {}
|
2021-02-20 11:42:46 -05:00
|
|
|
void ConstantFloatElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
|
|
|
goos::Object ConstantFloatElement::to_form_internal(const Env&) const {
|
2021-02-25 09:51:28 -05:00
|
|
|
return pretty_print::float_representation(m_value);
|
2021-02-20 11:42:46 -05:00
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// StorePlainDeref
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-07-09 22:20:37 -04:00
|
|
|
StorePlainDeref::StorePlainDeref(Form* dst,
|
2021-02-18 11:35:45 -05:00
|
|
|
SimpleExpression expr,
|
|
|
|
int my_idx,
|
2021-02-28 12:38:29 -05:00
|
|
|
RegisterAccess base_var,
|
2021-03-14 16:11:42 -04:00
|
|
|
std::optional<TypeSpec> dst_cast_type,
|
2021-06-05 23:55:36 -04:00
|
|
|
std::optional<TypeSpec> src_cast_type,
|
|
|
|
int size)
|
2021-02-18 11:35:45 -05:00
|
|
|
: m_dst(dst),
|
|
|
|
m_expr(std::move(expr)),
|
|
|
|
m_my_idx(my_idx),
|
2021-03-14 16:11:42 -04:00
|
|
|
m_base_var(base_var),
|
|
|
|
m_dst_cast_type(std::move(dst_cast_type)),
|
2021-06-05 23:55:36 -04:00
|
|
|
m_src_cast_type(std::move(src_cast_type)),
|
2021-07-09 22:20:37 -04:00
|
|
|
m_size(size) {
|
|
|
|
m_dst->parent_element = this;
|
|
|
|
}
|
2021-03-14 16:11:42 -04:00
|
|
|
|
2021-02-18 11:35:45 -05:00
|
|
|
goos::Object StorePlainDeref::to_form_internal(const Env& env) const {
|
2021-03-14 16:11:42 -04:00
|
|
|
std::vector<goos::Object> lst = {pretty_print::to_symbol("set!")};
|
|
|
|
|
|
|
|
if (m_dst_cast_type) {
|
|
|
|
lst.push_back(
|
|
|
|
pretty_print::build_list("the-as", m_dst_cast_type->print(), m_dst->to_form(env)));
|
2021-02-18 11:35:45 -05:00
|
|
|
} else {
|
2021-03-14 16:11:42 -04:00
|
|
|
lst.push_back(m_dst->to_form(env));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_src_cast_type) {
|
|
|
|
lst.push_back(pretty_print::build_list("the-as", m_src_cast_type->print(),
|
|
|
|
m_expr.to_form(env.file->labels, env)));
|
|
|
|
} else {
|
|
|
|
lst.push_back(m_expr.to_form(env.file->labels, env));
|
2021-02-18 11:35:45 -05:00
|
|
|
}
|
2021-03-14 16:11:42 -04:00
|
|
|
|
|
|
|
return pretty_print::build_list(lst);
|
2021-02-18 11:35:45 -05:00
|
|
|
}
|
2021-03-14 16:11:42 -04:00
|
|
|
|
2021-02-18 11:35:45 -05:00
|
|
|
void StorePlainDeref::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_dst->apply(f);
|
|
|
|
}
|
|
|
|
|
2021-07-09 22:20:37 -04:00
|
|
|
void StorePlainDeref::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_dst->apply_form(f);
|
|
|
|
}
|
2021-02-18 11:35:45 -05:00
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void StorePlainDeref::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-02-18 11:35:45 -05:00
|
|
|
m_expr.collect_vars(vars);
|
2021-03-05 18:48:01 -05:00
|
|
|
m_dst->collect_vars(vars, recursive);
|
2021-02-18 11:35:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void StorePlainDeref::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_dst->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// StoreArrayAccess
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-02-18 11:35:45 -05:00
|
|
|
StoreArrayAccess::StoreArrayAccess(ArrayFieldAccess* dst,
|
|
|
|
SimpleExpression expr,
|
|
|
|
int my_idx,
|
2021-04-28 20:51:17 -04:00
|
|
|
RegisterAccess array_src,
|
|
|
|
std::optional<TypeSpec> src_cast_type)
|
|
|
|
: m_dst(dst),
|
|
|
|
m_expr(expr),
|
|
|
|
m_my_idx(my_idx),
|
|
|
|
m_base_var(array_src),
|
|
|
|
m_src_cast_type(src_cast_type) {}
|
2021-02-18 11:35:45 -05:00
|
|
|
|
|
|
|
goos::Object StoreArrayAccess::to_form_internal(const Env& env) const {
|
|
|
|
return pretty_print::build_list("set!", m_dst->to_form(env),
|
|
|
|
m_expr.to_form(env.file->labels, env));
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreArrayAccess::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_dst->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StoreArrayAccess::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_dst->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void StoreArrayAccess::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-02-18 11:35:45 -05:00
|
|
|
m_expr.collect_vars(vars);
|
2021-03-05 18:48:01 -05:00
|
|
|
m_dst->collect_vars(vars, recursive);
|
2021-02-18 11:35:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void StoreArrayAccess::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_dst->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// DecompiledDataElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-07-01 21:38:19 -04:00
|
|
|
DecompiledDataElement::DecompiledDataElement(const DecompilerLabel& label,
|
2021-08-29 11:13:06 -04:00
|
|
|
const std::optional<LabelInfo>& label_info)
|
|
|
|
: m_label(label), m_label_info(label_info) {}
|
2021-02-25 09:51:28 -05:00
|
|
|
|
|
|
|
goos::Object DecompiledDataElement::to_form_internal(const Env&) const {
|
2021-07-01 21:38:19 -04:00
|
|
|
if (m_decompiled) {
|
|
|
|
return m_description;
|
|
|
|
} else {
|
|
|
|
return pretty_print::to_symbol(fmt::format("<static-data {}>", m_label.name));
|
|
|
|
}
|
2021-02-25 09:51:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void DecompiledDataElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DecompiledDataElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
void DecompiledDataElement::collect_vars(RegAccessSet&, bool) const {}
|
2021-02-25 09:51:28 -05:00
|
|
|
|
|
|
|
void DecompiledDataElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-07-01 21:38:19 -04:00
|
|
|
void DecompiledDataElement::do_decomp(const Env& env, const LinkedObjectFile* file) {
|
2021-08-29 11:13:06 -04:00
|
|
|
if (m_label_info) {
|
2022-10-09 12:53:44 -04:00
|
|
|
m_description =
|
|
|
|
decompile_at_label_with_hint(*m_label_info, m_label, env.file->labels,
|
|
|
|
env.file->words_by_seg, *env.dts, file, env.version);
|
2021-07-01 21:38:19 -04:00
|
|
|
} else {
|
|
|
|
m_description = decompile_at_label_guess_type(m_label, env.file->labels, env.file->words_by_seg,
|
2022-10-09 12:53:44 -04:00
|
|
|
env.dts->ts, file, env.version);
|
2021-07-01 21:38:19 -04:00
|
|
|
}
|
|
|
|
m_decompiled = true;
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
/////////////////////////////
|
|
|
|
// LetElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
LetElement::LetElement(Form* body, bool star) : m_body(body), m_star(star) {
|
|
|
|
m_body->parent_element = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::add_def(RegisterAccess dst, Form* value) {
|
|
|
|
value->parent_element = this;
|
|
|
|
m_entries.push_back({dst, value});
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::make_let_star() {
|
|
|
|
m_star = true;
|
|
|
|
}
|
|
|
|
|
2022-06-09 21:18:08 -04:00
|
|
|
void LetElement::clear_let_star() {
|
|
|
|
m_star = false;
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:48:01 -05:00
|
|
|
goos::Object LetElement::to_form_internal(const Env& env) const {
|
|
|
|
std::vector<goos::Object> outer = {pretty_print::to_symbol(m_star ? "let*" : "let")};
|
|
|
|
|
|
|
|
std::vector<goos::Object> def_list;
|
|
|
|
|
|
|
|
for (auto& entry : m_entries) {
|
2021-04-11 16:07:01 -04:00
|
|
|
def_list.push_back(pretty_print::build_list(
|
|
|
|
entry.dest.to_form(env, RegisterAccess::Print::AS_VARIABLE_NO_CAST),
|
|
|
|
entry.src->to_form(env)));
|
2021-03-05 18:48:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
outer.push_back(pretty_print::build_list(def_list));
|
|
|
|
m_body->inline_forms(outer, env);
|
|
|
|
return pretty_print::build_list(outer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& entry : m_entries) {
|
|
|
|
entry.src->apply(f);
|
|
|
|
}
|
|
|
|
m_body->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
for (auto& entry : m_entries) {
|
|
|
|
entry.src->apply_form(f);
|
|
|
|
}
|
|
|
|
m_body->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
for (auto& entry : m_entries) {
|
|
|
|
vars.insert(entry.dest);
|
2021-06-09 21:35:13 -04:00
|
|
|
if (recursive) {
|
|
|
|
entry.src->collect_vars(vars, recursive);
|
|
|
|
}
|
2021-03-05 18:48:01 -05:00
|
|
|
}
|
|
|
|
m_body->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto& entry : m_entries) {
|
|
|
|
regs.insert(entry.dest.reg());
|
|
|
|
}
|
|
|
|
m_body->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::add_entry(const Entry& e) {
|
|
|
|
e.src->parent_element = this;
|
|
|
|
m_entries.push_back(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LetElement::set_body(Form* new_body) {
|
|
|
|
m_body = new_body;
|
|
|
|
m_body->parent_element = this;
|
|
|
|
}
|
|
|
|
|
2021-03-05 21:46:39 -05:00
|
|
|
/////////////////////////////
|
2021-06-25 20:51:25 -04:00
|
|
|
// CounterLoopElement
|
2021-03-05 21:46:39 -05:00
|
|
|
/////////////////////////////
|
|
|
|
|
2021-06-25 20:51:25 -04:00
|
|
|
CounterLoopElement::CounterLoopElement(Kind kind,
|
|
|
|
RegisterAccess var_init,
|
|
|
|
RegisterAccess var_check,
|
|
|
|
RegisterAccess var_inc,
|
|
|
|
Form* check_value,
|
|
|
|
Form* body)
|
2021-03-05 21:46:39 -05:00
|
|
|
: m_var_init(var_init),
|
|
|
|
m_var_check(var_check),
|
|
|
|
m_var_inc(var_inc),
|
|
|
|
m_check_value(check_value),
|
2021-06-25 20:51:25 -04:00
|
|
|
m_body(body),
|
|
|
|
m_kind(kind) {
|
2021-03-05 21:46:39 -05:00
|
|
|
m_body->parent_element = this;
|
|
|
|
m_check_value->parent_element = this;
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(m_var_inc.reg() == m_var_check.reg());
|
|
|
|
ASSERT(m_var_init.reg() == m_var_inc.reg());
|
2021-03-05 21:46:39 -05:00
|
|
|
}
|
|
|
|
|
2021-06-25 20:51:25 -04:00
|
|
|
goos::Object CounterLoopElement::to_form_internal(const Env& env) const {
|
|
|
|
std::string loop_name;
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::DOTIMES:
|
|
|
|
loop_name = "dotimes";
|
|
|
|
break;
|
|
|
|
case Kind::COUNTDOWN:
|
|
|
|
loop_name = "countdown";
|
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-06-25 20:51:25 -04:00
|
|
|
}
|
2021-03-05 21:46:39 -05:00
|
|
|
std::vector<goos::Object> outer = {
|
2021-06-25 20:51:25 -04:00
|
|
|
pretty_print::to_symbol(loop_name),
|
2021-03-05 21:46:39 -05:00
|
|
|
pretty_print::build_list(m_var_init.to_form(env), m_check_value->to_form(env))};
|
|
|
|
m_body->inline_forms(outer, env);
|
|
|
|
return pretty_print::build_list(outer);
|
|
|
|
}
|
|
|
|
|
2021-06-25 20:51:25 -04:00
|
|
|
void CounterLoopElement::apply(const std::function<void(FormElement*)>& f) {
|
2021-03-05 21:46:39 -05:00
|
|
|
f(this);
|
|
|
|
m_check_value->apply(f);
|
|
|
|
m_body->apply(f);
|
|
|
|
}
|
|
|
|
|
2021-06-25 20:51:25 -04:00
|
|
|
void CounterLoopElement::apply_form(const std::function<void(Form*)>& f) {
|
2021-03-05 21:46:39 -05:00
|
|
|
m_check_value->apply_form(f);
|
|
|
|
m_body->apply_form(f);
|
|
|
|
}
|
|
|
|
|
2021-06-25 20:51:25 -04:00
|
|
|
void CounterLoopElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
2021-03-05 21:46:39 -05:00
|
|
|
vars.insert(m_var_init);
|
|
|
|
vars.insert(m_var_check);
|
|
|
|
vars.insert(m_var_inc);
|
|
|
|
if (recursive) {
|
|
|
|
m_body->collect_vars(vars, recursive);
|
|
|
|
m_check_value->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-25 20:51:25 -04:00
|
|
|
void CounterLoopElement::get_modified_regs(RegSet& regs) const {
|
2021-03-05 21:46:39 -05:00
|
|
|
regs.insert(m_var_inc.reg());
|
|
|
|
m_body->get_modified_regs(regs);
|
|
|
|
m_check_value->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-03-14 19:06:51 -04:00
|
|
|
/////////////////////////////
|
|
|
|
// LambdaDefinitionElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
|
|
|
LambdaDefinitionElement::LambdaDefinitionElement(const goos::Object& def) : m_def(def) {}
|
|
|
|
|
|
|
|
goos::Object LambdaDefinitionElement::to_form_internal(const Env&) const {
|
|
|
|
return m_def;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LambdaDefinitionElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
|
|
|
void LambdaDefinitionElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LambdaDefinitionElement::collect_vars(RegAccessSet&, bool) const {}
|
|
|
|
|
|
|
|
void LambdaDefinitionElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-03-27 15:18:59 -04:00
|
|
|
/////////////////////////////
|
|
|
|
// StackVarDefElement
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-06-04 13:43:19 -04:00
|
|
|
StackStructureDefElement::StackStructureDefElement(const StackStructureEntry& entry)
|
|
|
|
: m_entry(entry) {}
|
2021-03-27 15:18:59 -04:00
|
|
|
|
2021-06-04 13:43:19 -04:00
|
|
|
goos::Object StackStructureDefElement::to_form_internal(const Env&) const {
|
2021-03-27 15:18:59 -04:00
|
|
|
switch (m_entry.hint.container_type) {
|
2021-06-04 13:43:19 -04:00
|
|
|
case StackStructureHint::ContainerType::NONE:
|
2021-04-18 19:51:15 -04:00
|
|
|
return pretty_print::build_list(
|
|
|
|
fmt::format("new 'stack-no-clear '{}", m_entry.ref_type.print()));
|
2021-07-26 21:39:05 -04:00
|
|
|
case StackStructureHint::ContainerType::INLINE_ARRAY:
|
|
|
|
return pretty_print::build_list(fmt::format("new 'stack-no-clear 'inline-array '{} {}",
|
|
|
|
m_entry.ref_type.get_single_arg().print(),
|
|
|
|
m_entry.hint.container_size));
|
2021-08-14 23:15:10 -04:00
|
|
|
case StackStructureHint::ContainerType::ARRAY:
|
|
|
|
return pretty_print::build_list(fmt::format("new 'stack-no-clear 'array '{} {}",
|
|
|
|
m_entry.ref_type.get_single_arg().print(),
|
|
|
|
m_entry.hint.container_size));
|
2021-03-27 15:18:59 -04:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-27 15:18:59 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-04 13:43:19 -04:00
|
|
|
void StackStructureDefElement::apply_form(const std::function<void(Form*)>&) {}
|
2021-03-27 15:18:59 -04:00
|
|
|
|
2021-06-04 13:43:19 -04:00
|
|
|
void StackStructureDefElement::apply(const std::function<void(FormElement*)>& f) {
|
2021-03-27 15:18:59 -04:00
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
2021-06-04 13:43:19 -04:00
|
|
|
void StackStructureDefElement::collect_vars(RegAccessSet&, bool) const {}
|
2021-03-27 15:18:59 -04:00
|
|
|
|
2021-06-04 13:43:19 -04:00
|
|
|
void StackStructureDefElement::get_modified_regs(RegSet&) const {}
|
2021-03-27 15:18:59 -04:00
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// VectorFloatLoadStoreElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
VectorFloatLoadStoreElement::VectorFloatLoadStoreElement(Register vf_reg,
|
|
|
|
Form* location,
|
2021-06-26 22:52:52 -04:00
|
|
|
bool is_load,
|
|
|
|
int my_idx)
|
|
|
|
: m_vf_reg(vf_reg), m_location(location), m_is_load(is_load), m_my_idx(my_idx) {
|
2021-03-27 15:18:59 -04:00
|
|
|
location->parent_element = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object VectorFloatLoadStoreElement::to_form_internal(const Env& env) const {
|
|
|
|
if (m_is_load) {
|
|
|
|
return pretty_print::build_list(".lvf", pretty_print::to_symbol(m_vf_reg.to_charp()),
|
|
|
|
m_location->to_form(env));
|
|
|
|
} else {
|
|
|
|
return pretty_print::build_list(".svf", m_location->to_form(env),
|
|
|
|
pretty_print::to_symbol(m_vf_reg.to_charp()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VectorFloatLoadStoreElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_location->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VectorFloatLoadStoreElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_location->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VectorFloatLoadStoreElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_location->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VectorFloatLoadStoreElement::get_modified_regs(RegSet&) const {
|
|
|
|
// vf's dont count
|
|
|
|
}
|
|
|
|
|
|
|
|
void VectorFloatLoadStoreElement::collect_vf_regs(RegSet& regs) const {
|
|
|
|
regs.insert(m_vf_reg);
|
|
|
|
}
|
|
|
|
|
2021-04-25 14:48:54 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// StackSpillStoreElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
2021-05-05 17:38:16 -04:00
|
|
|
StackSpillStoreElement::StackSpillStoreElement(SimpleAtom value,
|
2021-04-25 14:48:54 -04:00
|
|
|
int size,
|
|
|
|
int stack_offset,
|
|
|
|
const std::optional<TypeSpec>& cast_type)
|
|
|
|
: m_value(value), m_size(size), m_stack_offset(stack_offset), m_cast_type(cast_type) {}
|
|
|
|
|
|
|
|
goos::Object StackSpillStoreElement::to_form_internal(const Env& env) const {
|
|
|
|
return pretty_print::build_list(
|
|
|
|
fmt::format("set! {}", env.get_spill_slot_var_name(m_stack_offset)), m_value.to_form(env));
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackSpillStoreElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackSpillStoreElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
|
|
|
void StackSpillStoreElement::collect_vars(RegAccessSet& vars, bool) const {
|
2021-05-05 17:38:16 -04:00
|
|
|
if (m_value.is_var()) {
|
|
|
|
vars.insert(m_value.var());
|
|
|
|
}
|
2021-04-25 14:48:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void StackSpillStoreElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// StackSpillValueElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
StackSpillValueElement::StackSpillValueElement(int size, int stack_offset, bool is_signed)
|
|
|
|
: m_size(size), m_stack_offset(stack_offset), m_is_signed(is_signed) {}
|
|
|
|
|
|
|
|
goos::Object StackSpillValueElement::to_form_internal(const Env& env) const {
|
|
|
|
return pretty_print::to_symbol(env.get_spill_slot_var_name(m_stack_offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackSpillValueElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackSpillValueElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
void StackSpillValueElement::collect_vars(RegAccessSet&, bool) const {}
|
|
|
|
void StackSpillValueElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-05-06 00:42:49 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// MethodOfTypeElement
|
|
|
|
///////////////////////////////
|
|
|
|
|
|
|
|
MethodOfTypeElement::MethodOfTypeElement(RegisterAccess type_reg,
|
|
|
|
const TypeSpec& type_at_decompile,
|
|
|
|
const MethodInfo& method_info)
|
|
|
|
: m_type_reg(type_reg), m_type_at_decompile(type_at_decompile), m_method_info(method_info) {}
|
|
|
|
|
|
|
|
goos::Object MethodOfTypeElement::to_form_internal(const Env& env) const {
|
|
|
|
return pretty_print::build_list("method-of-type", m_type_reg.to_form(env), m_method_info.name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MethodOfTypeElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MethodOfTypeElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
|
|
|
|
void MethodOfTypeElement::collect_vars(RegAccessSet& vars, bool) const {
|
|
|
|
vars.insert(m_type_reg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MethodOfTypeElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-05-23 20:16:34 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// LabelElement
|
|
|
|
///////////////////////////////
|
|
|
|
|
|
|
|
LabelElement::LabelElement(int lid) : m_lid(lid) {}
|
|
|
|
|
|
|
|
goos::Object LabelElement::to_form_internal(const Env&) const {
|
|
|
|
return pretty_print::build_list(fmt::format("label cfg-{}", m_lid));
|
|
|
|
}
|
|
|
|
|
|
|
|
void LabelElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LabelElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
void LabelElement::collect_vars(RegAccessSet&, bool) const {}
|
|
|
|
void LabelElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-08-19 20:35:12 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// LabelDerefElement
|
|
|
|
///////////////////////////////
|
|
|
|
|
|
|
|
LabelDerefElement::LabelDerefElement(int lid,
|
|
|
|
int size,
|
|
|
|
LoadVarOp::Kind load_kind,
|
|
|
|
RegisterAccess var)
|
|
|
|
: m_lid(lid), m_size(size), m_load_kind(load_kind), m_var(var) {}
|
|
|
|
|
|
|
|
goos::Object LabelDerefElement::to_form_internal(const Env& env) const {
|
|
|
|
return pretty_print::build_list(fmt::format("label-deref {} :label {} :size {} :kind {}",
|
|
|
|
m_var.to_string(env), env.file->labels.at(m_lid).name,
|
|
|
|
m_size, load_kind_to_string(m_load_kind)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void LabelDerefElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LabelDerefElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
void LabelDerefElement::collect_vars(RegAccessSet& regs, bool) const {
|
|
|
|
regs.insert(m_var);
|
|
|
|
}
|
|
|
|
void LabelDerefElement::get_modified_regs(RegSet&) const {}
|
|
|
|
|
2021-05-23 20:16:34 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// GetSymbolStringPointer
|
|
|
|
//////////////////////////////
|
|
|
|
|
|
|
|
GetSymbolStringPointer::GetSymbolStringPointer(Form* src) : m_src(src) {
|
|
|
|
m_src->parent_element = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object GetSymbolStringPointer::to_form_internal(const Env& env) const {
|
|
|
|
return pretty_print::build_list("sym->str-ptr", m_src->to_form(env));
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetSymbolStringPointer::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_src->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetSymbolStringPointer::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_src->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetSymbolStringPointer::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_src->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetSymbolStringPointer::get_modified_regs(RegSet& regs) const {
|
|
|
|
return m_src->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
2021-08-17 20:54:03 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// DefstateElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
DefstateElement::DefstateElement(const std::string& process_type,
|
|
|
|
const std::string& state_name,
|
|
|
|
const std::vector<Entry>& entries,
|
2022-01-31 20:44:54 -05:00
|
|
|
bool is_virtual,
|
|
|
|
bool is_override)
|
2021-08-17 20:54:03 -04:00
|
|
|
: m_process_type(process_type),
|
|
|
|
m_state_name(state_name),
|
|
|
|
m_entries(entries),
|
2022-01-31 20:44:54 -05:00
|
|
|
m_is_virtual(is_virtual),
|
|
|
|
m_is_override(is_override) {
|
2021-08-17 20:54:03 -04:00
|
|
|
for (auto& e : m_entries) {
|
|
|
|
e.val->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefstateElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
e.val->apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefstateElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
e.val->apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefstateElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
e.val->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefstateElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto& e : m_entries) {
|
|
|
|
e.val->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object DefstateElement::to_form_internal(const Env& env) const {
|
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
forms.push_back(pretty_print::to_symbol("defstate"));
|
|
|
|
forms.push_back(pretty_print::to_symbol(m_state_name));
|
|
|
|
forms.push_back(pretty_print::build_list(m_process_type));
|
|
|
|
|
|
|
|
if (m_is_virtual) {
|
2022-01-31 20:44:54 -05:00
|
|
|
if (!m_is_override) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(":virtual #t"));
|
|
|
|
} else {
|
|
|
|
forms.push_back(pretty_print::to_symbol(":virtual override"));
|
|
|
|
}
|
2021-08-17 20:54:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& e : m_entries) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(":{}", handler_kind_to_name(e.kind))));
|
|
|
|
auto to_print = e.val;
|
|
|
|
forms.push_back(to_print->to_form(env));
|
|
|
|
}
|
|
|
|
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
2021-11-04 19:10:39 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// DefskelgroupElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
DefskelgroupElement::DefskelgroupElement(const std::string& name,
|
|
|
|
const DefskelgroupElement::Info& info,
|
|
|
|
const StaticInfo& data)
|
|
|
|
: m_name(name), m_static_info(data), m_info(info) {
|
|
|
|
for (auto& e : m_info.lods) {
|
|
|
|
e.mgeo->parent_element = this;
|
|
|
|
e.lod_dist->parent_element = this;
|
|
|
|
}
|
|
|
|
m_info.janim->parent_element = this;
|
|
|
|
m_info.jgeo->parent_element = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefskelgroupElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
for (auto& e : m_info.lods) {
|
|
|
|
e.mgeo->apply(f);
|
|
|
|
e.lod_dist->apply(f);
|
|
|
|
}
|
|
|
|
m_info.janim->apply(f);
|
|
|
|
m_info.jgeo->apply(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefskelgroupElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
for (auto& e : m_info.lods) {
|
|
|
|
e.mgeo->apply_form(f);
|
|
|
|
e.lod_dist->apply_form(f);
|
|
|
|
}
|
|
|
|
m_info.janim->apply_form(f);
|
|
|
|
m_info.jgeo->apply_form(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefskelgroupElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
for (auto& e : m_info.lods) {
|
|
|
|
e.mgeo->collect_vars(vars, recursive);
|
|
|
|
e.lod_dist->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
m_info.janim->collect_vars(vars, recursive);
|
|
|
|
m_info.jgeo->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DefskelgroupElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
for (auto& e : m_info.lods) {
|
|
|
|
e.mgeo->get_modified_regs(regs);
|
|
|
|
e.lod_dist->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
m_info.janim->get_modified_regs(regs);
|
|
|
|
m_info.jgeo->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object DefskelgroupElement::to_form_internal(const Env& env) const {
|
|
|
|
std::vector<goos::Object> forms;
|
2022-05-19 21:30:14 -04:00
|
|
|
forms.push_back(pretty_print::to_symbol("defskelgroup"));
|
|
|
|
forms.push_back(pretty_print::to_symbol(m_name));
|
2022-10-14 19:35:57 -04:00
|
|
|
forms.push_back(pretty_print::to_symbol(m_static_info.art_group_name));
|
|
|
|
const auto& art = env.dts->art_group_info.find(m_static_info.art_group_name + "-ag");
|
2022-05-19 21:30:14 -04:00
|
|
|
bool has_art = art != env.dts->art_group_info.end();
|
|
|
|
auto jg = m_info.jgeo->to_form(env);
|
|
|
|
if (jg.is_int() && has_art && art->second.count(jg.as_int())) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(art->second.at(jg.as_int())));
|
|
|
|
} else {
|
|
|
|
forms.push_back(jg);
|
|
|
|
}
|
|
|
|
auto ja = m_info.janim->to_form(env);
|
|
|
|
if (ja.is_int() && has_art && art->second.count(ja.as_int())) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(art->second.at(ja.as_int())));
|
|
|
|
} else {
|
|
|
|
forms.push_back(ja);
|
|
|
|
}
|
2021-11-04 19:10:39 -04:00
|
|
|
|
|
|
|
std::vector<goos::Object> lod_forms;
|
|
|
|
for (const auto& e : m_info.lods) {
|
2022-01-15 20:01:38 -05:00
|
|
|
auto f_dist = pretty_print::to_symbol(
|
|
|
|
fmt::format("(meters {})", meters_to_string(e.lod_dist->to_form(env).as_float())));
|
2022-05-19 21:30:14 -04:00
|
|
|
auto mg = e.mgeo->to_form(env);
|
|
|
|
if (mg.is_int() && has_art && art->second.count(mg.as_int())) {
|
|
|
|
lod_forms.push_back(
|
|
|
|
pretty_print::build_list(pretty_print::to_symbol(art->second.at(mg.as_int())), f_dist));
|
|
|
|
} else {
|
|
|
|
lod_forms.push_back(pretty_print::build_list(mg, f_dist));
|
|
|
|
}
|
2021-11-04 19:10:39 -04:00
|
|
|
}
|
|
|
|
forms.push_back(pretty_print::build_list(lod_forms));
|
|
|
|
|
2022-01-15 20:01:38 -05:00
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(
|
|
|
|
":bounds (static-spherem {} {} {} {})", meters_to_string(m_static_info.bounds.x()),
|
|
|
|
meters_to_string(m_static_info.bounds.y()), meters_to_string(m_static_info.bounds.z()),
|
|
|
|
meters_to_string(m_static_info.bounds.w()))));
|
2022-05-19 21:30:14 -04:00
|
|
|
|
|
|
|
if (m_static_info.longest_edge != 0) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(
|
|
|
|
fmt::format(":longest-edge (meters {})", meters_to_string(m_static_info.longest_edge))));
|
|
|
|
}
|
2021-11-04 19:10:39 -04:00
|
|
|
|
|
|
|
if (m_static_info.shadow != 0) {
|
2022-05-19 21:30:14 -04:00
|
|
|
if (has_art && art->second.count(m_static_info.shadow)) {
|
|
|
|
forms.push_back(
|
|
|
|
pretty_print::to_symbol(fmt::format(":shadow {}", art->second.at(m_static_info.shadow))));
|
|
|
|
} else {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(":shadow {}", m_static_info.shadow)));
|
|
|
|
}
|
2021-11-04 19:10:39 -04:00
|
|
|
}
|
|
|
|
if (m_static_info.tex_level != 0) {
|
|
|
|
forms.push_back(
|
|
|
|
pretty_print::to_symbol(fmt::format(":texture-level {}", m_static_info.tex_level)));
|
|
|
|
}
|
|
|
|
if (m_static_info.sort != 0) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(":sort {}", m_static_info.sort)));
|
|
|
|
}
|
2022-10-14 19:35:57 -04:00
|
|
|
// jak 2 skelgroups seem to be using version 7
|
|
|
|
if (env.version != GameVersion::Jak1) {
|
|
|
|
if (m_static_info.version != 7) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(":version {}", m_static_info.version)));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (m_static_info.version != 6) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(":version {}", m_static_info.version)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (env.version != GameVersion::Jak1) {
|
|
|
|
if (m_static_info.origin_joint_index != 0) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(
|
|
|
|
fmt::format(":origin-joint-index {}", m_static_info.origin_joint_index)));
|
|
|
|
}
|
|
|
|
if (m_static_info.shadow_joint_index != 0) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(
|
|
|
|
fmt::format(":shadow-joint-index {}", m_static_info.origin_joint_index)));
|
|
|
|
}
|
|
|
|
if (m_static_info.light_index != 0) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(
|
|
|
|
fmt::format(":light-index {}", m_static_info.origin_joint_index)));
|
|
|
|
}
|
2021-11-04 19:10:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
2022-01-15 20:01:38 -05:00
|
|
|
////////////////////////////////
|
|
|
|
// DefpartgroupElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
DefpartgroupElement::DefpartgroupElement(const StaticInfo& data, int group_id)
|
|
|
|
: m_static_info(data), m_group_id(group_id) {}
|
|
|
|
|
|
|
|
void DefpartgroupElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
2022-01-17 14:36:29 -05:00
|
|
|
void DefpartgroupElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
void DefpartgroupElement::collect_vars(RegAccessSet&, bool) const {}
|
|
|
|
void DefpartgroupElement::get_modified_regs(RegSet&) const {}
|
2022-01-15 20:01:38 -05:00
|
|
|
|
|
|
|
goos::Object DefpartgroupElement::to_form_internal(const Env& env) const {
|
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format("defpartgroup {}", name())));
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(":id {}", m_group_id)));
|
|
|
|
if (m_static_info.duration != 3000) {
|
2022-10-09 12:53:44 -04:00
|
|
|
forms.push_back(pretty_print::to_symbol(
|
|
|
|
fmt::format(":duration (seconds {})", seconds_to_string(m_static_info.duration))));
|
2022-01-15 20:01:38 -05:00
|
|
|
}
|
|
|
|
if (m_static_info.linger != 1500) {
|
2022-10-09 12:53:44 -04:00
|
|
|
// 5 seconds is default
|
|
|
|
forms.push_back(pretty_print::to_symbol(
|
|
|
|
fmt::format(":linger-duration (seconds {})", seconds_to_string(m_static_info.linger))));
|
2022-01-15 20:01:38 -05:00
|
|
|
}
|
|
|
|
if (m_static_info.flags != 0) {
|
|
|
|
auto things = decompile_bitfield_enum_from_int(TypeSpec("sp-group-flag"), env.dts->ts,
|
|
|
|
m_static_info.flags);
|
|
|
|
std::string result = ":flags (";
|
|
|
|
for (auto& thing : things) {
|
|
|
|
result += thing;
|
|
|
|
result += ' ';
|
|
|
|
}
|
|
|
|
result.pop_back();
|
|
|
|
result += ')';
|
|
|
|
forms.push_back(pretty_print::to_symbol(result));
|
|
|
|
}
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(
|
|
|
|
":bounds (static-bspherem {} {} {} {})", meters_to_string(m_static_info.bounds.x()),
|
|
|
|
meters_to_string(m_static_info.bounds.y()), meters_to_string(m_static_info.bounds.z()),
|
|
|
|
meters_to_string(m_static_info.bounds.w()))));
|
|
|
|
|
2022-10-09 12:53:44 -04:00
|
|
|
if (env.version != GameVersion::Jak1) {
|
|
|
|
// jak 2 stuff.
|
|
|
|
if (m_static_info.rot != 0) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(
|
|
|
|
":rotate ((degrees {}) (degrees {}) (degrees {}))",
|
|
|
|
meters_to_string(m_static_info.rot.x()), meters_to_string(m_static_info.rot.y()),
|
|
|
|
meters_to_string(m_static_info.rot.z()))));
|
|
|
|
}
|
|
|
|
if (m_static_info.scale != 1) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format(
|
|
|
|
":scale ({} {} {})", float_to_string(m_static_info.rot.x()),
|
|
|
|
float_to_string(m_static_info.rot.y()), float_to_string(m_static_info.rot.z()))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-15 20:01:38 -05:00
|
|
|
std::vector<goos::Object> item_forms;
|
|
|
|
for (const auto& e : m_static_info.elts) {
|
|
|
|
s32 launcher = e.part_id;
|
|
|
|
u16 flags = e.flags;
|
|
|
|
u16 period = e.period;
|
|
|
|
u16 length = e.length;
|
|
|
|
u16 offset = e.offset;
|
|
|
|
u32 hour_mask = e.hour_mask;
|
|
|
|
u32 binding = e.binding;
|
|
|
|
|
|
|
|
std::string result =
|
|
|
|
fmt::format("(sp-item {}", launcher); // use decimal, so it matches array idx
|
|
|
|
|
|
|
|
if (e.fade != 0.0) {
|
|
|
|
result += fmt::format(" :fade-after (meters {})", meters_to_string(e.fade));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e.falloff != 0.0) {
|
|
|
|
result += fmt::format(" :falloff-to (meters {})", meters_to_string(e.falloff));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags) {
|
|
|
|
auto things =
|
|
|
|
decompile_bitfield_enum_from_int(TypeSpec("sp-group-item-flag"), env.dts->ts, flags);
|
|
|
|
result += " :flags (";
|
|
|
|
for (auto& thing : things) {
|
|
|
|
result += thing;
|
|
|
|
result += ' ';
|
|
|
|
}
|
|
|
|
result.pop_back();
|
|
|
|
result += ')';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (period) {
|
|
|
|
result += fmt::format(" :period {}", period);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length) {
|
|
|
|
result += fmt::format(" :length {}", length);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset) {
|
|
|
|
result += fmt::format(" :offset {}", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hour_mask) {
|
|
|
|
result += fmt::format(" :hour-mask #b{:b}", hour_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (binding) {
|
|
|
|
result += fmt::format(" :binding {}", binding);
|
|
|
|
}
|
|
|
|
|
|
|
|
result += ')';
|
|
|
|
|
|
|
|
item_forms.push_back(pretty_print::to_symbol(result));
|
|
|
|
}
|
|
|
|
if (!item_forms.empty()) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(":parts"));
|
|
|
|
forms.push_back(pretty_print::build_list(item_forms));
|
|
|
|
}
|
|
|
|
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// DefpartElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
DefpartElement::DefpartElement(const StaticInfo& data, int id) : m_static_info(data), m_id(id) {}
|
|
|
|
|
|
|
|
void DefpartElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
}
|
|
|
|
|
2022-01-17 14:36:29 -05:00
|
|
|
void DefpartElement::apply_form(const std::function<void(Form*)>&) {}
|
|
|
|
void DefpartElement::collect_vars(RegAccessSet&, bool) const {}
|
|
|
|
void DefpartElement::get_modified_regs(RegSet&) const {}
|
2022-01-15 20:01:38 -05:00
|
|
|
|
|
|
|
goos::Object DefpartElement::to_form_internal(const Env& env) const {
|
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
forms.push_back(pretty_print::to_symbol("defpart"));
|
|
|
|
forms.push_back(pretty_print::to_symbol(fmt::format("{}", m_id)));
|
|
|
|
|
|
|
|
std::vector<goos::Object> item_forms;
|
|
|
|
for (const auto& e : m_static_info.fields) {
|
2022-10-09 12:53:44 -04:00
|
|
|
if (e.is_sp_end(env.version)) {
|
2022-01-15 20:01:38 -05:00
|
|
|
// sp-end
|
|
|
|
break;
|
|
|
|
}
|
2022-10-09 12:53:44 -04:00
|
|
|
item_forms.push_back(decompile_sparticle_field_init(e, env.dts->ts, env.version));
|
2022-01-15 20:01:38 -05:00
|
|
|
}
|
|
|
|
if (!item_forms.empty()) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(":init-specs"));
|
|
|
|
forms.push_back(pretty_print::build_list(item_forms));
|
|
|
|
}
|
|
|
|
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
|
|
|
|
2021-08-31 15:01:54 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// ResLumpMacroElement
|
|
|
|
////////////////////////////////
|
|
|
|
|
|
|
|
ResLumpMacroElement::ResLumpMacroElement(Kind kind,
|
|
|
|
Form* lump_object,
|
|
|
|
Form* property_name,
|
|
|
|
Form* default_arg,
|
|
|
|
Form* tag_ptr,
|
|
|
|
Form* time,
|
|
|
|
const TypeSpec& result_type)
|
|
|
|
: m_kind(kind),
|
|
|
|
m_lump_object(lump_object),
|
|
|
|
m_property_name(property_name),
|
|
|
|
m_default_arg(default_arg),
|
|
|
|
m_tag_ptr(tag_ptr),
|
|
|
|
m_time(time),
|
|
|
|
m_result_type(result_type) {
|
|
|
|
m_lump_object->parent_element = this;
|
|
|
|
m_property_name->parent_element = this;
|
|
|
|
if (m_default_arg) {
|
|
|
|
m_default_arg->parent_element = this;
|
|
|
|
}
|
|
|
|
if (m_tag_ptr) {
|
|
|
|
m_tag_ptr->parent_element = this;
|
|
|
|
}
|
|
|
|
if (m_time) {
|
|
|
|
m_time->parent_element = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ResLumpMacroElement::apply(const std::function<void(FormElement*)>& f) {
|
|
|
|
f(this);
|
|
|
|
m_lump_object->apply(f);
|
|
|
|
m_property_name->apply(f);
|
|
|
|
if (m_default_arg) {
|
|
|
|
m_default_arg->apply(f);
|
|
|
|
}
|
|
|
|
if (m_tag_ptr) {
|
|
|
|
m_tag_ptr->apply(f);
|
|
|
|
}
|
|
|
|
if (m_time) {
|
|
|
|
m_time->apply(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ResLumpMacroElement::apply_form(const std::function<void(Form*)>& f) {
|
|
|
|
m_lump_object->apply_form(f);
|
|
|
|
m_property_name->apply_form(f);
|
|
|
|
if (m_default_arg) {
|
|
|
|
m_default_arg->apply_form(f);
|
|
|
|
}
|
|
|
|
if (m_tag_ptr) {
|
|
|
|
m_tag_ptr->apply_form(f);
|
|
|
|
}
|
|
|
|
if (m_time) {
|
|
|
|
m_time->apply_form(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ResLumpMacroElement::collect_vars(RegAccessSet& vars, bool recursive) const {
|
|
|
|
if (recursive) {
|
|
|
|
m_lump_object->collect_vars(vars, recursive);
|
|
|
|
m_property_name->collect_vars(vars, recursive);
|
|
|
|
if (m_default_arg) {
|
|
|
|
m_default_arg->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
if (m_tag_ptr) {
|
|
|
|
m_tag_ptr->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
if (m_time) {
|
|
|
|
m_time->collect_vars(vars, recursive);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ResLumpMacroElement::get_modified_regs(RegSet& regs) const {
|
|
|
|
m_lump_object->get_modified_regs(regs);
|
|
|
|
m_property_name->get_modified_regs(regs);
|
|
|
|
if (m_default_arg) {
|
|
|
|
m_default_arg->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
if (m_tag_ptr) {
|
|
|
|
m_tag_ptr->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
if (m_time) {
|
|
|
|
m_time->get_modified_regs(regs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
goos::Object ResLumpMacroElement::to_form_internal(const Env& env) const {
|
|
|
|
std::vector<goos::Object> forms;
|
|
|
|
|
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::DATA:
|
|
|
|
forms.push_back(pretty_print::to_symbol("res-lump-data"));
|
|
|
|
break;
|
|
|
|
case Kind::STRUCT:
|
|
|
|
forms.push_back(pretty_print::to_symbol("res-lump-struct"));
|
|
|
|
break;
|
|
|
|
case Kind::VALUE:
|
|
|
|
forms.push_back(pretty_print::to_symbol("res-lump-value"));
|
|
|
|
break;
|
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-08-31 15:01:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
forms.push_back(m_lump_object->to_form(env));
|
|
|
|
forms.push_back(m_property_name->to_form(env));
|
|
|
|
|
|
|
|
forms.push_back(pretty_print::to_symbol(m_result_type.print()));
|
|
|
|
|
|
|
|
if (m_default_arg) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(":default"));
|
|
|
|
forms.push_back(m_default_arg->to_form(env));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_tag_ptr) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(":tag-ptr"));
|
|
|
|
forms.push_back(m_tag_ptr->to_form(env));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_time) {
|
|
|
|
forms.push_back(pretty_print::to_symbol(":time"));
|
|
|
|
forms.push_back(m_time->to_form(env));
|
|
|
|
}
|
|
|
|
|
|
|
|
return pretty_print::build_list(forms);
|
|
|
|
}
|
2021-04-11 16:07:01 -04:00
|
|
|
////////////////////////////////
|
|
|
|
// Utilities
|
|
|
|
////////////////////////////////
|
|
|
|
|
2021-05-30 19:57:11 -04:00
|
|
|
std::optional<SimpleAtom> form_element_as_atom(const FormElement* f) {
|
|
|
|
auto as_atom = dynamic_cast<const SimpleAtomElement*>(f);
|
2021-03-05 21:46:39 -05:00
|
|
|
if (as_atom) {
|
|
|
|
return as_atom->atom();
|
|
|
|
}
|
|
|
|
|
2021-05-30 19:57:11 -04:00
|
|
|
auto as_se = dynamic_cast<const SimpleExpressionElement*>(f);
|
2021-03-05 21:46:39 -05:00
|
|
|
if (as_se && as_se->expr().is_identity()) {
|
|
|
|
return as_se->expr().get_arg(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
2021-04-02 11:35:14 -04:00
|
|
|
|
2021-05-30 19:57:11 -04:00
|
|
|
std::optional<SimpleAtom> form_as_atom(const Form* f) {
|
|
|
|
auto as_single = f->try_as_single_element();
|
|
|
|
return form_element_as_atom(as_single);
|
|
|
|
}
|
|
|
|
|
2021-04-02 11:35:14 -04:00
|
|
|
FormElement* make_cast_using_existing(FormElement* elt, const TypeSpec& type, FormPool& pool) {
|
|
|
|
auto as_cast = dynamic_cast<CastElement*>(elt);
|
|
|
|
if (as_cast) {
|
|
|
|
if (as_cast->type() != type) {
|
|
|
|
as_cast->set_type(type);
|
|
|
|
}
|
|
|
|
return as_cast;
|
|
|
|
} else {
|
|
|
|
return pool.alloc_element<CastElement>(type, pool.alloc_single_form(nullptr, elt));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-05 20:22:03 -04:00
|
|
|
GenericElement* alloc_generic_token_op(const std::string& name,
|
|
|
|
const std::vector<Form*>& args,
|
|
|
|
FormPool& pool) {
|
|
|
|
auto op = GenericOperator::make_function(
|
|
|
|
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, name));
|
|
|
|
return pool.alloc_element<GenericElement>(op, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
Form* alloc_var_form(const RegisterAccess& var, FormPool& pool) {
|
|
|
|
return pool.alloc_single_element_form<SimpleAtomElement>(nullptr, SimpleAtom::make_var(var));
|
|
|
|
}
|
|
|
|
|
2021-01-17 18:08:18 -05:00
|
|
|
} // namespace decompiler
|