mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 00:57:44 -04:00
[gcommon decomp] compiler and decompiler fixes (#239)
* wip * decompile file-io * a * fix
This commit is contained in:
parent
f8b63a3f92
commit
e01e065170
|
@ -13,12 +13,18 @@ bool debug_reverse_lookup = false;
|
|||
/*!
|
||||
* Is the actual dereference compatible with the expected?
|
||||
*/
|
||||
bool deref_matches(const DerefInfo& expected, const DerefKind& actual, bool is_integer) {
|
||||
bool deref_matches(const DerefInfo& expected,
|
||||
const DerefKind& actual,
|
||||
bool is_integer,
|
||||
bool is_basic) {
|
||||
assert(expected.mem_deref);
|
||||
assert(expected.can_deref);
|
||||
if (actual.is_store || actual.size >= 8 || !is_integer) {
|
||||
// don't check sign extension
|
||||
return expected.load_size == actual.size;
|
||||
} else if (is_basic) {
|
||||
// this is kinda weird, but it seems like GOAL uses lw and lwu for loading basics.
|
||||
return expected.load_size == actual.size;
|
||||
} else {
|
||||
return expected.load_size == actual.size && expected.sign_extend == actual.sign_extend;
|
||||
}
|
||||
|
@ -105,6 +111,7 @@ bool TypeSystem::try_reverse_lookup_pointer(const FieldReverseLookupInput& input
|
|||
auto di = get_deref_info(input.base_type);
|
||||
bool is_integer =
|
||||
typecheck(TypeSpec("integer"), input.base_type.get_single_arg(), "", false, false);
|
||||
bool is_basic = typecheck(TypeSpec("basic"), input.base_type.get_single_arg(), "", false, false);
|
||||
assert(di.mem_deref); // it's accessing a pointer.
|
||||
auto elt_type = di.result_type;
|
||||
if (input.stride) {
|
||||
|
@ -123,7 +130,7 @@ bool TypeSystem::try_reverse_lookup_pointer(const FieldReverseLookupInput& input
|
|||
token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
|
||||
path->push_back(token);
|
||||
if (input.deref.has_value()) {
|
||||
if (deref_matches(di, input.deref.value(), is_integer)) {
|
||||
if (deref_matches(di, input.deref.value(), is_integer, is_basic)) {
|
||||
// access element of array
|
||||
*addr_of = false;
|
||||
*result_type = elt_type;
|
||||
|
@ -151,7 +158,7 @@ bool TypeSystem::try_reverse_lookup_pointer(const FieldReverseLookupInput& input
|
|||
token.kind = FieldReverseLookupOutput::Token::Kind::CONSTANT_IDX;
|
||||
token.idx = elt_idx;
|
||||
if (input.deref.has_value()) {
|
||||
if (!deref_matches(di, input.deref.value(), is_integer)) {
|
||||
if (!deref_matches(di, input.deref.value(), is_integer, is_basic)) {
|
||||
// this isn't the right type of dereference
|
||||
return false;
|
||||
}
|
||||
|
@ -200,6 +207,7 @@ bool TypeSystem::try_reverse_lookup_array(const FieldReverseLookupInput& input,
|
|||
auto di = get_deref_info(array_data_type);
|
||||
bool is_integer =
|
||||
typecheck(TypeSpec("integer"), input.base_type.get_single_arg(), "", false, false);
|
||||
bool is_basic = typecheck(TypeSpec("basic"), input.base_type.get_single_arg(), "", false, false);
|
||||
assert(di.mem_deref); // it's accessing a pointer.
|
||||
auto elt_type = di.result_type;
|
||||
if (input.stride) {
|
||||
|
@ -218,7 +226,7 @@ bool TypeSystem::try_reverse_lookup_array(const FieldReverseLookupInput& input,
|
|||
token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
|
||||
path->push_back(token);
|
||||
if (input.deref.has_value()) {
|
||||
if (deref_matches(di, input.deref.value(), is_integer)) {
|
||||
if (deref_matches(di, input.deref.value(), is_integer, is_basic)) {
|
||||
// access element of array
|
||||
*addr_of = false;
|
||||
*result_type = elt_type;
|
||||
|
@ -248,7 +256,7 @@ bool TypeSystem::try_reverse_lookup_array(const FieldReverseLookupInput& input,
|
|||
// always put array index, even if it's zero.
|
||||
path->push_back(token);
|
||||
if (input.deref.has_value()) {
|
||||
if (!deref_matches(di, input.deref.value(), is_integer)) {
|
||||
if (!deref_matches(di, input.deref.value(), is_integer, is_basic)) {
|
||||
// this isn't the right type of dereference
|
||||
return false;
|
||||
}
|
||||
|
@ -391,7 +399,8 @@ bool TypeSystem::try_reverse_lookup_other(const FieldReverseLookupInput& input,
|
|||
TypeSpec loc_type = make_pointer_typespec(field_deref.type);
|
||||
auto di = get_deref_info(loc_type);
|
||||
bool is_integer = typecheck(TypeSpec("integer"), field_deref.type, "", false, false);
|
||||
if (!deref_matches(di, input.deref.value(), is_integer)) {
|
||||
bool is_basic = typecheck(TypeSpec("basic"), field_deref.type, "", false, false);
|
||||
if (!deref_matches(di, input.deref.value(), is_integer, is_basic)) {
|
||||
continue; // try another field!
|
||||
}
|
||||
// it's a match, just access the field like normal!
|
||||
|
|
|
@ -820,7 +820,13 @@ void TypeSystem::add_builtin_types() {
|
|||
add_field_to_type(connectable_type, "prev1", make_typespec("connectable"));
|
||||
|
||||
// todo
|
||||
(void)file_stream_type;
|
||||
builtin_structure_inherit(file_stream_type);
|
||||
add_field_to_type(file_stream_type, "flags", make_typespec("uint32"));
|
||||
add_field_to_type(file_stream_type, "mode", make_typespec("basic"));
|
||||
add_field_to_type(file_stream_type, "name", make_typespec("string"));
|
||||
add_field_to_type(file_stream_type, "file", make_typespec("uint32"));
|
||||
add_method(file_stream_type, "new",
|
||||
make_function_typespec({"symbol", "type", "string", "basic"}, "_type_"));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -291,6 +291,7 @@ class AsmOp : public AtomicOp {
|
|||
const Env& env,
|
||||
DecompilerTypeSystem& dts) override;
|
||||
void collect_vars(VariableSet& vars) const override;
|
||||
const Instruction& instruction() const { return m_instr; }
|
||||
|
||||
private:
|
||||
Instruction m_instr;
|
||||
|
|
|
@ -79,7 +79,7 @@ FormElement* SetVarOp::get_as_form(FormPool& pool, const Env& env) const {
|
|||
}
|
||||
|
||||
FormElement* AsmOp::get_as_form(FormPool& pool, const Env&) const {
|
||||
return pool.alloc_element<AtomicOpElement>(this);
|
||||
return pool.alloc_element<AsmOpElement>(this);
|
||||
}
|
||||
|
||||
FormElement* SetVarConditionOp::get_as_form(FormPool& pool, const Env& env) const {
|
||||
|
|
|
@ -112,7 +112,9 @@ TP_Type SimpleAtom::get_type(const TypeState& input,
|
|||
} else if ((label.offset & 7) == PAIR_OFFSET) {
|
||||
return TP_Type::make_from_ts(TypeSpec("pair"));
|
||||
}
|
||||
throw std::runtime_error("IR_StaticAddress couldn't figure out the type: " + label.name);
|
||||
// throw std::runtime_error("IR_StaticAddress couldn't figure out the type: " + label.name);
|
||||
lg::error("IR_StaticAddress doesn't know the type of {}", label.name);
|
||||
return TP_Type::make_from_ts("object");
|
||||
}
|
||||
case Kind::INVALID:
|
||||
default:
|
||||
|
@ -136,6 +138,12 @@ TP_Type SimpleExpression::get_type(const TypeState& input,
|
|||
}
|
||||
case Kind::FPR_TO_GPR:
|
||||
case Kind::DIV_S:
|
||||
case Kind::SUB_S:
|
||||
case Kind::MUL_S:
|
||||
case Kind::ADD_S:
|
||||
case Kind::SQRT_S:
|
||||
case Kind::ABS_S:
|
||||
case Kind::NEG_S:
|
||||
return TP_Type::make_from_ts("float");
|
||||
case Kind::ADD:
|
||||
case Kind::SUB:
|
||||
|
|
|
@ -349,6 +349,36 @@ void AtomicOpElement::get_modified_regs(RegSet& regs) const {
|
|||
}
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// AsmOpElement
|
||||
/////////////////////////////
|
||||
|
||||
AsmOpElement::AsmOpElement(const AsmOp* op) : m_op(op) {}
|
||||
|
||||
goos::Object AsmOpElement::to_form(const Env& env) const {
|
||||
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*)>&) {}
|
||||
|
||||
void AsmOpElement::collect_vars(VariableSet& vars) const {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// ConditionElement
|
||||
/////////////////////////////
|
||||
|
@ -474,29 +504,38 @@ goos::Object ReturnElement::to_form(const Env& env) const {
|
|||
std::vector<goos::Object> forms;
|
||||
forms.push_back(pretty_print::to_symbol("return"));
|
||||
forms.push_back(return_code->to_form(env));
|
||||
forms.push_back(dead_code->to_form(env));
|
||||
if (dead_code) {
|
||||
forms.push_back(dead_code->to_form(env));
|
||||
}
|
||||
return pretty_print::build_list(forms);
|
||||
}
|
||||
|
||||
void ReturnElement::apply(const std::function<void(FormElement*)>& f) {
|
||||
f(this);
|
||||
return_code->apply(f);
|
||||
dead_code->apply(f);
|
||||
if (dead_code) {
|
||||
dead_code->apply(f);
|
||||
}
|
||||
}
|
||||
|
||||
void ReturnElement::apply_form(const std::function<void(Form*)>& f) {
|
||||
return_code->apply_form(f);
|
||||
dead_code->apply_form(f);
|
||||
if (dead_code) {
|
||||
dead_code->apply_form(f);
|
||||
}
|
||||
}
|
||||
|
||||
void ReturnElement::collect_vars(VariableSet& vars) const {
|
||||
return_code->collect_vars(vars);
|
||||
dead_code->collect_vars(vars);
|
||||
if (dead_code) {
|
||||
dead_code->collect_vars(vars);
|
||||
}
|
||||
}
|
||||
|
||||
void ReturnElement::get_modified_regs(RegSet& regs) const {
|
||||
for (auto x : {return_code, dead_code}) {
|
||||
x->get_modified_regs(regs);
|
||||
return_code->get_modified_regs(regs);
|
||||
if (dead_code) {
|
||||
dead_code->get_modified_regs(regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -874,7 +913,7 @@ TypeOfElement::TypeOfElement(Form* _value, std::optional<Variable> _clobber)
|
|||
}
|
||||
|
||||
goos::Object TypeOfElement::to_form(const Env& env) const {
|
||||
return pretty_print::build_list("type-of", value->to_form(env));
|
||||
return pretty_print::build_list("rtype-of", value->to_form(env));
|
||||
}
|
||||
|
||||
void TypeOfElement::apply(const std::function<void(FormElement*)>& f) {
|
||||
|
@ -1048,6 +1087,8 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
|
|||
return "-";
|
||||
case FixedOperatorKind::MULTIPLICATION:
|
||||
return "*";
|
||||
case FixedOperatorKind::SQRT:
|
||||
return "sqrt";
|
||||
case FixedOperatorKind::ARITH_SHIFT:
|
||||
return "ash";
|
||||
case FixedOperatorKind::MOD:
|
||||
|
|
|
@ -84,6 +84,18 @@ class SimpleExpressionElement : public FormElement {
|
|||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
void update_from_stack_float_2(const Env& env,
|
||||
FixedOperatorKind kind,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
void update_from_stack_float_1(const Env& env,
|
||||
FixedOperatorKind kind,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects);
|
||||
void update_from_stack_add_i(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
|
@ -259,6 +271,24 @@ class AtomicOpElement : public FormElement {
|
|||
const AtomicOp* m_op;
|
||||
};
|
||||
|
||||
/*!
|
||||
* A wrapper around a single AsmOp
|
||||
*/
|
||||
class AsmOpElement : public FormElement {
|
||||
public:
|
||||
explicit AsmOpElement(const AsmOp* op);
|
||||
goos::Object to_form(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;
|
||||
const AsmOp* op() const { return m_op; }
|
||||
|
||||
private:
|
||||
const AsmOp* m_op;
|
||||
};
|
||||
|
||||
/*!
|
||||
* 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)).
|
||||
|
@ -344,6 +374,8 @@ class BranchElement : public FormElement {
|
|||
/*!
|
||||
* Represents a (return-from #f x) form, which immediately returns from the function.
|
||||
* This always has some "dead code" after it that can't be reached, which is the "dead_code".
|
||||
* We store the dead code because it may contain an unreachable jump to the next place that can
|
||||
* be stripped away in later analysis passes. Or they may have written code after the return.
|
||||
*/
|
||||
class ReturnElement : public FormElement {
|
||||
public:
|
||||
|
@ -444,6 +476,7 @@ class EmptyElement : public FormElement {
|
|||
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;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -646,6 +679,7 @@ class ConditionalMoveFalseElement : public FormElement {
|
|||
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;
|
||||
};
|
||||
|
||||
std::string fixed_operator_to_string(FixedOperatorKind kind);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "FormStack.h"
|
||||
#include "GenericElementMatcher.h"
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
|
||||
/*
|
||||
* TODO
|
||||
|
@ -335,6 +336,42 @@ void SimpleExpressionElement::update_from_stack_div_s(const Env& env,
|
|||
}
|
||||
}
|
||||
|
||||
void SimpleExpressionElement::update_from_stack_float_2(const Env& env,
|
||||
FixedOperatorKind kind,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
if (is_float_type(env, m_my_idx, m_expr.get_arg(0).var()) &&
|
||||
is_float_type(env, m_my_idx, m_expr.get_arg(1).var())) {
|
||||
// todo - check the order here
|
||||
|
||||
auto args = pop_to_forms({m_expr.get_arg(0).var(), m_expr.get_arg(1).var()}, env, pool, stack,
|
||||
allow_side_effects);
|
||||
auto new_form = pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind),
|
||||
args.at(0), args.at(1));
|
||||
result->push_back(new_form);
|
||||
} else {
|
||||
throw std::runtime_error(fmt::format("Floating point math attempted on invalid types."));
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleExpressionElement::update_from_stack_float_1(const Env& env,
|
||||
FixedOperatorKind kind,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
std::vector<FormElement*>* result,
|
||||
bool allow_side_effects) {
|
||||
if (is_float_type(env, m_my_idx, m_expr.get_arg(0).var())) {
|
||||
auto args = pop_to_forms({m_expr.get_arg(0).var()}, env, pool, stack, allow_side_effects);
|
||||
auto new_form =
|
||||
pool.alloc_element<GenericElement>(GenericOperator::make_fixed(kind), args.at(0));
|
||||
result->push_back(new_form);
|
||||
} else {
|
||||
throw std::runtime_error(fmt::format("Floating point division attempted on invalid types."));
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
|
@ -546,6 +583,30 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
|
|||
case SimpleExpression::Kind::DIV_S:
|
||||
update_from_stack_div_s(env, pool, stack, result, allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::SUB_S:
|
||||
update_from_stack_float_2(env, FixedOperatorKind::SUBTRACTION, pool, stack, result,
|
||||
allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::MUL_S:
|
||||
update_from_stack_float_2(env, FixedOperatorKind::MULTIPLICATION, pool, stack, result,
|
||||
allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::ADD_S:
|
||||
update_from_stack_float_2(env, FixedOperatorKind::ADDITION, pool, stack, result,
|
||||
allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::SQRT_S:
|
||||
update_from_stack_float_1(env, FixedOperatorKind::SQRT, pool, stack, result,
|
||||
allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::ABS_S:
|
||||
update_from_stack_float_1(env, FixedOperatorKind::ABS, pool, stack, result,
|
||||
allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::NEG_S:
|
||||
update_from_stack_float_1(env, FixedOperatorKind::SUBTRACTION, pool, stack, result,
|
||||
allow_side_effects);
|
||||
break;
|
||||
case SimpleExpression::Kind::ADD:
|
||||
update_from_stack_add_i(env, pool, stack, result, allow_side_effects);
|
||||
break;
|
||||
|
@ -702,7 +763,29 @@ void FunctionCallElement::update_from_stack(const Env& env,
|
|||
}
|
||||
auto unstacked = pop_to_forms(all_pop_vars, env, pool, stack, allow_side_effects);
|
||||
std::vector<Form*> arg_forms;
|
||||
arg_forms.insert(arg_forms.begin(), unstacked.begin() + 1, unstacked.end());
|
||||
TypeSpec function_type;
|
||||
if (env.has_type_analysis()) {
|
||||
function_type =
|
||||
env.get_types_before_op(all_pop_vars.at(0).idx()).get(all_pop_vars.at(0).reg()).typespec();
|
||||
}
|
||||
|
||||
for (size_t arg_id = 0; arg_id < nargs; arg_id++) {
|
||||
auto val = unstacked.at(arg_id + 1); // first is the function itself.
|
||||
auto& var = all_pop_vars.at(arg_id + 1);
|
||||
if (env.has_type_analysis() && function_type.arg_count() == nargs + 1) {
|
||||
auto actual_arg_type = env.get_types_before_op(var.idx()).get(var.reg()).typespec();
|
||||
auto desired_arg_type = function_type.get_arg(arg_id);
|
||||
if (!env.dts->ts.typecheck(desired_arg_type, actual_arg_type, "", false, false)) {
|
||||
arg_forms.push_back(
|
||||
pool.alloc_single_element_form<CastElement>(nullptr, desired_arg_type, val));
|
||||
} else {
|
||||
arg_forms.push_back(val);
|
||||
}
|
||||
} else {
|
||||
arg_forms.push_back(val);
|
||||
}
|
||||
}
|
||||
|
||||
auto new_form = pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(unstacked.at(0)), arg_forms);
|
||||
|
||||
|
@ -1161,6 +1244,36 @@ FormElement* ConditionElement::make_generic(const Env&,
|
|||
casted);
|
||||
}
|
||||
|
||||
case IR2_Condition::Kind::FLOAT_NOT_EQUAL: {
|
||||
auto casted = make_cast(source_forms, types, TypeSpec("float"), pool);
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::NEQ),
|
||||
casted);
|
||||
}
|
||||
|
||||
case IR2_Condition::Kind::FLOAT_EQUAL: {
|
||||
auto casted = make_cast(source_forms, types, TypeSpec("float"), pool);
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::EQ),
|
||||
casted);
|
||||
}
|
||||
|
||||
case IR2_Condition::Kind::FLOAT_LEQ: {
|
||||
auto casted = make_cast(source_forms, types, TypeSpec("float"), pool);
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::LEQ),
|
||||
casted);
|
||||
}
|
||||
|
||||
case IR2_Condition::Kind::FLOAT_LESS_THAN: {
|
||||
auto casted = make_cast(source_forms, types, TypeSpec("float"), pool);
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::LT),
|
||||
casted);
|
||||
}
|
||||
|
||||
case IR2_Condition::Kind::FLOAT_GEQ: {
|
||||
auto casted = make_cast(source_forms, types, TypeSpec("float"), pool);
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::GEQ),
|
||||
casted);
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error("ConditionElement::make_generic NYI for kind " +
|
||||
get_condition_kind_name(m_kind));
|
||||
|
@ -1254,6 +1367,10 @@ void AtomicOpElement::push_to_stack(const Env& env, FormPool&, FormStack& stack)
|
|||
throw std::runtime_error("Can't push atomic op to stack: " + m_op->to_string(env));
|
||||
}
|
||||
|
||||
void AsmOpElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
void GenericElement::update_from_stack(const Env& env,
|
||||
FormPool& pool,
|
||||
FormStack& stack,
|
||||
|
@ -1305,7 +1422,7 @@ void DynamicMethodAccess::update_from_stack(const Env& env,
|
|||
|
||||
auto deref = pool.alloc_element<DerefElement>(
|
||||
var_to_form(base.value(), pool), false,
|
||||
std::vector<DerefToken>{DerefToken::make_field_name("methods"),
|
||||
std::vector<DerefToken>{DerefToken::make_field_name("method-table"),
|
||||
DerefToken::make_int_expr(var_to_form(idx.value(), pool))});
|
||||
result->push_back(deref);
|
||||
}
|
||||
|
@ -1450,4 +1567,16 @@ void TypeOfElement::update_from_stack(const Env& env,
|
|||
result->push_back(this);
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// EmptyElement
|
||||
////////////////////////
|
||||
|
||||
void EmptyElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
void ConditionalMoveFalseElement::push_to_stack(const Env&, FormPool&, FormStack& stack) {
|
||||
stack.push_form_element(this, true);
|
||||
}
|
||||
|
||||
} // namespace decompiler
|
||||
|
|
|
@ -95,6 +95,7 @@ enum class FixedOperatorKind {
|
|||
ADDITION,
|
||||
SUBTRACTION,
|
||||
MULTIPLICATION,
|
||||
SQRT,
|
||||
ARITH_SHIFT,
|
||||
MOD,
|
||||
ABS,
|
||||
|
@ -125,9 +126,15 @@ enum class FixedOperatorKind {
|
|||
struct VariableNames {
|
||||
struct VarInfo {
|
||||
VarInfo() = default;
|
||||
std::string name() const { return fmt::format("{}-{}", reg_id.reg.to_charp(), reg_id.id); }
|
||||
std::string name() const {
|
||||
if (!override_name.empty()) {
|
||||
return override_name;
|
||||
}
|
||||
return fmt::format("{}-{}", reg_id.reg.to_charp(), reg_id.id);
|
||||
}
|
||||
TP_Type type;
|
||||
RegId reg_id;
|
||||
std::string override_name;
|
||||
bool initialized = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -150,6 +150,30 @@ void clean_up_return(FormPool& pool, ReturnElement* ir) {
|
|||
}
|
||||
}
|
||||
|
||||
void clean_up_return_final(const Function& f, ReturnElement* ir) {
|
||||
SetVarElement* dead = dynamic_cast<SetVarElement*>(ir->dead_code->try_as_single_element());
|
||||
if (!dead) {
|
||||
dead = dynamic_cast<SetVarElement*>(ir->dead_code->elts().front());
|
||||
for (int i = 1; i < ir->dead_code->size(); i++) {
|
||||
if (!dynamic_cast<EmptyElement*>(ir->dead_code->at(i))) {
|
||||
dead = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dead) {
|
||||
lg::error("failed to recognize dead code after return, got {}",
|
||||
ir->dead_code->to_string(f.ir2.env));
|
||||
}
|
||||
assert(dead);
|
||||
auto src = dynamic_cast<SimpleExpressionElement*>(dead->src()->try_as_single_element());
|
||||
assert(src);
|
||||
assert(src->expr().is_identity() && src->expr().get_arg(0).is_int() &&
|
||||
src->expr().get_arg(0).get_int() == 0);
|
||||
ir->dead_code = nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Remove the branch in a break (really return-from nonfunction scope)
|
||||
*/
|
||||
|
@ -1355,8 +1379,22 @@ Form* cfg_to_ir(FormPool& pool, Function& f, const CfgVtx* vtx) {
|
|||
return result;
|
||||
} else if (dynamic_cast<const GotoEnd*>(vtx)) {
|
||||
auto* cvtx = dynamic_cast<const GotoEnd*>(vtx);
|
||||
|
||||
// dead code should always be (set! var 0)
|
||||
auto dead_code = cfg_to_ir(pool, f, cvtx->unreachable_block);
|
||||
// auto dead = dynamic_cast<SetVarElement*>(dead_code->try_as_single_element());
|
||||
// if (!dead) {
|
||||
// lg::error("failed to recognize dead code after return, got {}",
|
||||
// dead_code->to_string(f.ir2.env));
|
||||
// }
|
||||
// assert(dead);
|
||||
// auto src = dynamic_cast<SimpleExpressionElement*>(dead->src()->try_as_single_element());
|
||||
// assert(src);
|
||||
// assert(src->expr().is_identity() && src->expr().get_arg(0).is_int() &&
|
||||
// src->expr().get_arg(0).get_int() == 0);
|
||||
|
||||
auto result = pool.alloc_single_element_form<ReturnElement>(
|
||||
nullptr, cfg_to_ir(pool, f, cvtx->body), cfg_to_ir(pool, f, cvtx->unreachable_block));
|
||||
nullptr, cfg_to_ir(pool, f, cvtx->body), dead_code);
|
||||
clean_up_return(pool, dynamic_cast<ReturnElement*>(result->try_as_single_element()));
|
||||
return result;
|
||||
} else if (dynamic_cast<const Break*>(vtx)) {
|
||||
|
@ -1433,6 +1471,11 @@ void build_initial_forms(Function& function) {
|
|||
if (as_cne) {
|
||||
clean_up_cond_no_else_final(function, as_cne);
|
||||
}
|
||||
|
||||
auto as_return = dynamic_cast<ReturnElement*>(form);
|
||||
if (as_return) {
|
||||
clean_up_return_final(function, as_return);
|
||||
}
|
||||
});
|
||||
|
||||
function.ir2.top_form = result;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
namespace decompiler {
|
||||
|
||||
// TODO - remove all these and put them in the analysis methods instead.
|
||||
void clean_up_ifs(Form* top_level_form) {
|
||||
void clean_up_ifs(Form* top_level_form, const Env&) {
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
|
@ -30,6 +30,9 @@ void clean_up_ifs(Form* top_level_form) {
|
|||
assert(me != parent_vector.end());
|
||||
|
||||
// now insert the fake condition
|
||||
for (auto& x : top_condition->elts()) {
|
||||
x->parent_form = elt->parent_form;
|
||||
}
|
||||
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
|
||||
top_condition->elts() = {real_condition};
|
||||
changed = true;
|
||||
|
@ -54,6 +57,9 @@ void clean_up_ifs(Form* top_level_form) {
|
|||
assert(me != parent_vector.end());
|
||||
|
||||
// now insert the fake condition
|
||||
for (auto& x : top_condition->elts()) {
|
||||
x->parent_form = elt->parent_form;
|
||||
}
|
||||
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
|
||||
top_condition->elts() = {real_condition};
|
||||
changed = true;
|
||||
|
@ -81,6 +87,9 @@ void clean_up_ifs(Form* top_level_form) {
|
|||
assert(me != parent_vector.end());
|
||||
|
||||
// now insert the fake condition
|
||||
for (auto& x : top_condition->elts()) {
|
||||
x->parent_form = elt->parent_form;
|
||||
}
|
||||
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
|
||||
top_condition->elts() = {real_condition};
|
||||
changed = true;
|
||||
|
@ -153,7 +162,7 @@ bool convert_to_expressions(Form* top_level_form,
|
|||
// fmt::print("Before clean:\n{}\n",
|
||||
// pretty_print::to_string(top_level_form->to_form(f.ir2.env)));
|
||||
// fix up stuff
|
||||
clean_up_ifs(top_level_form);
|
||||
clean_up_ifs(top_level_form, f.ir2.env);
|
||||
|
||||
} catch (std::exception& e) {
|
||||
std::string warning = fmt::format("Expression building failed: {}", e.what());
|
||||
|
|
|
@ -56,6 +56,10 @@
|
|||
(define-extern *enable-method-set* int)
|
||||
(define-extern install-debug-handler (function int object symbol))
|
||||
|
||||
(define-extern file-stream-open (function file-stream basic basic file-stream))
|
||||
(define-extern file-stream-length (function file-stream int))
|
||||
(define-extern file-stream-read (function file-stream pointer int int))
|
||||
|
||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; GCOMMON ;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -740,6 +744,7 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
|
||||
|
||||
(deftype bit-array (basic)
|
||||
((length int32 :offset-assert 4)
|
||||
(allocated-length int32 :offset-assert 8)
|
||||
|
@ -914,7 +919,8 @@
|
|||
)
|
||||
|
||||
(deftype vector (structure)
|
||||
((data float 4 :offset-assert 0)
|
||||
(
|
||||
(data float 4 :offset-assert 0)
|
||||
(x float :offset 0)
|
||||
(y float :offset 4)
|
||||
(z float :offset 8)
|
||||
|
@ -1793,6 +1799,7 @@
|
|||
; ;; likely a bitfield type
|
||||
; )
|
||||
|
||||
|
||||
; ;; dma-h
|
||||
(deftype dma-bucket (structure)
|
||||
((tag uint64 :offset-assert 0)
|
||||
|
@ -2219,24 +2226,109 @@
|
|||
|
||||
(define-extern *display* display)
|
||||
|
||||
;;;;;;;;;;;;;;;
|
||||
;; file-io
|
||||
;;;;;;;;;;;;;;;
|
||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; VECTOR ;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
|
||||
;; todo
|
||||
; (deftype file-stream (basic)
|
||||
; ((flags uint32 :offset-assert 4)
|
||||
; (mode basic :offset-assert 8)
|
||||
; (name basic :offset-assert 12)
|
||||
; (file uint32 :offset-assert 16)
|
||||
; )
|
||||
; :method-count-assert 9
|
||||
; :size-assert #x14
|
||||
; :flag-assert #x900000014
|
||||
; )
|
||||
(define-extern sin (function float float))
|
||||
(define-extern cos (function float float))
|
||||
(define-extern atan (function float float float))
|
||||
|
||||
(define-extern vector-cross! (function vector vector vector vector))
|
||||
(define-extern vector+float! (function vector vector float vector))
|
||||
(define-extern vector*! (function vector vector vector vector))
|
||||
(define-extern vector+*! (function vector vector vector float vector))
|
||||
(define-extern vector-*! (function vector vector vector float vector))
|
||||
(define-extern vector/! (function vector vector vector vector))
|
||||
(define-extern vector-float*! (function vector vector float vector))
|
||||
(define-extern vector-average! (function vector vector vector vector))
|
||||
(define-extern vector+float*! (function vector vector vector float vector))
|
||||
(define-extern vector--float*! (function vector vector vector float vector))
|
||||
(define-extern vector-float/! (function vector vector float vector))
|
||||
(define-extern vector-negate! (function vector vector vector))
|
||||
(define-extern vector-negate-in-place! (function vector vector))
|
||||
(define-extern vector= (function vector vector symbol))
|
||||
(define-extern vector-delta (function vector vector float))
|
||||
(define-extern vector-seek! (function vector vector float vector))
|
||||
(define-extern vector-seek-2d-xz-smooth! (function vector vector float float vector))
|
||||
(define-extern vector-seek-2d-yz-smooth! (function vector vector float float vector))
|
||||
(define-extern vector-seek-3d-smooth! (function vector vector float float vector))
|
||||
(define-extern seek-with-smooth (function float float float float float float))
|
||||
(define-extern vector-identity! (function vector vector))
|
||||
(define-extern vector-seconds (function vector vector vector))
|
||||
(define-extern vector-seconds! (function vector vector))
|
||||
(define-extern vector-v! (function vector vector))
|
||||
(define-extern vector-v+! (function vector vector vector vector))
|
||||
(define-extern vector-v*float+! (function vector vector vector float vector))
|
||||
(define-extern vector-v++! (function vector vector vector))
|
||||
(define-extern vector-v*float! (function vector float float vector))
|
||||
(define-extern vector-v*float++! (function vector vector float vector))
|
||||
(define-extern vector-to-ups! (function vector vector vector))
|
||||
(define-extern vector-from-ups! (function vector vector vector))
|
||||
(define-extern vector-length (function vector float))
|
||||
(define-extern vector-length-squared (function vector float))
|
||||
(define-extern vector-xz-length-squared (function vector float))
|
||||
(define-extern vector-xz-length (function vector float))
|
||||
(define-extern vector-vector-distance (function vector vector float))
|
||||
(define-extern vector-vector-distance-squared (function vector vector float))
|
||||
(define-extern vector-vector-xz-distance (function vector vector float))
|
||||
(define-extern vector-vector-xz-distance-squared (function vector vector float))
|
||||
(define-extern vector-normalize! (function vector vector vector))
|
||||
(define-extern vector-normalize-ret-len! (function vector float float))
|
||||
(define-extern vector-normalize-copy! (function vector vector float vector))
|
||||
(define-extern vector-xz-normalize! (function vector float vector))
|
||||
(define-extern vector-length-max! (function vector float vector))
|
||||
(define-extern vector-xz-length-max! (function vector float vector))
|
||||
(define-extern vector-rotate-around-y! (function vector vector float vector))
|
||||
(define-extern rotate-y<-vector+vector (function vector vector float))
|
||||
(define-extern vector-cvt.w.s! (function vector vector vector))
|
||||
(define-extern vector-cvt.s.w! (function vector vector vector))
|
||||
(define-extern rot-zxy-from-vector! (function vector vector vector))
|
||||
(define-extern rot-zyx-from-vector! (function vector vector vector))
|
||||
(define-extern vector-lerp! (function vector vector vector))
|
||||
(define-extern vector-lerp-clamp! (function vector vector float float vector))
|
||||
(define-extern vector4-lerp! (function vector vector vector))
|
||||
(define-extern vector4-lerp-clamp! (function vector vector float float vector))
|
||||
(define-extern vector-degi (function vector vector vector))
|
||||
(define-extern vector-degf (function vector vector vector))
|
||||
(define-extern vector-degmod (function vector vector vector))
|
||||
(define-extern vector-deg-diff (function vector vector vector vector))
|
||||
(define-extern vector-deg-lerp-clamp! function) ;; todo
|
||||
(define-extern vector3s-copy! (function vector vector vector))
|
||||
(define-extern vector3s+! (function vector vector vector vector))
|
||||
(define-extern vector3s*float! (function vector vector float vector))
|
||||
(define-extern vector3s-! (function vector vector vector vector))
|
||||
(define-extern spheres-overlap? (function vector vector symbol))
|
||||
(define-extern sphere<-vector! (function sphere vector sphere))
|
||||
(define-extern sphere<-vector+r! (function sphere vector float sphere))
|
||||
(define-extern rand-vu-sphere-point! function) ;; todo
|
||||
|
||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; FILE-IO ;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
|
||||
(deftype file-stream (basic)
|
||||
((flags uint32 :offset-assert 4)
|
||||
(mode basic :offset-assert 8)
|
||||
(name string :offset-assert 12)
|
||||
(file uint32 :offset-assert 16)
|
||||
)
|
||||
(:methods
|
||||
(new ((allocation symbol) (type-to-make type) (name string) (mode basic)) _type_)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x14
|
||||
:flag-assert #x900000014
|
||||
)
|
||||
|
||||
(define-extern file-stream-read-string (function file-stream string string))
|
||||
|
||||
(deftype file-info (basic)
|
||||
((file-type basic :offset-assert 4)
|
||||
((file-type symbol :offset-assert 4)
|
||||
(file-name basic :offset-assert 8)
|
||||
(major-version uint32 :offset-assert 12)
|
||||
(minor-version uint32 :offset-assert 16)
|
||||
|
@ -2249,6 +2341,12 @@
|
|||
:flag-assert #x900000020
|
||||
)
|
||||
|
||||
(define-extern *file-temp-string* string)
|
||||
|
||||
(define-extern make-file-name (function int string int string))
|
||||
(define-extern make-vfile-name (function int string string))
|
||||
(define-extern file-info-correct-version? (function file-info int int symbol))
|
||||
|
||||
;;;;;;;;;;;;;;;
|
||||
;; loader-h
|
||||
;;;;;;;;;;;;;;;
|
||||
|
@ -31396,14 +31494,11 @@
|
|||
(define-extern matrix-translate! function)
|
||||
(define-extern matrix-4x4-inverse! function)
|
||||
(define-extern matrix-! function)
|
||||
(define-extern atan function)
|
||||
(define-extern vector-sincos! function)
|
||||
(define-extern cos function)
|
||||
(define-extern sin function)
|
||||
(define-extern trs-matrix-calc! function)
|
||||
(define-extern transform-matrix-parent-calc! function)
|
||||
(define-extern transform-matrix-calc! function)
|
||||
(define-extern vector-identity! function)
|
||||
|
||||
(define-extern quaternion-zero! function)
|
||||
(define-extern quaternion-set! function)
|
||||
(define-extern matrix->quaternion function)
|
||||
|
@ -31457,15 +31552,15 @@
|
|||
(define-extern quaternion-i! function)
|
||||
(define-extern sincos-rad! function)
|
||||
(define-extern vector-sincos-rad! function)
|
||||
(define-extern vector-xz-normalize! function)
|
||||
|
||||
(define-extern atan-series-rad function)
|
||||
(define-extern atan2-rad function)
|
||||
(define-extern quaternion-from-two-vectors-max-angle! function)
|
||||
(define-extern vector-length function)
|
||||
|
||||
(define-extern vector-rad<-vector-deg/2! function)
|
||||
(define-extern vector-sin-rad! function)
|
||||
(define-extern acos-rad function)
|
||||
(define-extern vector-xz-length function)
|
||||
|
||||
(define-extern acos function)
|
||||
(define-extern quat->eul function)
|
||||
(define-extern set-eul! function)
|
||||
|
@ -31514,15 +31609,7 @@
|
|||
(define-extern forward-down-nopitch->inv-matrix function)
|
||||
(define-extern vector-reflect-flat-above! function)
|
||||
(define-extern vector-circle-tangent-new function)
|
||||
(define-extern vector-vector-distance-squared function)
|
||||
(define-extern vector-cross! function)
|
||||
(define-extern vector+float*! function)
|
||||
(define-extern vector-normalize! function)
|
||||
(define-extern vector-negate! function)
|
||||
(define-extern vector-vector-distance function)
|
||||
(define-extern vector-normalize-ret-len! function)
|
||||
(define-extern vector-normalize-copy! function)
|
||||
(define-extern vector-float*! function)
|
||||
|
||||
(define-extern coserp function)
|
||||
(define-extern sinerp-clamp function)
|
||||
;;(define-extern exp-slead object) ;; unknown type
|
||||
|
@ -31773,72 +31860,9 @@
|
|||
;;(define-extern draw-env object) ;; unknown type
|
||||
;;(define-extern *pre-draw-hook* object) ;; unknown type
|
||||
(define-extern set-display function)
|
||||
(define-extern vector4-lerp! function)
|
||||
(define-extern rotate-y<-vector+vector function)
|
||||
(define-extern rot-zxy-from-vector! function)
|
||||
(define-extern vector3s-copy! function)
|
||||
(define-extern vector-seek-2d-yz-smooth! function)
|
||||
(define-extern vector-from-ups! function)
|
||||
(define-extern vector-seek-2d-xz-smooth! function)
|
||||
(define-extern vector/! function)
|
||||
(define-extern rand-vu-sphere-point! function)
|
||||
(define-extern vector-vector-xz-distance function)
|
||||
(define-extern vector-v*float+! function)
|
||||
(define-extern vector-length-max! function)
|
||||
(define-extern vector*! function)
|
||||
(define-extern vector+*! function)
|
||||
(define-extern vector-deg-lerp-clamp! function)
|
||||
(define-extern vector-negate-in-place! function)
|
||||
(define-extern vector--float*! function)
|
||||
(define-extern rot-zyx-from-vector! function)
|
||||
(define-extern vector4-lerp-clamp! function)
|
||||
(define-extern vector-seconds! function)
|
||||
(define-extern vector-degmod function)
|
||||
(define-extern vector-v*float++! function)
|
||||
(define-extern vector-degi function)
|
||||
(define-extern sphere<-vector+r! function)
|
||||
(define-extern vector-xz-length-max! function)
|
||||
(define-extern vector3s-! function)
|
||||
(define-extern vector3s+! function)
|
||||
(define-extern vector-average! function)
|
||||
(define-extern vector-cvt.w.s! function)
|
||||
(define-extern vector-v! function)
|
||||
(define-extern vector-degf function)
|
||||
(define-extern vector-vector-xz-distance-squared function)
|
||||
(define-extern vector-xz-length-squared function)
|
||||
(define-extern vector-lerp-clamp! function)
|
||||
(define-extern vector-cvt.s.w! function)
|
||||
(define-extern vector-to-ups! function)
|
||||
(define-extern vector-seek! function)
|
||||
(define-extern vector-seconds function)
|
||||
(define-extern vector-deg-diff function)
|
||||
(define-extern vector-delta function)
|
||||
(define-extern vector+float! function)
|
||||
(define-extern vector-v+! function)
|
||||
(define-extern vector3s*float! function)
|
||||
(define-extern spheres-overlap? function)
|
||||
(define-extern vector-length-squared function)
|
||||
(define-extern vector-lerp! function)
|
||||
(define-extern vector-rotate-around-y! function)
|
||||
(define-extern vector-*! function)
|
||||
(define-extern seek-with-smooth function)
|
||||
(define-extern vector-v*float! function)
|
||||
(define-extern vector-v++! function)
|
||||
(define-extern vector-seek-3d-smooth! function)
|
||||
(define-extern sphere<-vector! function)
|
||||
(define-extern vector-float/! function)
|
||||
(define-extern vector= function)
|
||||
|
||||
;;(define-extern *display* object) ;; unknown type
|
||||
(define-extern make-vfile-name function)
|
||||
;;(define-extern file-stream object) ;; unknown type
|
||||
(define-extern file-info type)
|
||||
(define-extern make-file-name function)
|
||||
(define-extern file-info-correct-version? function)
|
||||
;;(define-extern *file-temp-string* object) ;; unknown type
|
||||
(define-extern file-stream-read-string function)
|
||||
;;(define-extern file-stream-length object) ;; unknown type
|
||||
;;(define-extern file-stream-read object) ;; unknown type
|
||||
;;(define-extern file-stream-open object) ;; unknown type
|
||||
|
||||
;;(define-extern load-dir object) ;; unknown type
|
||||
;;(define-extern external-art-buffer object) ;; unknown type
|
||||
;;(define-extern load-dir-art-group object) ;; unknown type
|
||||
|
@ -32085,7 +32109,7 @@
|
|||
;;(define-extern *display-strip-lines* object) ;; unknown type
|
||||
;;(define-extern *display-process-anim* object) ;; unknown type
|
||||
;;(define-extern *display-actor-marks* object) ;; unknown type
|
||||
(define-extern *menu-hook* function)
|
||||
(define-extern *menu-hook* (function none))
|
||||
;;(define-extern *display-load-boundaries* object) ;; unknown type
|
||||
;;(define-extern *display-water-marks* object) ;; unknown type
|
||||
;;(define-extern *artist-flip-visible* object) ;; unknown type
|
||||
|
|
|
@ -574,6 +574,13 @@ if `x` is a match, returns `x` from the function (not shown) immediately.
|
|||
|
||||
The `return-from` form is very rarely used to return from a block, but sometimes used to return from a function.
|
||||
|
||||
## `return`
|
||||
Exit a function early.
|
||||
```lisp
|
||||
(return value)
|
||||
```
|
||||
Has the same behavior as `(return-from #f value)`.
|
||||
|
||||
## `label`
|
||||
Create a named label for `goto` or `goto-when`.
|
||||
```lisp
|
||||
|
@ -1290,7 +1297,16 @@ This code generation is identical to using a `(set! dst src)` form.
|
|||
(.nop.vf)
|
||||
```
|
||||
|
||||
Inserts a `FNOP` assembly instruction, which is fundamentally the same as a `NOP`.
|
||||
Inserts a `FNOP` assembly instruction, which is fundamentally the same as a `NOP`. It is a 2-byte instruction.
|
||||
|
||||
## `.nop` or `(nop!)`
|
||||
```lisp
|
||||
(.nop)
|
||||
;; or
|
||||
(nop!)
|
||||
```
|
||||
|
||||
Inserts a single-byte `nop`.
|
||||
|
||||
## `.lvf`
|
||||
```lisp
|
||||
|
|
|
@ -425,7 +425,8 @@ u64 kopen(u64 fs, u64 name, u64 mode) {
|
|||
file_stream->flags = 0;
|
||||
printf("****** CALL TO kopen() ******\n");
|
||||
char buffer[128];
|
||||
sprintf(buffer, "host:%s", Ptr<String>(name)->data());
|
||||
// sprintf(buffer, "host:%s", Ptr<String>(name)->data());
|
||||
sprintf(buffer, "%s", Ptr<String>(name)->data());
|
||||
if (!strcmp(info(Ptr<Symbol>(mode))->str->data(), "read")) {
|
||||
file_stream->file = sceOpen(buffer, SCE_RDONLY);
|
||||
} else {
|
||||
|
|
|
@ -5,3 +5,133 @@
|
|||
;; name in dgo: main-h
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(define *stats-poly* '#f)
|
||||
(define *stats-memory* '#f)
|
||||
(define *stats-memory-short* '#f)
|
||||
(define *stats-collide* '#f)
|
||||
(define *stats-bsp* '#f)
|
||||
(define *stats-buffer* '#f)
|
||||
(define *stats-target* '#f)
|
||||
(define *stats-dma-test* '#f)
|
||||
(define *artist-all-visible* '#f)
|
||||
(define *artist-flip-visible* '#f)
|
||||
(define *artist-fix-visible* '#f)
|
||||
(define *artist-fix-frustum* '#f)
|
||||
(define *artist-error-spheres* '#f)
|
||||
(define *artist-use-menu-subdiv* '#f)
|
||||
(define *display-profile* '#t)
|
||||
(define *display-sidekick-stats* '#f)
|
||||
(define *display-quad-stats* '#f)
|
||||
(define *display-tri-stats* '#f)
|
||||
(define *display-perf-stats* '#f)
|
||||
(define *display-ground-stats* '#f)
|
||||
(define *display-collision-marks* '#f)
|
||||
(define *display-collide-cache* '#f)
|
||||
(define *display-render-collision* '#f)
|
||||
(define *display-hipri-collision-marks* '#f)
|
||||
(define *display-edge-collision-marks* '#f)
|
||||
(define *display-geo-marks* '#f)
|
||||
(define *display-target-marks* '#f)
|
||||
(define *display-collide-history* 0)
|
||||
(define *display-xyz-axes* '#f)
|
||||
(define *display-cam-collide-history* '#f)
|
||||
(define *record-cam-collide-history* '#f)
|
||||
(define *display-cam-master-marks* '#f)
|
||||
(define *display-cam-other* '#f)
|
||||
(define *display-camera-marks* '#f)
|
||||
(define *camera-no-mip-correction* '#f)
|
||||
(define *display-cam-los-info* '#f)
|
||||
(define *display-cam-los-debug* '#f)
|
||||
(define *display-cam-los-marks* '#f)
|
||||
(define *display-cam-coll-marks* '#f)
|
||||
(define *display-camera-info* '#f)
|
||||
(define *display-camera-old-stats* '#f)
|
||||
(define *display-camera-last-attacker* '#f)
|
||||
(define *display-file-info* '#f)
|
||||
(define *display-actor-marks* '#f)
|
||||
(define *display-ambient-hint-marks* '#f)
|
||||
(define *display-ambient-sound-marks* '#f)
|
||||
(define *display-ambient-poi-marks* '#f)
|
||||
(define *display-ambient-light-marks* '#f)
|
||||
(define *display-ambient-dark-marks* '#f)
|
||||
(define *display-ambient-weather-off-marks* '#f)
|
||||
(define *display-ambient-ocean-off-marks* '#f)
|
||||
(define *display-ambient-ocean-near-off-marks* '#f)
|
||||
(define *display-ambient-music-marks* '#f)
|
||||
(define *display-sprite-info* '#f)
|
||||
(define *display-entity-errors* '#t)
|
||||
(define *display-lights* '#f)
|
||||
(define *display-instance-info* '#f)
|
||||
(define *display-deci-count* '#f)
|
||||
(define *sync-dma* '#f)
|
||||
(define *display-strip-lines* 0)
|
||||
(define *display-nav-marks* '#f)
|
||||
(define *display-path-marks* '#f)
|
||||
(define *display-vol-marks* '#f)
|
||||
(define *display-water-marks* '#f)
|
||||
(define *display-actor-anim* '#f)
|
||||
(define *display-process-anim* '#f)
|
||||
(define *display-actor-vis* '#f)
|
||||
(define *display-actor-graph* '#f)
|
||||
(define *display-level-border* '#f)
|
||||
(define *display-load-boundaries* '#f)
|
||||
(define *display-memcard-info* '#f)
|
||||
(define *display-split-boxes* '#f)
|
||||
(define *display-split-box-info* '#f)
|
||||
(define *display-texture-download* '#f)
|
||||
(define *display-art-control* '#f)
|
||||
(define *display-level-spheres* '#f)
|
||||
(define *time-of-day-effects* '#t)
|
||||
(define *time-of-day-fast* '#t)
|
||||
(define *display-iop-info* '#f)
|
||||
(define *ambient-sound-class* '#t)
|
||||
(define *slow-frame-rate* '#f)
|
||||
(define *weather-off* '#f)
|
||||
(define *debug-pause* '#f)
|
||||
(define *subdivide-draw-mode* 0)
|
||||
(define *ocean-subdivide-draw-mode* 0)
|
||||
|
||||
;; this is a bit of a trick.
|
||||
;; I believe *dproc* is the display process.
|
||||
;; if it is already created and this file is reloaded, we don't want to write over it.
|
||||
;; so we only set it to #f if we think it hasn't been set before.
|
||||
(define-extern *dproc* process)
|
||||
(when (or (not *dproc*)
|
||||
(zero? *dproc*))
|
||||
;; no dproc, safe to write over it.
|
||||
(set! *dproc* #f)
|
||||
)
|
||||
|
||||
(define *run* '#f)
|
||||
(define *teleport* '#f)
|
||||
(define *teleport-count* 0)
|
||||
(define *draw-hook* nothing)
|
||||
(define *debug-hook* nothing)
|
||||
(define *menu-hook* nothing)
|
||||
(define *progress-hook* nothing)
|
||||
(define *dma-timeout-hook* nothing)
|
||||
|
||||
(deftype frame-stats (structure)
|
||||
((field-time uint64 2 :offset-assert 0)
|
||||
(field int32 :offset-assert 16)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x14
|
||||
:flag-assert #x900000014
|
||||
)
|
||||
|
||||
(define *frame-stats* (new 'static 'frame-stats))
|
||||
|
||||
|
||||
(deftype screen-filter (basic)
|
||||
((draw? basic :offset-assert 4)
|
||||
(color uint32 :offset-assert 8)
|
||||
)
|
||||
:method-count-assert 10
|
||||
:size-assert #xc
|
||||
:flag-assert #xa0000000c
|
||||
(:methods
|
||||
(dummy-9 () none 9)
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -5,3 +5,186 @@
|
|||
;; name in dgo: file-io
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; represents a file that can be read/written, similar to FILE* in C.
|
||||
;; NOTE: this is a special type in three ways:
|
||||
;; 1). It is used in the C runtime. This must be kept in sync with kmachine.h's FileStream
|
||||
;; 2). This type is built-in to the compiler (see TypeSystem.cpp, add_builtin_types)
|
||||
;; It must be kept up to date with that definition as well.
|
||||
;; 3). The C runtime constructs this type before anything is loaded. The sizes
|
||||
;; must be kept up to date there as well.
|
||||
(deftype file-stream (basic)
|
||||
((flags uint32 :offset-assert 4)
|
||||
(mode basic :offset-assert 8)
|
||||
(name string :offset-assert 12)
|
||||
(file uint32 :offset-assert 16)
|
||||
)
|
||||
(:methods
|
||||
(new ((allocation symbol) (type-to-make type) (name string) (mode basic)) _type_)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x14
|
||||
:flag-assert #x900000014
|
||||
)
|
||||
|
||||
|
||||
(defmethod new file-stream ((allocation symbol) (type-to-make type) (name string) (mode basic))
|
||||
"Allocate a file-stream and open it."
|
||||
(let ((stream (object-new)))
|
||||
(file-stream-open stream name mode)
|
||||
stream
|
||||
)
|
||||
)
|
||||
|
||||
;; we already have a length method for a file-stream defined in C.
|
||||
;; just store that in the method table.
|
||||
(set! (-> file-stream method-table 4) file-stream-length)
|
||||
|
||||
(defun file-stream-read-string ((stream file-stream) (str string))
|
||||
"Fill a string with data from a file stream.
|
||||
Note: this function does not work."
|
||||
;; makes the length of the string 0.
|
||||
(clear str)
|
||||
;; so this will read nothing.
|
||||
(file-stream-read stream (-> str data) (length str))
|
||||
str
|
||||
)
|
||||
|
||||
|
||||
;; A common file header found in GOAL files.
|
||||
(deftype file-info (basic)
|
||||
((file-type symbol :offset-assert 4)
|
||||
(file-name basic :offset-assert 8)
|
||||
(major-version uint32 :offset-assert 12)
|
||||
(minor-version uint32 :offset-assert 16)
|
||||
(maya-file-name basic :offset-assert 20)
|
||||
(tool-debug basic :offset-assert 24)
|
||||
(mdb-file-name basic :offset-assert 28)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x20
|
||||
:flag-assert #x900000020
|
||||
)
|
||||
|
||||
(defmethod print file-info ((obj file-info))
|
||||
"Print information about a file"
|
||||
(format #t "#<~A ~A :version ~D.~D @ #x~X>"
|
||||
(-> obj type) (-> obj file-name) (-> obj major-version) (-> obj minor-version) obj)
|
||||
obj
|
||||
)
|
||||
|
||||
;; allocate a temporary string
|
||||
(define *file-temp-string* (new 'global 'string 128 (the string #f)))
|
||||
|
||||
|
||||
(defun make-file-name ((kind int) (name string) (art-group-version int))
|
||||
"Make a file name. Similar to MakeFileName in C.
|
||||
Note: file type enum is different between C and GOAL.
|
||||
File versions should match those in versions.h.
|
||||
Uses a single *file-temp-string* buffer, shared with make-vfile-name."
|
||||
|
||||
(clear *file-temp-string*)
|
||||
(cond
|
||||
((= kind 3)
|
||||
(format *file-temp-string* "texture-page~D/dir-tpages" 7))
|
||||
((= kind 2)
|
||||
(format *file-temp-string* "texture-page~D/tpage-~S" 7 name))
|
||||
((zero? kind)
|
||||
(format *file-temp-string* "level~D/~S-bt" 30 name))
|
||||
((= kind 5)
|
||||
(format *file-temp-string* "res~D/~S-tx" 1 name))
|
||||
((= kind 4)
|
||||
(format *file-temp-string* "level~D/~S-vs" 30 name))
|
||||
((= kind 6)
|
||||
(format *file-temp-string* "~S.VIS" name))
|
||||
((= kind 1)
|
||||
(format *file-temp-string* "art-group~D/~S-ag"
|
||||
(if (> art-group-version 0) art-group-version 6)
|
||||
name
|
||||
)
|
||||
)
|
||||
)
|
||||
*file-temp-string*
|
||||
)
|
||||
|
||||
|
||||
|
||||
(defun make-vfile-name ((a0-0 int) (a1-0 string))
|
||||
"Make another type of file name."
|
||||
(local-vars
|
||||
(s5-0 int)
|
||||
(gp-0 string)
|
||||
)
|
||||
(set! s5-0 a0-0)
|
||||
(set! gp-0 a1-0)
|
||||
(clear *file-temp-string*)
|
||||
(cond
|
||||
((zero? s5-0) (format *file-temp-string* "$LEVEL/~S" gp-0))
|
||||
((= s5-0 1) (format *file-temp-string* "$ART_GROUP/~S" gp-0))
|
||||
)
|
||||
*file-temp-string*
|
||||
)
|
||||
|
||||
(defun file-info-correct-version? ((info file-info) (kind int) (version int))
|
||||
"Check if the file info is valid. If you call this with version = 0,
|
||||
it will pick the right version for the kind automatically."
|
||||
(local-vars
|
||||
(v1-0 int)
|
||||
(v1-1 int)
|
||||
(expected-kind string)
|
||||
(expected-version int)
|
||||
)
|
||||
|
||||
;; figure out the expected major version
|
||||
(set! expected-version
|
||||
(cond
|
||||
((zero? version) ;; version not specified.
|
||||
(set! v1-0 kind)
|
||||
(cond
|
||||
((or (zero? (+ v1-0 -2)) (zero? (+ v1-0 -3))) 7) ;; textures.
|
||||
((zero? v1-0) 30) ;; level
|
||||
((= v1-0 1) 6) ;; art-group
|
||||
)
|
||||
)
|
||||
(else version) ;; version was specified
|
||||
)
|
||||
)
|
||||
|
||||
;; figure out the expected kind
|
||||
(set! expected-kind
|
||||
(begin
|
||||
(set! v1-1 kind)
|
||||
(cond ((= v1-1 2) "texture-page")
|
||||
((zero? v1-1) "bsp-header")
|
||||
((= v1-1 1) "art-group"))
|
||||
)
|
||||
)
|
||||
|
||||
;; check:
|
||||
(cond
|
||||
;; first, check the name is right:
|
||||
;; not clear why we dereference the symbol like this.
|
||||
((not (name= (the-as basic (-> info file-type value)) expected-kind))
|
||||
|
||||
(format 0 "ERROR: file ~A is of type ~S but needs to be ~S.~%"
|
||||
(-> info file-name) (-> info file-type) expected-kind)
|
||||
;; FAIL
|
||||
'#f
|
||||
)
|
||||
|
||||
;; check versions (only major)
|
||||
((!= expected-version (-> info major-version))
|
||||
(format
|
||||
0
|
||||
"ERROR: file ~A is version ~D.~D, but needs to be ~D.x~%"
|
||||
(-> info file-name)
|
||||
(-> info major-version)
|
||||
(-> info minor-version)
|
||||
expected-version
|
||||
)
|
||||
'#f
|
||||
)
|
||||
|
||||
;; both tests pass!
|
||||
(else '#t)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -302,7 +302,9 @@
|
|||
)
|
||||
)
|
||||
|
||||
;; TODO - these work but aren't very efficient.
|
||||
(defmacro return (val)
|
||||
`(return-from #f ,val)
|
||||
)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -126,10 +126,11 @@
|
|||
;; install-handler
|
||||
;; install-debug-handler
|
||||
;; file-stream-open
|
||||
(define-extern file-stream-open (function file-stream basic basic file-stream))
|
||||
;; file-stream-close
|
||||
;; file-stream-length
|
||||
(define-extern file-stream-length (function file-stream int))
|
||||
;; file-stream-seek
|
||||
;; file-stream-read
|
||||
(define-extern file-stream-read (function file-stream pointer int int))
|
||||
;; file-stream-write
|
||||
;; scf-get-language
|
||||
;; scf-get-time
|
||||
|
|
|
@ -389,9 +389,67 @@
|
|||
)
|
||||
)
|
||||
|
||||
;; todo
|
||||
;; nassoc
|
||||
;; nassce
|
||||
(defun nassoc ((a0-0 string) (a1-0 object))
|
||||
(local-vars
|
||||
(v0-2 object)
|
||||
(v1-1 object)
|
||||
(v1-3 symbol)
|
||||
(a1-1 object)
|
||||
(s5-0 string)
|
||||
(gp-0 object)
|
||||
)
|
||||
(begin
|
||||
(set! s5-0 a0-0)
|
||||
(set! gp-0 a1-0)
|
||||
(while
|
||||
(not
|
||||
(or
|
||||
(= gp-0 '())
|
||||
(begin
|
||||
(set! a1-1 (car (car gp-0)))
|
||||
(if (pair? a1-1) (nmember s5-0 a1-1) (name= (the basic a1-1) s5-0))
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! gp-0 (cdr gp-0))
|
||||
)
|
||||
(set! v1-3 '#f)
|
||||
(if (!= gp-0 '()) (car gp-0))
|
||||
)
|
||||
)
|
||||
|
||||
(defun nassoce ((a0-0 string) (a1-0 object))
|
||||
(local-vars
|
||||
(v0-2 object)
|
||||
(v1-1 object)
|
||||
(v1-4 symbol)
|
||||
(s4-0 object)
|
||||
(s5-0 string)
|
||||
(gp-0 object)
|
||||
)
|
||||
(begin
|
||||
(set! s5-0 a0-0)
|
||||
(set! gp-0 a1-0)
|
||||
(while
|
||||
(not
|
||||
(or
|
||||
(= gp-0 '())
|
||||
(begin
|
||||
(set! s4-0 (car (car gp-0)))
|
||||
(if
|
||||
(pair? s4-0)
|
||||
(nmember s5-0 s4-0)
|
||||
(or (name= (the basic s4-0) s5-0) (= s4-0 'else))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set! gp-0 (cdr gp-0))
|
||||
)
|
||||
(set! v1-4 '#f)
|
||||
(if (!= gp-0 '()) (car gp-0))
|
||||
)
|
||||
)
|
||||
|
||||
(defun append! ((front object) (back object))
|
||||
"Append back to front."
|
||||
|
@ -605,7 +663,7 @@
|
|||
dst
|
||||
)
|
||||
|
||||
(defun mem-set32! ((dst pointer) (value int) (n int))
|
||||
(defun mem-set32! ((dst pointer) (n int) (value int))
|
||||
"Memset a 32-bit value n times. Total memory filled is 4 * n bytes."
|
||||
(let ((p (the pointer dst))
|
||||
(i 0))
|
||||
|
|
|
@ -85,7 +85,11 @@
|
|||
;; cat-string<-string_to_charp
|
||||
;; append-character-to-string
|
||||
;; charp-basename
|
||||
;; clear
|
||||
|
||||
(defun clear ((a0-0 string))
|
||||
(set! (-> a0-0 data 0) 0) a0-0
|
||||
)
|
||||
|
||||
;; string<?
|
||||
;; string>?
|
||||
;; string<=?
|
||||
|
|
|
@ -338,6 +338,7 @@ class Compiler {
|
|||
Val* compile_return_from(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_label(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_goto(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_nop(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
||||
// CompilerControl
|
||||
Val* compile_seval(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
|
|
@ -1023,6 +1023,26 @@ void IR_GetStackAddr::do_codegen(emitter::ObjectGenerator* gen,
|
|||
}
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
// Nop
|
||||
///////////////////////
|
||||
|
||||
IR_Nop::IR_Nop() {}
|
||||
|
||||
std::string IR_Nop::print() {
|
||||
return fmt::format("nop");
|
||||
}
|
||||
|
||||
RegAllocInstr IR_Nop::to_rai() {
|
||||
return {};
|
||||
}
|
||||
|
||||
void IR_Nop::do_codegen(emitter::ObjectGenerator* gen,
|
||||
const AllocationResult&,
|
||||
emitter::IR_Record irec) {
|
||||
gen->add_instr(IGen::nop(), irec);
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
// Asm
|
||||
///////////////////////
|
||||
|
|
|
@ -340,6 +340,16 @@ class IR_GetStackAddr : public IR {
|
|||
int m_slot = -1;
|
||||
};
|
||||
|
||||
class IR_Nop : public IR {
|
||||
public:
|
||||
IR_Nop();
|
||||
std::string print() override;
|
||||
RegAllocInstr to_rai() override;
|
||||
void do_codegen(emitter::ObjectGenerator* gen,
|
||||
const AllocationResult& allocs,
|
||||
emitter::IR_Record irec) override;
|
||||
};
|
||||
|
||||
class IR_Asm : public IR {
|
||||
public:
|
||||
explicit IR_Asm(bool use_coloring);
|
||||
|
|
|
@ -26,6 +26,7 @@ static const std::unordered_map<
|
|||
|
||||
// INLINE ASM - VECTOR FLOAT OPERATIONS
|
||||
{".nop.vf", &Compiler::compile_asm_nop_vf},
|
||||
{".nop", &Compiler::compile_nop},
|
||||
{".lvf", &Compiler::compile_asm_lvf},
|
||||
{".svf", &Compiler::compile_asm_svf},
|
||||
{".xor.vf", &Compiler::compile_asm_xor_vf},
|
||||
|
@ -70,6 +71,7 @@ static const std::unordered_map<
|
|||
{"return-from", &Compiler::compile_return_from},
|
||||
{"label", &Compiler::compile_label},
|
||||
{"goto", &Compiler::compile_goto},
|
||||
{"nop!", &Compiler::compile_nop},
|
||||
|
||||
// COMPILER CONTROL
|
||||
{"gs", &Compiler::compile_gs},
|
||||
|
|
|
@ -185,4 +185,11 @@ Val* Compiler::compile_goto(const goos::Object& form, const goos::Object& rest,
|
|||
get_parent_env_of_type<FunctionEnv>(env)->unresolved_gotos.push_back({ir_goto.get(), label_name});
|
||||
env->emit(std::move(ir_goto));
|
||||
return get_none();
|
||||
}
|
||||
|
||||
Val* Compiler::compile_nop(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
auto args = get_va(form, rest);
|
||||
va_check(form, args, {}, {});
|
||||
env->emit_ir<IR_Nop>();
|
||||
return get_none();
|
||||
}
|
|
@ -2009,6 +2009,12 @@ class IGen {
|
|||
return instr;
|
||||
}
|
||||
|
||||
static Instruction nop() {
|
||||
// NOP
|
||||
Instruction instr(0x90);
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction nop_vf() {
|
||||
// FNOP
|
||||
Instruction instr(0xd9);
|
||||
|
|
|
@ -234,7 +234,7 @@ TEST_F(FormRegressionTest, WhileLoop) {
|
|||
" (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n"
|
||||
" (if\n"
|
||||
" (= v1-0 a1-0)\n"
|
||||
" (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)) (set! v1-0 0))\n"
|
||||
" (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)))\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" (set! v0-0 '#f)\n"
|
||||
|
@ -300,7 +300,7 @@ TEST_F(FormRegressionTest, Or) {
|
|||
" )\n"
|
||||
" (if\n"
|
||||
" (= a0-0 a1-0)\n"
|
||||
" (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)) (set! v1-0 0))\n"
|
||||
" (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)))\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" (set! v0-0 '#f)\n"
|
||||
|
@ -365,9 +365,9 @@ TEST_F(FormRegressionTest, DynamicMethodAccess) {
|
|||
" (if\n"
|
||||
" (begin\n"
|
||||
" (if\n"
|
||||
" (begin (set! a2-0 object) (= a0-0 a2-0))\n" // if we reached the top
|
||||
" (return (begin (set! v1-3 nothing) (set! v0-0 v1-3)) (set! v1-2 0))\n" // return
|
||||
// nothing.
|
||||
" (begin (set! a2-0 object) (= a0-0 a2-0))\n" // if we reached the top
|
||||
" (return (begin (set! v1-3 nothing) (set! v0-0 v1-3)))\n" // return
|
||||
// nothing.
|
||||
" )\n"
|
||||
" (set! a0-0 (-> a0-0 parent))\n" // get next parent type
|
||||
" (set! a2-2 (sll a1-0 2))\n" // fancy access
|
||||
|
@ -376,9 +376,9 @@ TEST_F(FormRegressionTest, DynamicMethodAccess) {
|
|||
// condition)
|
||||
" (zero? v0-0)\n" // is it defined?
|
||||
" )\n"
|
||||
" (return (begin (set! v1-4 nothing) (set! v0-0 v1-4)) (set! v1-2 0))\n" // also
|
||||
// return
|
||||
// nothing.
|
||||
" (return (begin (set! v1-4 nothing) (set! v0-0 v1-4)))\n" // also
|
||||
// return
|
||||
// nothing.
|
||||
" )\n"
|
||||
" )\n"
|
||||
" (set! v1-5 '#f)\n"
|
||||
|
@ -887,7 +887,7 @@ TEST_F(FormRegressionTest, TypeOf) {
|
|||
std::string type = "(function object object)";
|
||||
std::string expected =
|
||||
"(begin\n"
|
||||
" (set! v1-1 (type-of a0-0))\n"
|
||||
" (set! v1-1 (rtype-of a0-0))\n"
|
||||
" (set! t9-0 (-> v1-1 methods-by-name print))\n" // print method.
|
||||
" (set! v0-0 (call! a0-0))\n"
|
||||
" (ret-value v0-0)\n"
|
||||
|
|
|
@ -461,7 +461,7 @@ TEST_F(FormRegressionTest, ExprBasicTypeP) {
|
|||
// don't plan on supporting this.
|
||||
" (if\n"
|
||||
" (= v1-0 a1-0)\n"
|
||||
" (return '#t (set! v1-0 0))\n"
|
||||
" (return '#t)\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" '#f\n"
|
||||
|
@ -507,7 +507,7 @@ TEST_F(FormRegressionTest, FinalBasicTypeP) {
|
|||
" (set! a0-1 object)\n"
|
||||
" (until\n"
|
||||
" (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n"
|
||||
" (if (= v1-0 a1-0) (return (quote #t) (set! v1-0 0)))\n"
|
||||
" (if (= v1-0 a1-0) (return (quote #t)))\n"
|
||||
" )\n"
|
||||
" (quote #f)\n"
|
||||
" )\n"
|
||||
|
@ -562,7 +562,7 @@ TEST_F(FormRegressionTest, ExprTypeTypep) {
|
|||
" (set! a0-0 (-> a0-0 parent))\n"
|
||||
" (or (= a0-0 v1-0) (zero? a0-0))\n"
|
||||
" )\n"
|
||||
" (if (= a0-0 a1-0) (return '#t (set! v1-0 0)))\n"
|
||||
" (if (= a0-0 a1-0) (return '#t))\n"
|
||||
" )\n"
|
||||
" '#f\n"
|
||||
" )";
|
||||
|
@ -618,13 +618,13 @@ TEST_F(FormRegressionTest, ExprFindParentMethod) {
|
|||
|
||||
std::string expected =
|
||||
"(begin\n"
|
||||
" (set! v1-2 (-> a0-0 methods a1-0))\n"
|
||||
" (set! v1-2 (-> a0-0 method-table a1-0))\n"
|
||||
" (until\n"
|
||||
" (!= v0-0 v1-2)\n"
|
||||
" (if (= a0-0 object) (return nothing (set! v1-2 0)))\n"
|
||||
" (if (= a0-0 object) (return nothing))\n"
|
||||
" (set! a0-0 (-> a0-0 parent))\n"
|
||||
" (set! v0-0 (-> a0-0 methods a1-0))\n"
|
||||
" (if (zero? v0-0) (return nothing (set! v1-2 0)))\n"
|
||||
" (set! v0-0 (-> a0-0 method-table a1-0))\n"
|
||||
" (if (zero? v0-0) (return nothing))\n"
|
||||
" )\n"
|
||||
" (set! v1-5 '#f)\n"
|
||||
" v0-0\n"
|
||||
|
@ -902,7 +902,7 @@ TEST_F(FormRegressionTest, ExprNmember) {
|
|||
" (set! s5-0 a0-0)\n"
|
||||
" (set! gp-0 a1-0)\n"
|
||||
" (while\n"
|
||||
" (not (or (= gp-0 '()) (name= (car gp-0) s5-0)))\n"
|
||||
" (not (or (= gp-0 '()) (name= (the-as basic (car gp-0)) s5-0)))\n"
|
||||
" (set! gp-0 (cdr gp-0))\n"
|
||||
" )\n"
|
||||
" (set! v1-2 '#f)\n"
|
||||
|
@ -1110,7 +1110,11 @@ TEST_F(FormRegressionTest, ExprNassoc) {
|
|||
" (= gp-0 (quote ()))\n"
|
||||
" (begin\n"
|
||||
" (set! a1-1 (car (car gp-0)))\n"
|
||||
" (if (pair? a1-1) (nmember s5-0 a1-1) (name= a1-1 s5-0))\n"
|
||||
" (if "
|
||||
" (pair? a1-1)\n"
|
||||
" (nmember (the-as basic s5-0) a1-1)\n"
|
||||
" (name= (the-as basic a1-1) (the-as basic s5-0))"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
|
@ -1213,8 +1217,11 @@ TEST_F(FormRegressionTest, ExprNassoce) {
|
|||
" (set! s4-0 (car (car gp-0)))\n"
|
||||
" (if\n"
|
||||
" (pair? s4-0)\n"
|
||||
" (nmember s5-0 s4-0)\n"
|
||||
" (or (name= s4-0 s5-0) (= s4-0 (quote else)))\n"
|
||||
" (nmember (the-as basic s5-0) s4-0)\n"
|
||||
" (or\n"
|
||||
" (name= (the-as basic s4-0) (the-as basic s5-0))\n"
|
||||
" (= s4-0 (quote else))\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
|
@ -2063,7 +2070,7 @@ TEST_F(FormRegressionTest, ExprPrint) {
|
|||
" daddiu sp, sp, 16";
|
||||
std::string type = "(function object object)";
|
||||
|
||||
std::string expected = "((method-of-type (type-of a0-0) print) a0-0)";
|
||||
std::string expected = "((method-of-type (rtype-of a0-0) print) a0-0)";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
|
@ -2112,7 +2119,7 @@ TEST_F(FormRegressionTest, ExprPrintl) {
|
|||
"(begin\n"
|
||||
" (set! gp-0 a0-0)\n"
|
||||
" (set! a0-1 gp-0)\n"
|
||||
" (set! v1-2 ((method-of-type (type-of a0-1) print) a0-1))\n"
|
||||
" (set! v1-2 ((method-of-type (rtype-of a0-1) print) a0-1))\n"
|
||||
" (format (quote #t) L324)\n"
|
||||
" gp-0\n"
|
||||
" )";
|
||||
|
@ -2143,7 +2150,7 @@ TEST_F(FormRegressionTest, ExprInspect) {
|
|||
" daddiu sp, sp, 16";
|
||||
std::string type = "(function object object)";
|
||||
|
||||
std::string expected = "((method-of-type (type-of a0-0) inspect) a0-0)";
|
||||
std::string expected = "((method-of-type (rtype-of a0-0) inspect) a0-0)";
|
||||
test_with_expr(func, type, expected);
|
||||
}
|
||||
|
||||
|
@ -2334,13 +2341,13 @@ TEST_F(FormRegressionTest, ExprPrintName) {
|
|||
"(cond\n"
|
||||
" ((= a0-0 a1-0) (quote #t))\n"
|
||||
" ((and (= (-> a0-0 type) string) (= (-> a1-0 type) string))\n"
|
||||
" (string= a0-0 a1-0)\n"
|
||||
" (string= (the-as string a0-0) (the-as string a1-0))\n"
|
||||
" )\n"
|
||||
" ((and (= (-> a0-0 type) string) (= (-> a1-0 type) symbol))\n"
|
||||
" (string= a0-0 (-> (+ 65336 (the-as int a1-0)) 0))\n"
|
||||
" (string= (the-as string a0-0) (-> (+ 65336 (the-as int a1-0)) 0))\n"
|
||||
" )\n"
|
||||
" ((and (= (-> a1-0 type) string) (= (-> a0-0 type) symbol))\n"
|
||||
" (string= a1-0 (-> (+ 65336 (the-as int a0-0)) 0))\n"
|
||||
" (string= (the-as string a1-0) (-> (+ 65336 (the-as int a0-0)) 0))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
|
|
|
@ -2002,8 +2002,8 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||
" (if s4-0 (set! v1-24 (format s5-0 L318 gp-0 s4-0 s3-0)))\n"
|
||||
" (quote #f)\n"
|
||||
" )\n"
|
||||
" ((and (= s3-0 type) (!= (type-of gp-0) type))\n"
|
||||
" (if s4-0 (set! v1-31 (format s5-0 L317 gp-0 s4-0 s3-0 (type-of gp-0))))\n"
|
||||
" ((and (= s3-0 type) (!= (rtype-of gp-0) type))\n"
|
||||
" (if s4-0 (set! v1-31 (format s5-0 L317 gp-0 s4-0 s3-0 (rtype-of gp-0))))\n"
|
||||
" (quote #f)\n"
|
||||
" )\n"
|
||||
" (else\n"
|
||||
|
@ -2011,16 +2011,16 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||
" v1-33\n"
|
||||
" (and\n"
|
||||
" (!= s3-0 type)\n"
|
||||
" (not (valid? (type-of gp-0) type (quote #f) (quote #t) 0))\n"
|
||||
" (not (valid? (rtype-of gp-0) type (quote #f) (quote #t) 0))\n"
|
||||
" )\n"
|
||||
" )\n"
|
||||
" (cond\n"
|
||||
" (v1-33\n"
|
||||
" (if s4-0 (set! v1-37 (format s5-0 L317 gp-0 s4-0 s3-0 (type-of gp-0))))\n"
|
||||
" (if s4-0 (set! v1-37 (format s5-0 L317 gp-0 s4-0 s3-0 (rtype-of gp-0))))\n"
|
||||
" (quote #f)\n"
|
||||
" )\n"
|
||||
" ((not (type-type? (type-of gp-0) s3-0))\n"
|
||||
" (if s4-0 (set! v1-41 (format s5-0 L316 gp-0 s4-0 s3-0 (type-of gp-0))))\n"
|
||||
" ((not (type-type? (rtype-of gp-0) s3-0))\n"
|
||||
" (if s4-0 (set! v1-41 (format s5-0 L316 gp-0 s4-0 s3-0 (rtype-of gp-0))))\n"
|
||||
" (quote #f)\n"
|
||||
" )\n"
|
||||
" ((= s3-0 symbol)\n"
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
(let* ((base-addr #x6000000)
|
||||
(word-cnt 23)
|
||||
(base (the (pointer int32) base-addr))
|
||||
(foo (mem-set32! base #x0 (+ 1 word-cnt)))
|
||||
(foo (mem-set32! base (+ 1 word-cnt) #x0))
|
||||
(last-byte (the (pointer uint8) (+ base-addr 3 (* 4 (- word-cnt 1)))))
|
||||
(dst (mem-set32! base #x0badbeef word-cnt))
|
||||
(dst (mem-set32! base word-cnt #x0badbeef))
|
||||
)
|
||||
|
||||
(if (!= dst base)
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
(set! (-> b x) 2.)
|
||||
(set! (-> b y) 3.)
|
||||
(set! (-> b z) 4.)
|
||||
(.nop)
|
||||
(nop!)
|
||||
(expect-true (= 20.0 (vector-dot-vu a b)))
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue