mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
[Decompiler] Clean Up (#271)
* clean up * fix up until generic ops * finish kernel * documentation * types * add missing file
This commit is contained in:
parent
1b5b9a2469
commit
db48d94270
|
@ -232,6 +232,11 @@ class SimpleExpression {
|
|||
goos::Object to_form(const std::vector<DecompilerLabel>& labels, const Env& env) const;
|
||||
bool operator==(const SimpleExpression& other) const;
|
||||
bool is_identity() const { return m_kind == Kind::IDENTITY; }
|
||||
bool is_var() const { return is_identity() && get_arg(0).is_var(); }
|
||||
const Variable& var() const {
|
||||
assert(is_var());
|
||||
return get_arg(0).var();
|
||||
}
|
||||
void get_regs(std::vector<Register>* out) const;
|
||||
TP_Type get_type(const TypeState& input, const Env& env, const DecompilerTypeSystem& dts) const;
|
||||
TP_Type get_type_int2(const TypeState& input,
|
||||
|
|
|
@ -106,10 +106,8 @@ FormElement* SetVarConditionOp::get_as_form(FormPool& pool, const Env& env) cons
|
|||
FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
||||
if (env.has_type_analysis()) {
|
||||
if (m_addr.is_identity() && m_addr.get_arg(0).is_sym_val()) {
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_value.as_expr(),
|
||||
m_my_idx);
|
||||
auto src = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_addr, m_my_idx);
|
||||
return pool.alloc_element<SetFormFormElement>(src, val);
|
||||
return pool.alloc_element<StoreInSymbolElement>(m_addr.get_arg(0).get_str(),
|
||||
m_value.as_expr(), m_my_idx);
|
||||
}
|
||||
|
||||
IR2_RegOffset ro;
|
||||
|
@ -120,22 +118,9 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
|||
(input_type.typespec() == TypeSpec("object") ||
|
||||
input_type.typespec() == TypeSpec("pair"))) {
|
||||
if (ro.offset == 2) {
|
||||
auto base = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, SimpleAtom::make_var(ro.var).as_expr(), m_my_idx);
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, m_value.as_expr(), m_my_idx);
|
||||
auto addr = pool.alloc_single_element_form<GenericElement>(
|
||||
nullptr, GenericOperator::make_fixed(FixedOperatorKind::CDR), base);
|
||||
auto fr = pool.alloc_element<SetFormFormElement>(addr, val);
|
||||
return fr;
|
||||
return pool.alloc_element<StoreInPairElement>(false, ro.var, m_value.as_expr(), m_my_idx);
|
||||
} else if (ro.offset == -2) {
|
||||
auto base = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, SimpleAtom::make_var(ro.var).as_expr(), m_my_idx);
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, m_value.as_expr(), m_my_idx);
|
||||
auto addr = pool.alloc_single_element_form<GenericElement>(
|
||||
nullptr, GenericOperator::make_fixed(FixedOperatorKind::CAR), base);
|
||||
return pool.alloc_element<SetFormFormElement>(addr, val);
|
||||
return pool.alloc_element<StoreInPairElement>(true, ro.var, m_value.as_expr(), m_my_idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,14 +145,14 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
|||
|
||||
// we pass along the register offset because code generation seems to be a bit
|
||||
// different in different cases.
|
||||
auto source = pool.alloc_single_element_form<ArrayFieldAccess>(
|
||||
nullptr, ro.var, tokens, input_type.get_multiplier(), ro.offset);
|
||||
auto source = pool.alloc_element<ArrayFieldAccess>(
|
||||
ro.var, tokens, input_type.get_multiplier(), ro.offset);
|
||||
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, m_value.as_expr(), m_my_idx);
|
||||
// auto val = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
// nullptr, m_value.as_expr(), m_my_idx);
|
||||
|
||||
assert(!rd.addr_of);
|
||||
return pool.alloc_element<SetFormFormElement>(source, val);
|
||||
return pool.alloc_element<StoreArrayAccess>(source, m_value.as_expr(), m_my_idx, ro.var);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,8 +168,6 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
|||
auto rd = env.dts->ts.reverse_field_lookup(rd_in);
|
||||
|
||||
if (rd.success) {
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, m_value.as_expr(), m_my_idx);
|
||||
auto source = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, SimpleAtom::make_var(ro.var).as_expr(), m_my_idx);
|
||||
std::vector<DerefToken> tokens;
|
||||
|
@ -192,13 +175,13 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
|||
tokens.push_back(to_token(x));
|
||||
}
|
||||
assert(!rd.addr_of);
|
||||
auto addr =
|
||||
pool.alloc_single_element_form<DerefElement>(nullptr, source, rd.addr_of, tokens);
|
||||
return pool.alloc_element<SetFormFormElement>(addr, val);
|
||||
auto addr = pool.alloc_element<DerefElement>(source, rd.addr_of, tokens);
|
||||
return pool.alloc_element<StorePlainDeref>(addr, m_value.as_expr(), m_my_idx, ro.var,
|
||||
std::nullopt);
|
||||
}
|
||||
|
||||
if (input_type.typespec() == TypeSpec("pointer") && ro.offset == 0) {
|
||||
std::string cast_type;
|
||||
if (input_type.typespec() == TypeSpec("pointer") && ro.offset == 0) {
|
||||
switch (m_size) {
|
||||
case 1:
|
||||
cast_type = "int8";
|
||||
|
@ -220,11 +203,10 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
|||
nullptr, SimpleAtom::make_var(ro.var).as_expr(), m_my_idx);
|
||||
auto cast_source = pool.alloc_single_element_form<CastElement>(
|
||||
nullptr, TypeSpec("pointer", {TypeSpec(cast_type)}), source);
|
||||
auto deref = pool.alloc_single_element_form<DerefElement>(nullptr, cast_source, false,
|
||||
std::vector<DerefToken>());
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(
|
||||
nullptr, m_value.as_expr(), m_my_idx);
|
||||
return pool.alloc_element<SetFormFormElement>(deref, val);
|
||||
auto deref =
|
||||
pool.alloc_element<DerefElement>(cast_source, false, std::vector<DerefToken>());
|
||||
return pool.alloc_element<StorePlainDeref>(deref, m_value.as_expr(), m_my_idx, ro.var,
|
||||
TypeSpec("pointer", {TypeSpec(cast_type)}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -319,6 +319,50 @@ bool SetVarElement::active() const {
|
|||
}
|
||||
}
|
||||
|
||||
StoreInSymbolElement::StoreInSymbolElement(std::string sym_name, SimpleExpression value, int my_idx)
|
||||
: m_sym_name(std::move(sym_name)), m_value(std::move(value)), m_my_idx(my_idx) {}
|
||||
|
||||
goos::Object StoreInSymbolElement::to_form_internal(const Env& env) const {
|
||||
return pretty_print::build_list("set!", m_sym_name, m_value.to_form(env.file->labels, env));
|
||||
}
|
||||
|
||||
void StoreInSymbolElement::apply(const std::function<void(FormElement*)>& f) {
|
||||
f(this);
|
||||
}
|
||||
|
||||
void StoreInSymbolElement::apply_form(const std::function<void(Form*)>&) {}
|
||||
|
||||
void StoreInSymbolElement::collect_vars(VariableSet& vars) const {
|
||||
m_value.collect_vars(vars);
|
||||
}
|
||||
|
||||
void StoreInSymbolElement::get_modified_regs(RegSet&) const {}
|
||||
|
||||
StoreInPairElement::StoreInPairElement(bool is_car,
|
||||
Variable pair,
|
||||
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*)>&) {}
|
||||
|
||||
void StoreInPairElement::collect_vars(VariableSet& vars) const {
|
||||
m_value.collect_vars(vars);
|
||||
vars.insert(m_pair);
|
||||
}
|
||||
|
||||
void StoreInPairElement::get_modified_regs(RegSet&) const {}
|
||||
|
||||
/////////////////////////////
|
||||
// SetFormFormElement
|
||||
/////////////////////////////
|
||||
|
@ -335,6 +379,7 @@ goos::Object SetFormFormElement::to_form_internal(const Env& env) const {
|
|||
}
|
||||
|
||||
void SetFormFormElement::apply(const std::function<void(FormElement*)>& f) {
|
||||
f(this);
|
||||
m_src->apply(f);
|
||||
m_dst->apply(f);
|
||||
}
|
||||
|
@ -1598,4 +1643,69 @@ void ConstantTokenElement::apply_form(const std::function<void(Form*)>&) {}
|
|||
void ConstantTokenElement::collect_vars(VariableSet&) const {}
|
||||
void ConstantTokenElement::get_modified_regs(RegSet&) const {}
|
||||
|
||||
StorePlainDeref::StorePlainDeref(DerefElement* dst,
|
||||
SimpleExpression expr,
|
||||
int my_idx,
|
||||
Variable base_var,
|
||||
std::optional<TypeSpec> cast_type)
|
||||
: m_dst(dst),
|
||||
m_expr(std::move(expr)),
|
||||
m_my_idx(my_idx),
|
||||
m_base_var(std::move(base_var)),
|
||||
m_cast_type(cast_type) {}
|
||||
goos::Object StorePlainDeref::to_form_internal(const Env& env) const {
|
||||
if (!m_cast_type.has_value()) {
|
||||
return pretty_print::build_list("set!", m_dst->to_form(env),
|
||||
m_expr.to_form(env.file->labels, env));
|
||||
} else {
|
||||
return pretty_print::build_list(
|
||||
"set!", pretty_print::build_list("the-as", m_cast_type->print(), m_dst->to_form(env)),
|
||||
m_expr.to_form(env.file->labels, env));
|
||||
}
|
||||
}
|
||||
void StorePlainDeref::apply(const std::function<void(FormElement*)>& f) {
|
||||
f(this);
|
||||
m_dst->apply(f);
|
||||
}
|
||||
|
||||
void StorePlainDeref::apply_form(const std::function<void(Form*)>&) {}
|
||||
|
||||
void StorePlainDeref::collect_vars(VariableSet& vars) const {
|
||||
m_expr.collect_vars(vars);
|
||||
m_dst->collect_vars(vars);
|
||||
}
|
||||
|
||||
void StorePlainDeref::get_modified_regs(RegSet& regs) const {
|
||||
m_dst->get_modified_regs(regs);
|
||||
}
|
||||
|
||||
StoreArrayAccess::StoreArrayAccess(ArrayFieldAccess* dst,
|
||||
SimpleExpression expr,
|
||||
int my_idx,
|
||||
Variable array_src)
|
||||
: m_dst(dst), m_expr(expr), m_my_idx(my_idx), m_base_var(array_src) {}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void StoreArrayAccess::collect_vars(VariableSet& vars) const {
|
||||
m_expr.collect_vars(vars);
|
||||
m_dst->collect_vars(vars);
|
||||
}
|
||||
|
||||
void StoreArrayAccess::get_modified_regs(RegSet& regs) const {
|
||||
m_dst->get_modified_regs(regs);
|
||||
}
|
||||
|
||||
} // namespace decompiler
|
||||
|
|
|
@ -43,9 +43,16 @@ class FormElement {
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
bool is_popped() const { return m_popped; }
|
||||
|
||||
void mark_popped() {
|
||||
assert(!m_popped);
|
||||
m_popped = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class Form;
|
||||
bool m_popped = false;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -61,8 +68,6 @@ class SimpleExpressionElement : public FormElement {
|
|||
void apply_form(const std::function<void(Form*)>& f) override;
|
||||
bool is_sequence_point() const override;
|
||||
void collect_vars(VariableSet& vars) const override;
|
||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||
// void push_to_stack(const Env& env, FormStack& stack) override;
|
||||
void update_from_stack(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
|
@ -219,13 +224,11 @@ class SimpleAtomElement : public FormElement {
|
|||
void collect_vars(VariableSet& vars) const override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
const SimpleAtom& atom() const { return m_atom; }
|
||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||
void update_from_stack(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) override;
|
||||
// void push_to_stack(const Env& env, FormStack& stack) override;
|
||||
|
||||
private:
|
||||
SimpleAtom m_atom;
|
||||
|
@ -246,11 +249,6 @@ class SetVarElement : public FormElement {
|
|||
bool is_sequence_point() const override;
|
||||
void collect_vars(VariableSet& vars) const override;
|
||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||
void update_from_stack(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
bool active() const override;
|
||||
|
||||
|
@ -276,6 +274,39 @@ class SetVarElement : public FormElement {
|
|||
SetVarInfo m_var_info;
|
||||
};
|
||||
|
||||
class StoreInSymbolElement : public FormElement {
|
||||
public:
|
||||
StoreInSymbolElement(std::string sym_name, SimpleExpression value, int my_idx);
|
||||
goos::Object to_form_internal(const Env& env) const override;
|
||||
void apply(const std::function<void(FormElement*)>& f) override;
|
||||
void apply_form(const std::function<void(Form*)>& f) override;
|
||||
void collect_vars(VariableSet& vars) const override;
|
||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
|
||||
private:
|
||||
std::string m_sym_name;
|
||||
SimpleExpression m_value;
|
||||
int m_my_idx = -1;
|
||||
};
|
||||
|
||||
class StoreInPairElement : public FormElement {
|
||||
public:
|
||||
StoreInPairElement(bool is_car, Variable pair, SimpleExpression value, int my_idx);
|
||||
goos::Object to_form_internal(const Env& env) const override;
|
||||
void apply(const std::function<void(FormElement*)>& f) override;
|
||||
void apply_form(const std::function<void(Form*)>& f) override;
|
||||
void collect_vars(VariableSet& vars) const override;
|
||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
|
||||
private:
|
||||
bool m_is_car = false;
|
||||
Variable m_pair;
|
||||
SimpleExpression m_value;
|
||||
int m_my_idx = -1;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Like SetVar, but sets a form to another form.
|
||||
* This is intended to be used with stores.
|
||||
|
@ -298,6 +329,7 @@ class SetFormFormElement : public FormElement {
|
|||
Form* dst() { return m_dst; }
|
||||
|
||||
private:
|
||||
int m_real_push_count = 0;
|
||||
Form* m_dst = nullptr;
|
||||
Form* m_src = nullptr;
|
||||
};
|
||||
|
@ -341,7 +373,8 @@ class AsmOpElement : public FormElement {
|
|||
|
||||
/*!
|
||||
* A "condition" like (< a b). This can be used as a boolean value directly: (set! a (< b c))
|
||||
* or it can be used as a branch condition: (if (< a b)).
|
||||
* or it can be used as a branch condition: (if (< a b)). As a result, it implements both push
|
||||
* and update.
|
||||
*
|
||||
* In the first case, it can be either a conditional move or actually branching. GOAL seems to use
|
||||
* the branching when sometimes it could have used the conditional move, and for now, we don't
|
||||
|
@ -892,10 +925,13 @@ class DerefElement : public FormElement {
|
|||
bool allow_side_effects) override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
|
||||
void inline_nested();
|
||||
|
||||
bool is_addr_of() const { return m_is_addr_of; }
|
||||
const Form* base() const { return m_base; }
|
||||
Form* base() { return m_base; }
|
||||
const std::vector<DerefToken>& tokens() const { return m_tokens; }
|
||||
void set_base(Form* new_base) { m_base = new_base; }
|
||||
|
||||
private:
|
||||
Form* m_base = nullptr;
|
||||
|
@ -938,6 +974,12 @@ class ArrayFieldAccess : public FormElement {
|
|||
bool allow_side_effects) override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
|
||||
void update_with_val(Form* new_val,
|
||||
const Env& env,
|
||||
FormPool& pool,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
|
||||
private:
|
||||
Variable m_source;
|
||||
std::vector<DerefToken> m_deref_tokens;
|
||||
|
@ -1001,6 +1043,46 @@ class ConstantTokenElement : public FormElement {
|
|||
std::string m_value;
|
||||
};
|
||||
|
||||
class StorePlainDeref : public FormElement {
|
||||
public:
|
||||
StorePlainDeref(DerefElement* dst,
|
||||
SimpleExpression expr,
|
||||
int my_idx,
|
||||
Variable base_var,
|
||||
std::optional<TypeSpec> cast_type);
|
||||
|
||||
goos::Object to_form_internal(const Env& env) const override;
|
||||
void apply(const std::function<void(FormElement*)>& f) override;
|
||||
void apply_form(const std::function<void(Form*)>& f) override;
|
||||
void collect_vars(VariableSet& vars) const override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||
|
||||
private:
|
||||
DerefElement* m_dst = nullptr;
|
||||
SimpleExpression m_expr;
|
||||
int m_my_idx = -1;
|
||||
Variable m_base_var;
|
||||
std::optional<TypeSpec> m_cast_type;
|
||||
};
|
||||
|
||||
class StoreArrayAccess : public FormElement {
|
||||
public:
|
||||
StoreArrayAccess(ArrayFieldAccess* dst, SimpleExpression expr, int my_idx, Variable array_src);
|
||||
goos::Object to_form_internal(const Env& env) const override;
|
||||
void apply(const std::function<void(FormElement*)>& f) override;
|
||||
void apply_form(const std::function<void(Form*)>& f) override;
|
||||
void collect_vars(VariableSet& vars) const override;
|
||||
void get_modified_regs(RegSet& regs) const override;
|
||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||
|
||||
private:
|
||||
ArrayFieldAccess* m_dst = nullptr;
|
||||
SimpleExpression m_expr;
|
||||
int m_my_idx = -1;
|
||||
Variable m_base_var;
|
||||
};
|
||||
|
||||
/*!
|
||||
* A Form is a wrapper around one or more FormElements.
|
||||
* This is done for two reasons:
|
||||
|
@ -1073,6 +1155,14 @@ class Form {
|
|||
bool has_side_effects();
|
||||
void get_modified_regs(RegSet& regs) const;
|
||||
|
||||
bool is_popped() const { return m_elements.at(0)->is_popped(); }
|
||||
|
||||
void mark_popped() {
|
||||
for (auto x : m_elements) {
|
||||
x->mark_popped();
|
||||
}
|
||||
}
|
||||
|
||||
FormElement* parent_element = nullptr;
|
||||
|
||||
private:
|
||||
|
|
|
@ -233,10 +233,15 @@ void Form::update_children_from_stack(const Env& env,
|
|||
for (size_t i = 0; i < m_elements.size(); i++) {
|
||||
if (i == 0) {
|
||||
// only bother doing the first one.
|
||||
if (!m_elements[i]->is_popped()) {
|
||||
m_elements[i]->update_from_stack(env, pool, stack, &new_elts, allow_side_effects);
|
||||
} else {
|
||||
new_elts.push_back(m_elements[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
new_elts.push_back(m_elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& x : new_elts) {
|
||||
|
@ -286,6 +291,7 @@ void LoadSourceElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
m_addr->update_children_from_stack(env, pool, stack, allow_side_effects);
|
||||
result->push_back(this);
|
||||
}
|
||||
|
@ -356,6 +362,8 @@ void SimpleExpressionElement::update_from_stack_fpr_to_gpr(const Env& env,
|
|||
// set ourself to identity.
|
||||
m_expr = src.as_expr();
|
||||
// then go again.
|
||||
assert(m_popped);
|
||||
m_popped = false;
|
||||
update_from_stack(env, pool, stack, result, allow_side_effects);
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
|
@ -756,6 +764,7 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
switch (m_expr.kind()) {
|
||||
case SimpleExpression::Kind::IDENTITY:
|
||||
update_from_stack_identity(env, pool, stack, result, allow_side_effects);
|
||||
|
@ -883,6 +892,7 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
|
|||
///////////////////
|
||||
|
||||
void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
for (auto x : m_src->elts()) {
|
||||
assert(x->parent_form == m_src);
|
||||
}
|
||||
|
@ -894,6 +904,7 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
|
|||
}
|
||||
|
||||
m_src->update_children_from_stack(env, pool, stack, true);
|
||||
|
||||
for (auto x : m_src->elts()) {
|
||||
assert(x->parent_form == m_src);
|
||||
}
|
||||
|
@ -926,23 +937,110 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
|
|||
}
|
||||
}
|
||||
|
||||
void SetVarElement::update_from_stack(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
m_src->update_children_from_stack(env, pool, stack, allow_side_effects);
|
||||
for (auto x : m_src->elts()) {
|
||||
assert(x->parent_form == m_src);
|
||||
}
|
||||
result->push_back(this);
|
||||
void SetFormFormElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
// todo - is the order here right?
|
||||
assert(m_popped);
|
||||
assert(m_real_push_count == 0);
|
||||
m_real_push_count++;
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
// todo - is the order here right?
|
||||
m_dst->update_children_from_stack(env, pool, stack, false);
|
||||
m_src->update_children_from_stack(env, pool, stack, false);
|
||||
stack.push_form_element(this, true);
|
||||
void StoreInSymbolElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
auto sym = pool.alloc_single_element_form<ConstantTokenElement>(nullptr, m_sym_name);
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_value, m_my_idx);
|
||||
val->update_children_from_stack(env, pool, stack, true);
|
||||
|
||||
auto elt = pool.alloc_element<SetFormFormElement>(sym, val);
|
||||
elt->mark_popped();
|
||||
stack.push_form_element(elt, true);
|
||||
}
|
||||
|
||||
void StoreInPairElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
auto op = m_is_car ? FixedOperatorKind::CAR : FixedOperatorKind::CDR;
|
||||
if (m_value.is_var()) {
|
||||
auto vars = std::vector<Variable>({m_value.var(), m_pair});
|
||||
auto popped = pop_to_forms(vars, env, pool, stack, true);
|
||||
auto addr = pool.alloc_single_element_form<GenericElement>(
|
||||
nullptr, GenericOperator::make_fixed(op), popped.at(1));
|
||||
addr->mark_popped();
|
||||
auto fr = pool.alloc_element<SetFormFormElement>(addr, popped.at(0));
|
||||
fr->mark_popped();
|
||||
stack.push_form_element(fr, true);
|
||||
} else {
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_value, m_my_idx);
|
||||
val->mark_popped();
|
||||
auto addr = pool.alloc_single_element_form<GenericElement>(
|
||||
nullptr, GenericOperator::make_fixed(op),
|
||||
pop_to_forms({m_pair}, env, pool, stack, true).at(0));
|
||||
addr->mark_popped();
|
||||
auto fr = pool.alloc_element<SetFormFormElement>(addr, val);
|
||||
fr->mark_popped();
|
||||
stack.push_form_element(fr, true);
|
||||
}
|
||||
}
|
||||
|
||||
void StorePlainDeref::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
if (m_expr.is_var()) {
|
||||
auto vars = std::vector<Variable>({m_expr.var(), m_base_var});
|
||||
auto popped = pop_to_forms(vars, env, pool, stack, true);
|
||||
if (m_cast_type.has_value()) {
|
||||
m_dst->set_base(
|
||||
pool.alloc_single_element_form<CastElement>(nullptr, *m_cast_type, popped.at(1)));
|
||||
} else {
|
||||
m_dst->set_base(popped.at(1));
|
||||
}
|
||||
|
||||
m_dst->mark_popped();
|
||||
m_dst->inline_nested();
|
||||
auto fr = pool.alloc_element<SetFormFormElement>(pool.alloc_single_form(nullptr, m_dst),
|
||||
popped.at(0));
|
||||
fr->mark_popped();
|
||||
stack.push_form_element(fr, true);
|
||||
} else {
|
||||
auto vars = std::vector<Variable>({m_base_var});
|
||||
auto popped = pop_to_forms(vars, env, pool, stack, true);
|
||||
if (m_cast_type.has_value()) {
|
||||
m_dst->set_base(
|
||||
pool.alloc_single_element_form<CastElement>(nullptr, *m_cast_type, popped.at(1)));
|
||||
} else {
|
||||
m_dst->set_base(popped.at(0));
|
||||
}
|
||||
m_dst->mark_popped();
|
||||
m_dst->inline_nested();
|
||||
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_expr, m_my_idx);
|
||||
val->mark_popped();
|
||||
auto fr = pool.alloc_element<SetFormFormElement>(pool.alloc_single_form(nullptr, m_dst), val);
|
||||
fr->mark_popped();
|
||||
stack.push_form_element(fr, true);
|
||||
}
|
||||
}
|
||||
|
||||
void StoreArrayAccess::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
Form* expr_form = nullptr;
|
||||
Form* array_form = nullptr;
|
||||
if (m_expr.is_var()) {
|
||||
auto vars = std::vector<Variable>({m_expr.var(), m_base_var});
|
||||
auto popped = pop_to_forms(vars, env, pool, stack, true);
|
||||
m_dst->mark_popped();
|
||||
expr_form = popped.at(0);
|
||||
array_form = popped.at(1);
|
||||
} else {
|
||||
auto vars = std::vector<Variable>({m_base_var});
|
||||
auto popped = pop_to_forms(vars, env, pool, stack, true);
|
||||
m_dst->mark_popped();
|
||||
expr_form = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_expr, m_my_idx);
|
||||
array_form = popped.at(0);
|
||||
}
|
||||
|
||||
std::vector<FormElement*> forms_out;
|
||||
m_dst->update_with_val(array_form, env, pool, &forms_out, true);
|
||||
auto form_out = pool.alloc_sequence_form(nullptr, forms_out);
|
||||
|
||||
auto fr = pool.alloc_element<SetFormFormElement>(form_out, expr_form);
|
||||
fr->mark_popped();
|
||||
stack.push_form_element(fr, true);
|
||||
}
|
||||
|
||||
///////////////////
|
||||
|
@ -954,6 +1052,7 @@ void AshElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
auto forms = pop_to_forms({value, shift_amount}, env, pool, stack, allow_side_effects, consumed);
|
||||
auto new_form = pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::ARITH_SHIFT), forms.at(0), forms.at(1));
|
||||
|
@ -969,6 +1068,7 @@ void AbsElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
auto forms = pop_to_forms({source}, env, pool, stack, allow_side_effects, consumed);
|
||||
auto new_form = pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::ABS), forms.at(0));
|
||||
|
@ -984,6 +1084,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
std::vector<Form*> args;
|
||||
auto nargs = m_op->arg_vars().size();
|
||||
args.resize(nargs, nullptr);
|
||||
|
@ -1272,17 +1373,12 @@ void DerefElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
// todo - update var tokens from stack?
|
||||
m_base->update_children_from_stack(env, pool, stack, allow_side_effects);
|
||||
|
||||
// merge nested ->'s
|
||||
auto as_deref = dynamic_cast<DerefElement*>(m_base->try_as_single_element());
|
||||
if (as_deref) {
|
||||
if (!m_is_addr_of && !as_deref->is_addr_of()) {
|
||||
m_tokens.insert(m_tokens.begin(), as_deref->tokens().begin(), as_deref->tokens().end());
|
||||
m_base = as_deref->m_base;
|
||||
}
|
||||
}
|
||||
inline_nested();
|
||||
|
||||
if (m_tokens.size() >= 3) {
|
||||
auto& method_name = m_tokens.at(m_tokens.size() - 1);
|
||||
|
@ -1332,11 +1428,22 @@ void DerefElement::update_from_stack(const Env& env,
|
|||
}
|
||||
}
|
||||
|
||||
void DerefElement::inline_nested() {
|
||||
auto as_deref = dynamic_cast<DerefElement*>(m_base->try_as_single_element());
|
||||
if (as_deref) {
|
||||
if (!m_is_addr_of && !as_deref->is_addr_of()) {
|
||||
m_tokens.insert(m_tokens.begin(), as_deref->tokens().begin(), as_deref->tokens().end());
|
||||
m_base = as_deref->m_base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// UntilElement
|
||||
///////////////////
|
||||
|
||||
void UntilElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
for (auto form : {condition, body}) {
|
||||
FormStack temp_stack(false);
|
||||
for (auto& entry : form->elts()) {
|
||||
|
@ -1353,6 +1460,7 @@ void UntilElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stac
|
|||
}
|
||||
|
||||
void WhileElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
bool first = true;
|
||||
for (auto form : {body, condition}) {
|
||||
FormStack temp_stack(first && stack.is_root());
|
||||
|
@ -1373,12 +1481,25 @@ void WhileElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stac
|
|||
// CondNoElseElement
|
||||
///////////////////
|
||||
void CondNoElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
if (already_rewritten) {
|
||||
stack.push_form_element(this, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// the first condition is special
|
||||
auto first_condition = entries.front().condition;
|
||||
// lets evaluate in on the parent stack...
|
||||
for (auto x : first_condition->elts()) {
|
||||
x->push_to_stack(env, pool, stack);
|
||||
}
|
||||
|
||||
for (auto& entry : entries) {
|
||||
for (auto form : {entry.condition, entry.body}) {
|
||||
if (form == first_condition) {
|
||||
form->clear();
|
||||
form->push_back(stack.pop_back(pool));
|
||||
} else {
|
||||
FormStack temp_stack(false);
|
||||
for (auto& elt : form->elts()) {
|
||||
elt->push_to_stack(env, pool, temp_stack);
|
||||
|
@ -1397,16 +1518,6 @@ void CondNoElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// raise expression.
|
||||
auto top_condition = entries.front().condition;
|
||||
if (!top_condition->is_single_element()) {
|
||||
auto real_condition = top_condition->back();
|
||||
top_condition->pop_back();
|
||||
for (auto x : top_condition->elts()) {
|
||||
x->push_to_stack(env, pool, stack);
|
||||
}
|
||||
top_condition->elts() = {real_condition};
|
||||
}
|
||||
|
||||
if (used_as_value) {
|
||||
|
@ -1418,6 +1529,7 @@ void CondNoElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
|
|||
}
|
||||
|
||||
void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
if (already_rewritten) {
|
||||
stack.push_form_element(this, true);
|
||||
return;
|
||||
|
@ -1426,9 +1538,20 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
|||
std::optional<Variable> last_var;
|
||||
bool rewrite_as_set = true;
|
||||
|
||||
// the first condition is special
|
||||
auto first_condition = entries.front().condition;
|
||||
// lets evaluate in on the parent stack...
|
||||
for (auto x : first_condition->elts()) {
|
||||
x->push_to_stack(env, pool, stack);
|
||||
}
|
||||
|
||||
// process conditions and bodies
|
||||
for (auto& entry : entries) {
|
||||
for (auto form : {entry.condition, entry.body}) {
|
||||
if (form == first_condition) {
|
||||
form->clear();
|
||||
form->push_back(stack.pop_back(pool));
|
||||
} else {
|
||||
FormStack temp_stack(false);
|
||||
for (auto& elt : form->elts()) {
|
||||
elt->push_to_stack(env, pool, temp_stack);
|
||||
|
@ -1443,6 +1566,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process else.
|
||||
FormStack temp_stack(false);
|
||||
|
@ -1500,17 +1624,6 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
|||
rewrite_to_get_var(else_ir->elts(), pool, *last_var);
|
||||
}
|
||||
|
||||
// raise expression.
|
||||
auto top_condition = entries.front().condition;
|
||||
if (!top_condition->is_single_element()) {
|
||||
auto real_condition = top_condition->back();
|
||||
top_condition->pop_back();
|
||||
for (auto x : top_condition->elts()) {
|
||||
x->push_to_stack(env, pool, stack);
|
||||
}
|
||||
top_condition->elts() = {real_condition};
|
||||
}
|
||||
|
||||
if (rewrite_as_set) {
|
||||
if (set_unused) {
|
||||
stack.push_form_element(this, true);
|
||||
|
@ -1528,6 +1641,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
|||
///////////////////
|
||||
|
||||
void ShortCircuitElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
if (!used_as_value.value_or(false)) {
|
||||
throw std::runtime_error(
|
||||
"ShortCircuitElement::push_to_stack not implemented for result not used case.");
|
||||
|
@ -1538,8 +1652,20 @@ void ShortCircuitElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
|||
stack.push_form_element(this, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// the first condition is special
|
||||
auto first_condition = entries.front().condition;
|
||||
// lets evaluate in on the parent stack...
|
||||
for (auto x : first_condition->elts()) {
|
||||
x->push_to_stack(env, pool, stack);
|
||||
}
|
||||
|
||||
for (int i = 0; i < int(entries.size()); i++) {
|
||||
auto& entry = entries.at(i);
|
||||
if (entry.condition == first_condition) {
|
||||
entry.condition->clear();
|
||||
entry.condition->push_back(stack.pop_back(pool));
|
||||
} else {
|
||||
FormStack temp_stack(false);
|
||||
for (auto& elt : entry.condition->elts()) {
|
||||
elt->push_to_stack(env, pool, temp_stack);
|
||||
|
@ -1557,15 +1683,6 @@ void ShortCircuitElement::push_to_stack(const Env& env, FormPool& pool, FormStac
|
|||
entry.condition->push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
auto top_condition = entries.front().condition;
|
||||
if (!top_condition->is_single_element()) {
|
||||
auto real_condition = top_condition->back();
|
||||
top_condition->pop_back();
|
||||
for (auto x : top_condition->elts()) {
|
||||
x->push_to_stack(env, pool, stack);
|
||||
}
|
||||
top_condition->elts() = {real_condition};
|
||||
}
|
||||
|
||||
assert(used_as_value.has_value());
|
||||
|
@ -1579,6 +1696,7 @@ void ShortCircuitElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool) {
|
||||
mark_popped();
|
||||
(void)stack;
|
||||
if (already_rewritten) {
|
||||
result->push_back(this);
|
||||
|
@ -1717,6 +1835,7 @@ FormElement* ConditionElement::make_generic(const Env&,
|
|||
}
|
||||
|
||||
void ConditionElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
std::vector<Form*> source_forms, popped_forms;
|
||||
std::vector<TypeSpec> source_types;
|
||||
std::vector<Variable> vars;
|
||||
|
@ -1766,6 +1885,7 @@ void ConditionElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
std::vector<Form*> source_forms, popped_forms;
|
||||
std::vector<TypeSpec> source_types;
|
||||
std::vector<Variable> vars;
|
||||
|
@ -1811,6 +1931,7 @@ void ConditionElement::update_from_stack(const Env& env,
|
|||
}
|
||||
|
||||
void ReturnElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
FormStack temp_stack(false);
|
||||
for (auto& elt : return_code->elts()) {
|
||||
elt->push_to_stack(env, pool, temp_stack);
|
||||
|
@ -1827,6 +1948,7 @@ void ReturnElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
|
|||
}
|
||||
|
||||
void AtomicOpElement::push_to_stack(const Env& env, FormPool&, FormStack& stack) {
|
||||
mark_popped();
|
||||
auto as_end = dynamic_cast<const FunctionEndOp*>(m_op);
|
||||
if (as_end) {
|
||||
// we don't want to push this to the stack (for now at least)
|
||||
|
@ -1851,6 +1973,7 @@ void AtomicOpElement::push_to_stack(const Env& env, FormPool&, FormStack& stack)
|
|||
}
|
||||
|
||||
void AsmOpElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
mark_popped();
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
|
@ -1859,11 +1982,11 @@ void GenericElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool) {
|
||||
// TODO improve.
|
||||
if (m_head.m_kind == GenericOperator::Kind::FUNCTION_EXPR) {
|
||||
m_head.m_function->update_children_from_stack(env, pool, stack, false);
|
||||
} else {
|
||||
m_elts.back()->update_children_from_stack(env, pool, stack, false);
|
||||
mark_popped();
|
||||
if (m_elts.size() == 1) {
|
||||
// a bit of a hack, but AtomicOpForm uses this for loading car/cdr
|
||||
// this is safe to do.
|
||||
m_elts.front()->update_children_from_stack(env, pool, stack, true);
|
||||
}
|
||||
result->push_back(this);
|
||||
}
|
||||
|
@ -1871,6 +1994,7 @@ void GenericElement::update_from_stack(const Env& env,
|
|||
void GenericElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
(void)env;
|
||||
(void)pool;
|
||||
mark_popped();
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
|
@ -1883,6 +2007,7 @@ void DynamicMethodAccess::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
auto new_val = stack.pop_reg(m_source, {}, env, allow_side_effects);
|
||||
auto reg0_matcher =
|
||||
Matcher::match_or({Matcher::any_reg(0), Matcher::cast("uint", Matcher::any_reg(0))});
|
||||
|
@ -1927,12 +2052,11 @@ bool is_power_of_two(int in, int* out) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
void ArrayFieldAccess::update_from_stack(const Env& env,
|
||||
void ArrayFieldAccess::update_with_val(Form* new_val,
|
||||
const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
auto new_val = stack.pop_reg(m_source, {}, env, allow_side_effects);
|
||||
bool) {
|
||||
int power_of_two = 0;
|
||||
|
||||
if (m_constant_offset == 0) {
|
||||
|
@ -2077,6 +2201,16 @@ void ArrayFieldAccess::update_from_stack(const Env& env,
|
|||
}
|
||||
}
|
||||
|
||||
void ArrayFieldAccess::update_from_stack(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
auto new_val = stack.pop_reg(m_source, {}, env, allow_side_effects);
|
||||
update_with_val(new_val, env, pool, result, allow_side_effects);
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// CastElement
|
||||
////////////////////////
|
||||
|
@ -2086,6 +2220,7 @@ void CastElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
m_source->update_children_from_stack(env, pool, stack, allow_side_effects);
|
||||
result->push_back(this);
|
||||
}
|
||||
|
@ -2099,6 +2234,7 @@ void TypeOfElement::update_from_stack(const Env& env,
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
mark_popped();
|
||||
value->update_children_from_stack(env, pool, stack, allow_side_effects);
|
||||
result->push_back(this);
|
||||
}
|
||||
|
@ -2108,6 +2244,7 @@ void TypeOfElement::update_from_stack(const Env& env,
|
|||
////////////////////////
|
||||
|
||||
void EmptyElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
mark_popped();
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
|
@ -2121,6 +2258,7 @@ bool is_symbol_true(const Form* form) {
|
|||
}
|
||||
|
||||
void ConditionalMoveFalseElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
mark_popped();
|
||||
// pop the value and the original
|
||||
auto popped = pop_to_forms({old_value, source}, env, pool, stack, true);
|
||||
if (!is_symbol_true(popped.at(0))) {
|
||||
|
@ -2136,27 +2274,21 @@ void ConditionalMoveFalseElement::push_to_stack(const Env& env, FormPool& pool,
|
|||
true);
|
||||
}
|
||||
|
||||
void SimpleAtomElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
void SimpleAtomElement::update_from_stack(const Env&,
|
||||
FormPool&,
|
||||
FormStack&,
|
||||
std::vector<FormElement*>* result,
|
||||
bool) {
|
||||
mark_popped();
|
||||
result->push_back(this);
|
||||
}
|
||||
|
||||
void SimpleExpressionElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
void StringConstantElement::update_from_stack(const Env&,
|
||||
FormPool&,
|
||||
FormStack&,
|
||||
std::vector<FormElement*>* result,
|
||||
bool) {
|
||||
mark_popped();
|
||||
result->push_back(this);
|
||||
}
|
||||
|
||||
|
@ -2165,6 +2297,7 @@ void GetMethodElement::update_from_stack(const Env&,
|
|||
FormStack&,
|
||||
std::vector<FormElement*>* result,
|
||||
bool) {
|
||||
mark_popped();
|
||||
result->push_back(this);
|
||||
}
|
||||
|
||||
|
@ -2173,6 +2306,7 @@ void CondNoElseElement::update_from_stack(const Env&,
|
|||
FormStack&,
|
||||
std::vector<FormElement*>* result,
|
||||
bool) {
|
||||
mark_popped();
|
||||
result->push_back(this);
|
||||
}
|
||||
|
||||
|
@ -2181,6 +2315,7 @@ void ConstantTokenElement::update_from_stack(const Env&,
|
|||
FormStack&,
|
||||
std::vector<FormElement*>* result,
|
||||
bool) {
|
||||
mark_popped();
|
||||
result->push_back(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -191,6 +191,21 @@ Form* FormStack::unsafe_peek(Register reg, const Env& env) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
FormElement* FormStack::pop_back(FormPool& pool) {
|
||||
auto& back = m_stack.back();
|
||||
assert(back.active);
|
||||
back.active = false;
|
||||
if (back.elt) {
|
||||
return back.elt;
|
||||
} else {
|
||||
assert(back.destination.has_value());
|
||||
auto elt = pool.alloc_element<SetVarElement>(*back.destination, back.source,
|
||||
back.sequence_point, back.set_info);
|
||||
back.source->parent_element = elt;
|
||||
return elt;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<FormElement*> FormStack::rewrite(FormPool& pool) {
|
||||
std::vector<FormElement*> result;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class FormStack {
|
|||
const Env& env,
|
||||
bool allow_side_effects,
|
||||
int begin_idx = -1);
|
||||
FormElement* pop_back(FormPool& pool);
|
||||
Form* unsafe_peek(Register reg, const Env& env);
|
||||
bool is_single_expression();
|
||||
std::vector<FormElement*> rewrite(FormPool& pool);
|
||||
|
|
|
@ -502,13 +502,13 @@
|
|||
(define-extern search-process-tree (function process-tree (function process-tree object) process))
|
||||
(define-extern execute-process-tree (function process-tree (function object object) kernel-context object))
|
||||
|
||||
(define-extern previous-brother (function process-tree process-tree))
|
||||
(define-extern previous-brother (function process-tree object))
|
||||
(define-extern change-parent (function process-tree process-tree process-tree))
|
||||
(define-extern change-brother (function process-tree process-tree process-tree))
|
||||
(define-extern change-brother (function process-tree process-tree object))
|
||||
(define-extern change-to-last-brother (function process-tree process-tree))
|
||||
|
||||
(define-extern *active-pool* process-tree)
|
||||
(define-extern kernel-dispatcher (function (function object)))
|
||||
(define-extern kernel-dispatcher (function object))
|
||||
(define-extern inspect-process-tree (function process-tree int int symbol process-tree))
|
||||
|
||||
(define-extern throw-dispatch (function catch-frame object none))
|
||||
|
@ -11014,53 +11014,54 @@
|
|||
:flag-assert #x900000028
|
||||
)
|
||||
|
||||
; ;; progress-h
|
||||
; (deftype progress (process)
|
||||
; ((~Tcurrent-debug-string int32 :offset-assert 112)
|
||||
; (~Tcurrent-debug-language int32 :offset-assert 116)
|
||||
; (~Tcurrent-debug-group int32 :offset-assert 120)
|
||||
; (~Tin-out-position int32 :offset-assert 124)
|
||||
; (~Tdisplay-state uint64 :offset-assert 128)
|
||||
; (~Tnext-display-state uint64 :offset-assert 136)
|
||||
; (~Toption-index int32 :offset-assert 144)
|
||||
; (~Tselected-option basic :offset-assert 148)
|
||||
; (~Tcompletion-percentage float :offset-assert 152)
|
||||
; (~Tready-to-run basic :offset-assert 156)
|
||||
; (~Tdisplay-level-index int32 :offset-assert 160)
|
||||
; (~Tnext-level-index int32 :offset-assert 164)
|
||||
; (~Ttask-index int32 :offset-assert 168)
|
||||
; (~Tin-transition basic :offset-assert 172)
|
||||
; (~Tlast-in-transition basic :offset-assert 176)
|
||||
; (~Tforce-transition basic :offset-assert 180)
|
||||
; (~Tstat-transition basic :offset-assert 184)
|
||||
; (~Tlevel-transition int32 :offset-assert 188)
|
||||
; (~Tlanguage-selection uint64 :offset-assert 192)
|
||||
; (~Tlanguage-direction basic :offset-assert 200)
|
||||
; (~Tlanguage-transition basic :offset-assert 204)
|
||||
; (~Tlanguage-x-offset int32 :offset-assert 208)
|
||||
; (~Tsides-x-scale float :offset-assert 212)
|
||||
; (~Tsides-y-scale float :offset-assert 216)
|
||||
; (~Tleft-x-offset int32 :offset-assert 220)
|
||||
; (~Tright-x-offset int32 :offset-assert 224)
|
||||
; (~Tbutton-scale float :offset-assert 228)
|
||||
; (~Tslot-scale float :offset-assert 232)
|
||||
; (~Tleft-side-x-scale float :offset-assert 236)
|
||||
; (~Tleft-side-y-scale float :offset-assert 240)
|
||||
; (~Tright-side-x-scale float :offset-assert 244)
|
||||
; (~Tright-side-y-scale float :offset-assert 248)
|
||||
; (~Tsmall-orb-y-offset int32 :offset-assert 252)
|
||||
; (~Tbig-orb-y-offset int32 :offset-assert 256)
|
||||
; (~Ttransition-offset int32 :offset-assert 260)
|
||||
; (~Ttransition-offset-invert int32 :offset-assert 264)
|
||||
; (~Ttransition-percentage float :offset-assert 268)
|
||||
; (~Ttransition-percentage-invert float :offset-assert 272)
|
||||
; (~Ttransition-speed float :offset-assert 276)
|
||||
; (~Ttotal-nb-of-power-cells int32 :offset-assert 280)
|
||||
; (~Ttotal-nb-of-orbs int32 :offset-assert 284)
|
||||
; (~Ttotal-nb-of-buzzers int32 :offset-assert 288)
|
||||
; (~Tcard-info mc-slot-info :offset-assert 292)
|
||||
; (~Tlast-option-index-change uint64 :offset-assert 296)
|
||||
; (~Tvideo-mode-timeout uint64 :offset-assert 304)
|
||||
;; progress-h
|
||||
(deftype progress (process)
|
||||
((~Tcurrent-debug-string int32 :offset-assert 112)
|
||||
(~Tcurrent-debug-language int32 :offset-assert 116)
|
||||
(~Tcurrent-debug-group int32 :offset-assert 120)
|
||||
(~Tin-out-position int32 :offset-assert 124)
|
||||
(~Tdisplay-state uint64 :offset-assert 128)
|
||||
(~Tnext-display-state uint64 :offset-assert 136)
|
||||
(~Toption-index int32 :offset-assert 144)
|
||||
(~Tselected-option basic :offset-assert 148)
|
||||
(~Tcompletion-percentage float :offset-assert 152)
|
||||
(~Tready-to-run basic :offset-assert 156)
|
||||
(~Tdisplay-level-index int32 :offset-assert 160)
|
||||
(~Tnext-level-index int32 :offset-assert 164)
|
||||
(~Ttask-index int32 :offset-assert 168)
|
||||
(~Tin-transition basic :offset-assert 172)
|
||||
(~Tlast-in-transition basic :offset-assert 176)
|
||||
(~Tforce-transition basic :offset-assert 180)
|
||||
(~Tstat-transition basic :offset-assert 184)
|
||||
(~Tlevel-transition int32 :offset-assert 188)
|
||||
(~Tlanguage-selection uint64 :offset-assert 192)
|
||||
(~Tlanguage-direction basic :offset-assert 200)
|
||||
(~Tlanguage-transition basic :offset-assert 204)
|
||||
(~Tlanguage-x-offset int32 :offset-assert 208)
|
||||
(~Tsides-x-scale float :offset-assert 212)
|
||||
(~Tsides-y-scale float :offset-assert 216)
|
||||
(~Tleft-x-offset int32 :offset-assert 220)
|
||||
(~Tright-x-offset int32 :offset-assert 224)
|
||||
(~Tbutton-scale float :offset-assert 228)
|
||||
(~Tslot-scale float :offset-assert 232)
|
||||
(~Tleft-side-x-scale float :offset-assert 236)
|
||||
(~Tleft-side-y-scale float :offset-assert 240)
|
||||
(~Tright-side-x-scale float :offset-assert 244)
|
||||
(~Tright-side-y-scale float :offset-assert 248)
|
||||
(~Tsmall-orb-y-offset int32 :offset-assert 252)
|
||||
(~Tbig-orb-y-offset int32 :offset-assert 256)
|
||||
(~Ttransition-offset int32 :offset-assert 260)
|
||||
(~Ttransition-offset-invert int32 :offset-assert 264)
|
||||
(~Ttransition-percentage float :offset-assert 268)
|
||||
(~Ttransition-percentage-invert float :offset-assert 272)
|
||||
(~Ttransition-speed float :offset-assert 276)
|
||||
(~Ttotal-nb-of-power-cells int32 :offset-assert 280)
|
||||
(~Ttotal-nb-of-orbs int32 :offset-assert 284)
|
||||
(~Ttotal-nb-of-buzzers int32 :offset-assert 288)
|
||||
(~Tcard-info mc-slot-info :offset-assert 292)
|
||||
(~Tlast-option-index-change uint64 :offset-assert 296)
|
||||
(~Tvideo-mode-timeout uint64 :offset-assert 304)
|
||||
(pad uint8 :offset 731)
|
||||
; (~Tdisplay-state-stack UNKNOWN 5 :offset-assert 312)
|
||||
; (~Toption-index-stack UNKNOWN 5 :offset-assert 352)
|
||||
; (~Tdisplay-state-pos int32 :offset-assert 372)
|
||||
|
@ -11070,64 +11071,59 @@
|
|||
; (~Tnb-of-particles int32 :offset-assert 408)
|
||||
; (~Tparticles UNKNOWN 40 :offset-assert 412)
|
||||
; (~Tparticle-state UNKNOWN 40 :offset-assert 572)
|
||||
; )
|
||||
; :method-count-assert 59
|
||||
; :size-assert #x2dc
|
||||
; :flag-assert #x3b027002dc
|
||||
; ;; inherited inspect of process
|
||||
; (:methods
|
||||
; (dummy-9 () none 9)
|
||||
; (dummy-10 () none 10)
|
||||
; (dummy-11 () none 11)
|
||||
; (dummy-12 () none 12)
|
||||
; (dummy-13 () none 13)
|
||||
; (dummy-14 () none 14)
|
||||
; (dummy-15 () none 15)
|
||||
; (dummy-16 () none 16)
|
||||
; (dummy-17 () none 17)
|
||||
; (dummy-18 () none 18)
|
||||
; (dummy-19 () none 19)
|
||||
; (dummy-20 () none 20)
|
||||
; (dummy-21 () none 21)
|
||||
; (dummy-22 () none 22)
|
||||
; (dummy-23 () none 23)
|
||||
; (dummy-24 () none 24)
|
||||
; (dummy-25 () none 25)
|
||||
; (dummy-26 () none 26)
|
||||
; (dummy-27 () none 27)
|
||||
; (dummy-28 () none 28)
|
||||
; (dummy-29 () none 29)
|
||||
; (dummy-30 () none 30)
|
||||
; (dummy-31 () none 31)
|
||||
; (dummy-32 () none 32)
|
||||
; (dummy-33 () none 33)
|
||||
; (dummy-34 () none 34)
|
||||
; (dummy-35 () none 35)
|
||||
; (dummy-36 () none 36)
|
||||
; (dummy-37 () none 37)
|
||||
; (dummy-38 () none 38)
|
||||
; (dummy-39 () none 39)
|
||||
; (dummy-40 () none 40)
|
||||
; (dummy-41 () none 41)
|
||||
; (dummy-42 () none 42)
|
||||
; (dummy-43 () none 43)
|
||||
; (dummy-44 () none 44)
|
||||
; (dummy-45 () none 45)
|
||||
; (dummy-46 () none 46)
|
||||
; (dummy-47 () none 47)
|
||||
; (dummy-48 () none 48)
|
||||
; (dummy-49 () none 49)
|
||||
; (dummy-50 () none 50)
|
||||
; (dummy-51 () none 51)
|
||||
; (dummy-52 () none 52)
|
||||
; (dummy-53 () none 53)
|
||||
; (dummy-54 () none 54)
|
||||
; (dummy-55 () none 55)
|
||||
; (dummy-56 () none 56)
|
||||
; (dummy-57 () none 57)
|
||||
; (dummy-58 () none 58)
|
||||
; )
|
||||
; )
|
||||
)
|
||||
:method-count-assert 59
|
||||
:size-assert #x2dc
|
||||
:flag-assert #x3b000002dc
|
||||
;; inherited inspect of process
|
||||
(:methods
|
||||
(dummy-14 () none 14)
|
||||
(dummy-15 () none 15)
|
||||
(dummy-16 () none 16)
|
||||
(dummy-17 () none 17)
|
||||
(dummy-18 () none 18)
|
||||
(dummy-19 () none 19)
|
||||
(dummy-20 () none 20)
|
||||
(dummy-21 () none 21)
|
||||
(dummy-22 () none 22)
|
||||
(dummy-23 () none 23)
|
||||
(dummy-24 () none 24)
|
||||
(dummy-25 () none 25)
|
||||
(dummy-26 () none 26)
|
||||
(dummy-27 () none 27)
|
||||
(dummy-28 () none 28)
|
||||
(dummy-29 () none 29)
|
||||
(dummy-30 () none 30)
|
||||
(dummy-31 () none 31)
|
||||
(dummy-32 () none 32)
|
||||
(dummy-33 () none 33)
|
||||
(dummy-34 () none 34)
|
||||
(dummy-35 () none 35)
|
||||
(dummy-36 () none 36)
|
||||
(dummy-37 () none 37)
|
||||
(dummy-38 () none 38)
|
||||
(dummy-39 () none 39)
|
||||
(dummy-40 () none 40)
|
||||
(dummy-41 () none 41)
|
||||
(dummy-42 () none 42)
|
||||
(dummy-43 () none 43)
|
||||
(dummy-44 () none 44)
|
||||
(dummy-45 () none 45)
|
||||
(dummy-46 () none 46)
|
||||
(dummy-47 () none 47)
|
||||
(dummy-48 () none 48)
|
||||
(dummy-49 () none 49)
|
||||
(dummy-50 () none 50)
|
||||
(dummy-51 () none 51)
|
||||
(dummy-52 () none 52)
|
||||
(dummy-53 () none 53)
|
||||
(dummy-54 () none 54)
|
||||
(dummy-55 () none 55)
|
||||
(dummy-56 () none 56)
|
||||
(dummy-57 () none 57)
|
||||
(dummy-58 () none 58)
|
||||
)
|
||||
)
|
||||
|
||||
;; rpc-h
|
||||
(deftype rpc-buffer (basic)
|
||||
|
@ -33078,7 +33074,7 @@
|
|||
;;(define-extern *hud-parts* object) ;; unknown type
|
||||
(define-extern game-option type)
|
||||
;;(define-extern progress object) ;; unknown type
|
||||
;;(define-extern *progress-process* object) ;; unknown type
|
||||
(define-extern *progress-process* process) ;; unknown type
|
||||
;;(define-extern count-info object) ;; unknown type
|
||||
(define-extern task-info-data type)
|
||||
(define-extern game-count-info type)
|
||||
|
@ -35375,13 +35371,13 @@
|
|||
(define-extern main-cheats function)
|
||||
;;(define-extern *progress-cheat* object) ;; unknown type
|
||||
(define-extern display-loop function)
|
||||
(define-extern letterbox function)
|
||||
(define-extern letterbox (function none))
|
||||
;;(define-extern *cheat-temp* object) ;; unknown type
|
||||
;;(define-extern *master-exit* object) ;; unknown type
|
||||
;;(define-extern *last-master-mode* object) ;; unknown type
|
||||
(define-extern off function)
|
||||
;;(define-extern *screen-filter* object) ;; unknown type
|
||||
(define-extern set-letterbox-frames function)
|
||||
(define-extern set-letterbox-frames (function int none))
|
||||
(define-extern entity-by-type function)
|
||||
;;(define-extern scf-get-timeout object) ;; unknown type
|
||||
(define-extern pause-allowed? function)
|
||||
|
@ -35767,7 +35763,7 @@
|
|||
;;(define-extern iron object) ;; unknown type
|
||||
;;(define-extern wood object) ;; unknown type
|
||||
;;(define-extern crate-type object) ;; unknown type
|
||||
;;(define-extern hud-arriving object) ;; unknown type
|
||||
(define-extern hud-arriving state) ;; unknown type
|
||||
;;(define-extern hud-leaving object) ;; unknown type
|
||||
;;(define-extern hud-hidden object) ;; unknown type
|
||||
;;(define-extern hud-in object) ;; unknown type
|
||||
|
|
|
@ -340,6 +340,11 @@
|
|||
"(method 0 state)":{
|
||||
"args":["allocation", "type-to-make", "name", "code", "trans", "enter", "exit", "event"],
|
||||
"vars":{"v0-0":"obj"}
|
||||
},
|
||||
|
||||
"previous-brother":{
|
||||
"args":["proc"],
|
||||
"vars":{"v1-0":"parent", "v1-2":"child"}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
- The types `cpu-thread` and `catch-frame` have a slightly different layout in OpenGOAL to back up x86-64 registers
|
||||
|
||||
## `gkernel`:
|
||||
- In progress
|
||||
- Many changes for x86-64/OpenGOAL
|
||||
- A few bugs in the game related to `process-tree` vs `(pointer process-tree)`.
|
||||
- `change-brother` is totally wrong, unused, and left out.
|
||||
|
||||
## `pskernel`: **Done**
|
||||
- Unimplemented in OpenGOAL. Seems to be debugging hooks into the PS2's kernel. Error strings indicate that there should have been a second related file included that actually contained the debugging handlers, but this file is not present.
|
||||
|
|
24
doc/emacs_config.el
Normal file
24
doc/emacs_config.el
Normal file
|
@ -0,0 +1,24 @@
|
|||
;; make gc files use lisp-mode
|
||||
(add-to-list 'auto-mode-alist '("\\.gc\\'" . lisp-mode))
|
||||
;; run setup-goal when we enter lisp mode
|
||||
(add-hook 'lisp-mode-hook 'setup-goal)
|
||||
|
||||
(defun setup-goal ()
|
||||
;; if we are in a gc file, change indent settings for GOAL
|
||||
(when (and (stringp buffer-file-name)
|
||||
(string-match "\\.gc\\'" buffer-file-name))
|
||||
(put 'with-pp 'common-lisp-indent-function 0)
|
||||
(put 'while 'common-lisp-indent-function 1)
|
||||
(put 'rlet 'common-lisp-indent-function 1)
|
||||
(put 'until 'common-lisp-indent-function 1)
|
||||
(put 'countdown 'common-lisp-indent-function 1)
|
||||
(put 'defun-debug 'common-lisp-indent-function 2)
|
||||
(put 'defenum 'common-lisp-indent-function 2)
|
||||
|
||||
;; indent for common lisp, this makes if's look nicer
|
||||
(custom-set-variables '(lisp-indent-function 'common-lisp-indent-function))
|
||||
(autoload 'common-lisp-indent-function "cl-indent" "Common Lisp indent.")
|
||||
;; use spaces, not tabs
|
||||
(setq-default indent-tabs-mode nil)
|
||||
)
|
||||
)
|
|
@ -113,21 +113,21 @@
|
|||
;; Thread and CPU Thread
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; A GOAL thread represents the execution of code in a process.
|
||||
; Each process has a "main thread", which is suspended and resumed.
|
||||
; A process may also execute various temporary threads which always run until completion.
|
||||
; A "temporary thread" cannot suspend and resume, but a "main thread" can.
|
||||
; The currently executing thread of a process is the "top-thread".
|
||||
;; A GOAL thread represents the execution of code in a process.
|
||||
;; Each process has a "main thread", which is suspended and resumed.
|
||||
;; A process may also execute various temporary threads which always run until completion.
|
||||
;; A "temporary thread" cannot suspend and resume, but a "main thread" can.
|
||||
;; The currently executing thread of a process is the "top-thread".
|
||||
|
||||
; Threads that suspend do so by saving their saved registers and their stack.
|
||||
; All threads run on a single large stack and have small "backup" stacks that are much smaller than the main stack.
|
||||
; as a result, suspending can fail if you are using more stack than the size of your backup stack.
|
||||
; This "backup stack" can be different sizes for different threads and makes the thread type dynamic.
|
||||
; The main thread is stored on the process heap, as they need the same lifetime as the process.
|
||||
; The temporary threads are stored on the stack. There can be only one temporary thread at a time.
|
||||
;; Threads that suspend do so by saving their saved registers and their stack.
|
||||
;; All threads run on a single large stack and have small "backup" stacks that are much smaller than the main stack.
|
||||
;; as a result, suspending can fail if you are using more stack than the size of your backup stack.
|
||||
;; This "backup stack" can be different sizes for different threads and makes the thread type dynamic.
|
||||
;; The main thread is stored on the process heap, as they need the same lifetime as the process.
|
||||
;; The temporary threads are stored on the stack. There can be only one temporary thread at a time.
|
||||
|
||||
; All threads are actually cpu-threads. It's not clear why there are two separate types.
|
||||
; Perhaps the thread was the public interface and cpu-thread is internal to the kernel?
|
||||
;; All threads are actually cpu-threads. It's not clear why there are two separate types.
|
||||
;; Perhaps the thread was the public interface and cpu-thread is internal to the kernel?
|
||||
|
||||
(defmethod delete thread ((obj thread))
|
||||
"Clean up a temporary thread after it is done being used.
|
||||
|
@ -1515,7 +1515,6 @@
|
|||
|
||||
(defun kill-by-type (type (pool process-tree))
|
||||
"Call deactivate on all processes with the given type"
|
||||
(break) ; this is sketchy.
|
||||
(set! *global-search-name* (the basic type))
|
||||
(let ((proc (the process-tree #f)))
|
||||
(while (set! proc (search-process-tree pool (lambda ((var process))
|
||||
|
@ -1537,7 +1536,6 @@
|
|||
|
||||
(defun kill-not-type (type (pool process-tree))
|
||||
"Call deactivate on all prcesses that don't match the given type"
|
||||
(break) ;; this function is weird.
|
||||
(set! *global-search-name* (the basic type))
|
||||
(let ((proc (the process-tree #f)))
|
||||
(while (set! proc (search-process-tree pool (lambda ((var process))
|
||||
|
@ -1693,8 +1691,7 @@
|
|||
((-> obj trans-hook)
|
||||
;; we have a trans hook defined. let's create a thread and run it. we can reuse the stack of the main-thread
|
||||
;; it is safe to do this because the main-thread is currently suspended or hasn't run yet.
|
||||
;; hack process -> global new todo
|
||||
(let ((trans (new 'global 'cpu-thread obj 'trans PROCESS_STACK_SAVE_SIZE (-> obj main-thread stack-top))))
|
||||
(let ((trans (new 'process 'cpu-thread obj 'trans PROCESS_STACK_SAVE_SIZE (-> obj main-thread stack-top))))
|
||||
;; call the function in the thread.
|
||||
(reset-and-call trans (-> obj trans-hook))
|
||||
;; remove the cpu-thread
|
||||
|
@ -1729,8 +1726,7 @@
|
|||
;; POST CODE
|
||||
(cond
|
||||
((-> obj post-hook)
|
||||
;; hack process -> global new todo
|
||||
(let ((post (new 'global 'cpu-thread obj 'post PROCESS_STACK_SAVE_SIZE *kernel-dram-stack*)))
|
||||
(let ((post (new 'process 'cpu-thread obj 'post PROCESS_STACK_SAVE_SIZE *kernel-dram-stack*)))
|
||||
(reset-and-call post (-> obj post-hook))
|
||||
(delete post)
|
||||
(when (eq? (-> obj status) 'dead)
|
||||
|
@ -1755,9 +1751,6 @@
|
|||
)
|
||||
*kernel-context*
|
||||
)
|
||||
|
||||
;; todo, remove this and replace it with the rest of the kernel dispatcher.
|
||||
(set! *listener-function* (the (function object) #f))
|
||||
)
|
||||
|
||||
(define-extern inspect-process-tree (function process-tree int int symbol process-tree))
|
||||
|
@ -1806,7 +1799,7 @@
|
|||
)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Stack Frame Stuff (TODO)
|
||||
;; Stack Frame Stuff
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The GOAL kernel supports dynamic throw and catch.
|
||||
|
@ -2038,7 +2031,29 @@
|
|||
;; Tree Stuff
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; todo previous-brother
|
||||
(defun previous-brother ((proc process-tree))
|
||||
"Get the process p where (-> p brother) is proc. Unused"
|
||||
(local-vars (parent (pointer process-tree))
|
||||
(child (pointer process-tree))
|
||||
)
|
||||
;; look up the tree to find our parent
|
||||
(set! parent (-> proc parent))
|
||||
(the-as process-tree
|
||||
(when parent
|
||||
;; make sure we aren't the only child.
|
||||
(set! child (-> parent 0 child))
|
||||
(if (= child proc) (return '#f))
|
||||
;; iterate, until we find the one.
|
||||
(while child
|
||||
(if (= (-> child 0 brother) proc) (return child))
|
||||
(set! child (-> child 0 brother))
|
||||
)
|
||||
;; nope, didn't find it. bad tree.
|
||||
'#f
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
(defun change-parent ((obj process-tree) (new-parent process-tree))
|
||||
"Make obj a child of new-parent"
|
||||
|
@ -2071,8 +2086,112 @@
|
|||
)
|
||||
)
|
||||
|
||||
;; todo change-brother
|
||||
;; todo change-to-last-brother
|
||||
(defun change-brother ((arg0 process-tree) (arg1 process-tree))
|
||||
"Unused, and wrong.
|
||||
It seems like this was written when processes store process-trees, not (pointer process-tree)."
|
||||
(local-vars
|
||||
(v1-4 (pointer process-tree))
|
||||
(a1-1 symbol)
|
||||
(a2-1 (pointer process-tree))
|
||||
(a3-1 (pointer process-tree))
|
||||
(t0-0 (pointer process-tree))
|
||||
(t1-0 (pointer process-tree))
|
||||
(t1-3 (pointer process-tree))
|
||||
(t1-4 (pointer process-tree))
|
||||
(t1-7 (pointer process-tree))
|
||||
(t1-8 (pointer process-tree))
|
||||
(t1-12 (pointer process-tree))
|
||||
(t1-13 (pointer process-tree))
|
||||
(t1-17 (pointer process-tree))
|
||||
)
|
||||
(when (and arg0 (!= (-> arg0 brother) arg1) (!= arg0 arg1))
|
||||
(set! a2-1 (-> arg0 parent))
|
||||
(when a2-1
|
||||
(set! t0-0 (-> a2-1 0 child))
|
||||
(set! a3-1 '#f)
|
||||
(set! v1-4 '#f)
|
||||
(set! t1-0 t0-0)
|
||||
(when (= (if t1-0 (-> t1-0 0 self)) arg0)
|
||||
(set! a3-1 a2-1)
|
||||
(set! t1-3 a3-1)
|
||||
)
|
||||
(set! t1-4 t0-0)
|
||||
(when (= (if t1-4 (-> t1-4 0 self)) arg1)
|
||||
(set! v1-4 a2-1)
|
||||
(set! t1-7 v1-4)
|
||||
)
|
||||
(while (and (-> t0-0 0 brother) (or (not a3-1) (not v1-4)))
|
||||
(set! t1-8 t0-0)
|
||||
(when (= (-> (if t1-8 (-> t1-8 0 self)) brother) arg1)
|
||||
(set! v1-4 t0-0)
|
||||
(set! t1-12 v1-4)
|
||||
)
|
||||
(set! t1-13 t0-0)
|
||||
(when (= (-> (if t1-13 (-> t1-13 0 self)) brother) arg0)
|
||||
(set! a3-1 t0-0)
|
||||
(set! t1-17 a3-1)
|
||||
)
|
||||
(set! t0-0 (-> t0-0 0 brother))
|
||||
)
|
||||
(if (or (not a3-1) (not v1-4))
|
||||
(return 0)
|
||||
(if (= a3-1 a2-1)
|
||||
(set! (-> a3-1 4) (the process-tree (-> arg0 brother))) ;; wrong
|
||||
(set! (-> a3-1 3) (the process-tree (-> arg0 brother))) ;; wrong
|
||||
)
|
||||
)
|
||||
(cond
|
||||
((= v1-4 a2-1)
|
||||
(set! (-> arg0 brother) (the (pointer process-tree) (-> v1-4 4))) ;; wrong
|
||||
(set! (-> v1-4 4) (the process-tree (-> arg0 ppointer))) ;; wrong
|
||||
)
|
||||
(else
|
||||
(set! (-> arg0 brother) (the (pointer process-tree) (-> v1-4 3)))
|
||||
(set! (-> v1-4 3) (the process-tree (-> arg0 ppointer)))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(the-as process-tree arg0)
|
||||
)
|
||||
|
||||
(defun change-to-last-brother ((arg0 process-tree))
|
||||
(local-vars
|
||||
(v1-4 (pointer process-tree))
|
||||
(v1-8 symbol)
|
||||
(a1-0 (pointer process-tree))
|
||||
(a1-5 symbol)
|
||||
(a1-9 symbol)
|
||||
)
|
||||
(when (and (-> arg0 brother) (-> arg0 parent))
|
||||
(set! a1-0 (-> arg0 parent))
|
||||
(set! v1-4 (-> a1-0 0 child))
|
||||
(cond
|
||||
((= (-> v1-4 0) arg0)
|
||||
(set! (-> a1-0 0 child) (-> arg0 brother)))
|
||||
(else
|
||||
(while (!= (-> v1-4 0 brother 0) arg0)
|
||||
(nop!)
|
||||
(nop!)
|
||||
(nop!)
|
||||
(nop!)
|
||||
(set! v1-4 (-> v1-4 0 brother))
|
||||
)
|
||||
(set! (-> v1-4 0 brother) (-> arg0 brother))
|
||||
)
|
||||
)
|
||||
(while (-> v1-4 0 brother)
|
||||
(nop!)
|
||||
(nop!)
|
||||
(nop!)
|
||||
(nop!)
|
||||
(set! v1-4 (-> v1-4 0 brother))
|
||||
)
|
||||
(set! (-> v1-4 0 brother) (-> arg0 ppointer))
|
||||
(set! (-> arg0 brother) '#f)
|
||||
)
|
||||
arg0
|
||||
)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -2106,8 +2225,7 @@
|
|||
(set! (-> obj connection-list next1) #f)
|
||||
(set! (-> obj connection-list prev1) #f)
|
||||
|
||||
;; todo global -> process
|
||||
(let ((thread (new 'global 'cpu-thread obj 'code PROCESS_STACK_SAVE_SIZE stack-top)))
|
||||
(let ((thread (new 'process 'cpu-thread obj 'code PROCESS_STACK_SAVE_SIZE stack-top)))
|
||||
(set! (-> obj main-thread) thread)
|
||||
)
|
||||
|
||||
|
@ -2244,12 +2362,10 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defmethod deactivate process-tree ((obj process-tree))
|
||||
;; todo
|
||||
(format 0 "CALL TO DEACTIVATE~%")
|
||||
(none)
|
||||
)
|
||||
|
||||
;; todo defstate
|
||||
;; The defstate macro isn't defined yet, so we do it manually.
|
||||
(define dead-state
|
||||
(new 'static 'state
|
||||
:name #f
|
||||
|
@ -2264,8 +2380,10 @@
|
|||
(set! (-> dead-state code) nothing)
|
||||
|
||||
|
||||
;; hack
|
||||
;; this is not yet defined.
|
||||
(define-extern entity-deactivate-handler (function process object none))
|
||||
(define entity-deactivate-handler (the (function process object none) nothing))
|
||||
|
||||
(define-extern process-disconnect (function object none))
|
||||
|
||||
(defmethod deactivate process ((obj process))
|
||||
|
@ -2372,8 +2490,7 @@
|
|||
(let ((obj (define *listener-process* (new 'global 'process 'listener 2048))))
|
||||
(set! (-> obj status) 'ready)
|
||||
(set! (-> obj pid) 1)
|
||||
;; allocation symbol is actually process, but it's ignored so this is ok for now.
|
||||
(set! (-> obj main-thread) (new 'global 'cpu-thread obj 'main 256 *kernel-dram-stack*))
|
||||
(set! (-> obj main-thread) (new 'process 'cpu-thread obj 'main 256 *kernel-dram-stack*))
|
||||
)
|
||||
|
||||
;; these are unknown
|
||||
|
@ -2418,26 +2535,3 @@
|
|||
(change-parent (define *default-pool* (new 'global 'process-tree 'default-pool)) *active-pool*)
|
||||
(set! (-> *default-pool* mask) (process-mask pause menu progress process-tree))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Temp Hacks
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; (defun kernel-dispatcher ()
|
||||
; "Kernel Dispatcher Function. This gets called from the main loop in kboot.cpp's KernelCheckAndDispatch"
|
||||
|
||||
; ;; check if we have a new listener function to run
|
||||
; (when *listener-function*
|
||||
; ;; we do! enable method-set for debug purposes
|
||||
; (+! *enable-method-set* 1)
|
||||
|
||||
; ;; execute and print result
|
||||
; (let ((result (*listener-function*)))
|
||||
; (format #t "~D~%" result)
|
||||
; )
|
||||
; (+! *enable-method-set* -1)
|
||||
|
||||
; ;; clear the pending function.
|
||||
; (set! *listener-function* (the (function object) #f))
|
||||
; )
|
||||
; )
|
||||
|
|
|
@ -876,7 +876,7 @@ Val* Compiler::compile_new(const goos::Object& form, const goos::Object& _rest,
|
|||
auto type = pair_car(*rest);
|
||||
rest = &pair_cdr(*rest);
|
||||
|
||||
if (allocation == "global" || allocation == "debug") {
|
||||
if (allocation == "global" || allocation == "debug" || allocation == "process") {
|
||||
// allocate on a named heap
|
||||
return compile_heap_new(form, allocation, type, rest, env);
|
||||
} else if (allocation == "static") {
|
||||
|
|
|
@ -640,10 +640,8 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||
" )\n"
|
||||
" )\n"
|
||||
" (else\n"
|
||||
// todo - why doesn't this merge?
|
||||
" (set! v1-40 (or (= v1-1 (quote uint128)) (= v1-1 (quote int128))))\n"
|
||||
" (cond\n"
|
||||
" (v1-40\n"
|
||||
" ((or (= v1-1 (quote uint128)) (= v1-1 (quote int128)))\n"
|
||||
" (set! s5-8 0)\n"
|
||||
" (while\n"
|
||||
" (< s5-8 (-> arg0 length))\n"
|
||||
|
@ -1309,9 +1307,8 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||
" )\n"
|
||||
" )\n"
|
||||
" (else\n"
|
||||
" (set! v1-40 (or (= v1-1 (quote int128)) (= v1-1 (quote uint128))))\n"
|
||||
" (cond\n"
|
||||
" (v1-40\n"
|
||||
" ((or (= v1-1 (quote int128)) (= v1-1 (quote uint128)))\n"
|
||||
" (set! s5-8 0)\n"
|
||||
" (while\n"
|
||||
" (< s5-8 (-> arg0 length))\n"
|
||||
|
@ -2092,16 +2089,11 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||
" (quote #f)\n"
|
||||
" )\n"
|
||||
" (else\n"
|
||||
// todo - why isn't this compacted?
|
||||
" (set!\n"
|
||||
" v1-33\n"
|
||||
" (and\n"
|
||||
" (!= arg1 type)\n"
|
||||
" (not (valid? (rtype-of arg0) type (quote #f) (quote #t) 0))\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" (cond\n"
|
||||
" (v1-33\n"
|
||||
" ((and\t\n"
|
||||
" (!= arg1 type)\t\n"
|
||||
" (not (valid? (rtype-of arg0) type (quote #f) (quote #t) 0))\t\n"
|
||||
" )\n"
|
||||
" (if\n"
|
||||
" arg2\n"
|
||||
" (format\n"
|
||||
|
@ -2483,7 +2475,6 @@ TEST_F(FormRegressionTest, ExprStringToInt) {
|
|||
" (a0-5 symbol)\n"
|
||||
" (a1-8 (pointer uint8))\n"
|
||||
" (a1-14 uint)\n"
|
||||
" (a1-16 symbol)\n"
|
||||
" (a1-20 uint)\n"
|
||||
" (a1-23 uint)\n"
|
||||
" (a1-33 symbol)\n"
|
||||
|
@ -2529,15 +2520,11 @@ TEST_F(FormRegressionTest, ExprStringToInt) {
|
|||
" (set! a1-14 v0-0)\n"
|
||||
" )\n"
|
||||
" (else\n"
|
||||
" (set!\n"
|
||||
" a1-16\n"
|
||||
" (and\n"
|
||||
" (>= (-> a0-3 0) (the-as uint 97))\n"
|
||||
" (>= (the-as uint 102) (-> a0-3 0))\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" (cond\n"
|
||||
" (a1-16\n"
|
||||
" ((and\t\n"
|
||||
" (>= (-> a0-3 0) (the-as uint 97))\t\n"
|
||||
" (>= (the-as uint 102) (-> a0-3 0))\t\n"
|
||||
" )\n"
|
||||
" (set! v0-0 (+ (+ (-> a0-3 0) -87) (the-as uint (shl v0-0 4))))\n"
|
||||
" (set! a1-20 v0-0)\n"
|
||||
" )\n"
|
||||
|
|
|
@ -534,8 +534,7 @@ TEST_F(FormRegressionTest, RemoveMethod3ProcessTree) {
|
|||
" (set! a0-5 (quote #t))\n"
|
||||
" (set! a1-4 \"~Tbrother: ~A~%\")\n"
|
||||
" (set! v1-2 (-> arg0 brother))\n"
|
||||
" (set! a2-4 (if v1-2 (-> v1-2 0 self)))\n"
|
||||
" (t9-4 a0-5 a1-4 a2-4)\n"
|
||||
" (t9-4 a0-5 a1-4 (if v1-2 (-> v1-2 0 self)))\n"
|
||||
" (set! t9-5 format)\n"
|
||||
" (set! a0-6 (quote #t))\n"
|
||||
" (set! a1-5 \"~Tchild: ~A~%\")\n"
|
||||
|
@ -2533,7 +2532,8 @@ TEST_F(FormRegressionTest, ExprMethod16DeadPoolHeap) {
|
|||
std::string expected =
|
||||
"(begin\n"
|
||||
" (set! s4-0 (memory-free arg0))\n"
|
||||
" (set! f0-2 (/ (the float s4-0) (the float (memory-total arg0))))\n"
|
||||
" (set! v1-2 (memory-total arg0))\n"
|
||||
" (set! f0-2 (/ (the float s4-0) (the float v1-2)))"
|
||||
" (cond\n"
|
||||
" ((< f0-2 (l.f L346))\n"
|
||||
" (set! arg1 1000)\n"
|
||||
|
|
Loading…
Reference in a new issue