mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -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?
|
* 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.mem_deref);
|
||||||
assert(expected.can_deref);
|
assert(expected.can_deref);
|
||||||
if (actual.is_store || actual.size >= 8 || !is_integer) {
|
if (actual.is_store || actual.size >= 8 || !is_integer) {
|
||||||
// don't check sign extension
|
// don't check sign extension
|
||||||
return expected.load_size == actual.size;
|
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 {
|
} else {
|
||||||
return expected.load_size == actual.size && expected.sign_extend == actual.sign_extend;
|
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);
|
auto di = get_deref_info(input.base_type);
|
||||||
bool is_integer =
|
bool is_integer =
|
||||||
typecheck(TypeSpec("integer"), input.base_type.get_single_arg(), "", false, false);
|
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.
|
assert(di.mem_deref); // it's accessing a pointer.
|
||||||
auto elt_type = di.result_type;
|
auto elt_type = di.result_type;
|
||||||
if (input.stride) {
|
if (input.stride) {
|
||||||
|
@ -123,7 +130,7 @@ bool TypeSystem::try_reverse_lookup_pointer(const FieldReverseLookupInput& input
|
||||||
token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
|
token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
|
||||||
path->push_back(token);
|
path->push_back(token);
|
||||||
if (input.deref.has_value()) {
|
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
|
// access element of array
|
||||||
*addr_of = false;
|
*addr_of = false;
|
||||||
*result_type = elt_type;
|
*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.kind = FieldReverseLookupOutput::Token::Kind::CONSTANT_IDX;
|
||||||
token.idx = elt_idx;
|
token.idx = elt_idx;
|
||||||
if (input.deref.has_value()) {
|
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
|
// this isn't the right type of dereference
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -200,6 +207,7 @@ bool TypeSystem::try_reverse_lookup_array(const FieldReverseLookupInput& input,
|
||||||
auto di = get_deref_info(array_data_type);
|
auto di = get_deref_info(array_data_type);
|
||||||
bool is_integer =
|
bool is_integer =
|
||||||
typecheck(TypeSpec("integer"), input.base_type.get_single_arg(), "", false, false);
|
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.
|
assert(di.mem_deref); // it's accessing a pointer.
|
||||||
auto elt_type = di.result_type;
|
auto elt_type = di.result_type;
|
||||||
if (input.stride) {
|
if (input.stride) {
|
||||||
|
@ -218,7 +226,7 @@ bool TypeSystem::try_reverse_lookup_array(const FieldReverseLookupInput& input,
|
||||||
token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
|
token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
|
||||||
path->push_back(token);
|
path->push_back(token);
|
||||||
if (input.deref.has_value()) {
|
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
|
// access element of array
|
||||||
*addr_of = false;
|
*addr_of = false;
|
||||||
*result_type = elt_type;
|
*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.
|
// always put array index, even if it's zero.
|
||||||
path->push_back(token);
|
path->push_back(token);
|
||||||
if (input.deref.has_value()) {
|
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
|
// this isn't the right type of dereference
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +399,8 @@ bool TypeSystem::try_reverse_lookup_other(const FieldReverseLookupInput& input,
|
||||||
TypeSpec loc_type = make_pointer_typespec(field_deref.type);
|
TypeSpec loc_type = make_pointer_typespec(field_deref.type);
|
||||||
auto di = get_deref_info(loc_type);
|
auto di = get_deref_info(loc_type);
|
||||||
bool is_integer = typecheck(TypeSpec("integer"), field_deref.type, "", false, false);
|
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!
|
continue; // try another field!
|
||||||
}
|
}
|
||||||
// it's a match, just access the field like normal!
|
// 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"));
|
add_field_to_type(connectable_type, "prev1", make_typespec("connectable"));
|
||||||
|
|
||||||
// todo
|
// 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,
|
const Env& env,
|
||||||
DecompilerTypeSystem& dts) override;
|
DecompilerTypeSystem& dts) override;
|
||||||
void collect_vars(VariableSet& vars) const override;
|
void collect_vars(VariableSet& vars) const override;
|
||||||
|
const Instruction& instruction() const { return m_instr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Instruction m_instr;
|
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 {
|
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 {
|
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) {
|
} else if ((label.offset & 7) == PAIR_OFFSET) {
|
||||||
return TP_Type::make_from_ts(TypeSpec("pair"));
|
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:
|
case Kind::INVALID:
|
||||||
default:
|
default:
|
||||||
|
@ -136,6 +138,12 @@ TP_Type SimpleExpression::get_type(const TypeState& input,
|
||||||
}
|
}
|
||||||
case Kind::FPR_TO_GPR:
|
case Kind::FPR_TO_GPR:
|
||||||
case Kind::DIV_S:
|
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");
|
return TP_Type::make_from_ts("float");
|
||||||
case Kind::ADD:
|
case Kind::ADD:
|
||||||
case Kind::SUB:
|
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
|
// ConditionElement
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
@ -474,29 +504,38 @@ goos::Object ReturnElement::to_form(const Env& env) const {
|
||||||
std::vector<goos::Object> forms;
|
std::vector<goos::Object> forms;
|
||||||
forms.push_back(pretty_print::to_symbol("return"));
|
forms.push_back(pretty_print::to_symbol("return"));
|
||||||
forms.push_back(return_code->to_form(env));
|
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);
|
return pretty_print::build_list(forms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReturnElement::apply(const std::function<void(FormElement*)>& f) {
|
void ReturnElement::apply(const std::function<void(FormElement*)>& f) {
|
||||||
f(this);
|
f(this);
|
||||||
return_code->apply(f);
|
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) {
|
void ReturnElement::apply_form(const std::function<void(Form*)>& f) {
|
||||||
return_code->apply_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 {
|
void ReturnElement::collect_vars(VariableSet& vars) const {
|
||||||
return_code->collect_vars(vars);
|
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 {
|
void ReturnElement::get_modified_regs(RegSet& regs) const {
|
||||||
for (auto x : {return_code, dead_code}) {
|
return_code->get_modified_regs(regs);
|
||||||
x->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 {
|
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) {
|
void TypeOfElement::apply(const std::function<void(FormElement*)>& f) {
|
||||||
|
@ -1048,6 +1087,8 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
|
||||||
return "-";
|
return "-";
|
||||||
case FixedOperatorKind::MULTIPLICATION:
|
case FixedOperatorKind::MULTIPLICATION:
|
||||||
return "*";
|
return "*";
|
||||||
|
case FixedOperatorKind::SQRT:
|
||||||
|
return "sqrt";
|
||||||
case FixedOperatorKind::ARITH_SHIFT:
|
case FixedOperatorKind::ARITH_SHIFT:
|
||||||
return "ash";
|
return "ash";
|
||||||
case FixedOperatorKind::MOD:
|
case FixedOperatorKind::MOD:
|
||||||
|
|
|
@ -84,6 +84,18 @@ class SimpleExpressionElement : public FormElement {
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result,
|
std::vector<FormElement*>* result,
|
||||||
bool allow_side_effects);
|
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,
|
void update_from_stack_add_i(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
|
@ -259,6 +271,24 @@ class AtomicOpElement : public FormElement {
|
||||||
const AtomicOp* m_op;
|
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))
|
* 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)).
|
||||||
|
@ -344,6 +374,8 @@ class BranchElement : public FormElement {
|
||||||
/*!
|
/*!
|
||||||
* Represents a (return-from #f x) form, which immediately returns from the function.
|
* 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".
|
* 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 {
|
class ReturnElement : public FormElement {
|
||||||
public:
|
public:
|
||||||
|
@ -444,6 +476,7 @@ class EmptyElement : public FormElement {
|
||||||
void apply_form(const std::function<void(Form*)>& f) override;
|
void apply_form(const std::function<void(Form*)>& f) override;
|
||||||
void collect_vars(VariableSet& vars) const override;
|
void collect_vars(VariableSet& vars) const override;
|
||||||
void get_modified_regs(RegSet& regs) 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 apply_form(const std::function<void(Form*)>& f) override;
|
||||||
void collect_vars(VariableSet& vars) const override;
|
void collect_vars(VariableSet& vars) const override;
|
||||||
void get_modified_regs(RegSet& regs) 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);
|
std::string fixed_operator_to_string(FixedOperatorKind kind);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "FormStack.h"
|
#include "FormStack.h"
|
||||||
#include "GenericElementMatcher.h"
|
#include "GenericElementMatcher.h"
|
||||||
#include "common/goos/PrettyPrinter.h"
|
#include "common/goos/PrettyPrinter.h"
|
||||||
|
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO
|
* 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,
|
void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
|
@ -546,6 +583,30 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
|
||||||
case SimpleExpression::Kind::DIV_S:
|
case SimpleExpression::Kind::DIV_S:
|
||||||
update_from_stack_div_s(env, pool, stack, result, allow_side_effects);
|
update_from_stack_div_s(env, pool, stack, result, allow_side_effects);
|
||||||
break;
|
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:
|
case SimpleExpression::Kind::ADD:
|
||||||
update_from_stack_add_i(env, pool, stack, result, allow_side_effects);
|
update_from_stack_add_i(env, pool, stack, result, allow_side_effects);
|
||||||
break;
|
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);
|
auto unstacked = pop_to_forms(all_pop_vars, env, pool, stack, allow_side_effects);
|
||||||
std::vector<Form*> arg_forms;
|
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>(
|
auto new_form = pool.alloc_element<GenericElement>(
|
||||||
GenericOperator::make_function(unstacked.at(0)), arg_forms);
|
GenericOperator::make_function(unstacked.at(0)), arg_forms);
|
||||||
|
|
||||||
|
@ -1161,6 +1244,36 @@ FormElement* ConditionElement::make_generic(const Env&,
|
||||||
casted);
|
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:
|
default:
|
||||||
throw std::runtime_error("ConditionElement::make_generic NYI for kind " +
|
throw std::runtime_error("ConditionElement::make_generic NYI for kind " +
|
||||||
get_condition_kind_name(m_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));
|
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,
|
void GenericElement::update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
|
@ -1305,7 +1422,7 @@ void DynamicMethodAccess::update_from_stack(const Env& env,
|
||||||
|
|
||||||
auto deref = pool.alloc_element<DerefElement>(
|
auto deref = pool.alloc_element<DerefElement>(
|
||||||
var_to_form(base.value(), pool), false,
|
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))});
|
DerefToken::make_int_expr(var_to_form(idx.value(), pool))});
|
||||||
result->push_back(deref);
|
result->push_back(deref);
|
||||||
}
|
}
|
||||||
|
@ -1450,4 +1567,16 @@ void TypeOfElement::update_from_stack(const Env& env,
|
||||||
result->push_back(this);
|
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
|
} // namespace decompiler
|
||||||
|
|
|
@ -95,6 +95,7 @@ enum class FixedOperatorKind {
|
||||||
ADDITION,
|
ADDITION,
|
||||||
SUBTRACTION,
|
SUBTRACTION,
|
||||||
MULTIPLICATION,
|
MULTIPLICATION,
|
||||||
|
SQRT,
|
||||||
ARITH_SHIFT,
|
ARITH_SHIFT,
|
||||||
MOD,
|
MOD,
|
||||||
ABS,
|
ABS,
|
||||||
|
@ -125,9 +126,15 @@ enum class FixedOperatorKind {
|
||||||
struct VariableNames {
|
struct VariableNames {
|
||||||
struct VarInfo {
|
struct VarInfo {
|
||||||
VarInfo() = default;
|
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;
|
TP_Type type;
|
||||||
RegId reg_id;
|
RegId reg_id;
|
||||||
|
std::string override_name;
|
||||||
bool initialized = false;
|
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)
|
* 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;
|
return result;
|
||||||
} else if (dynamic_cast<const GotoEnd*>(vtx)) {
|
} else if (dynamic_cast<const GotoEnd*>(vtx)) {
|
||||||
auto* cvtx = 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>(
|
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()));
|
clean_up_return(pool, dynamic_cast<ReturnElement*>(result->try_as_single_element()));
|
||||||
return result;
|
return result;
|
||||||
} else if (dynamic_cast<const Break*>(vtx)) {
|
} else if (dynamic_cast<const Break*>(vtx)) {
|
||||||
|
@ -1433,6 +1471,11 @@ void build_initial_forms(Function& function) {
|
||||||
if (as_cne) {
|
if (as_cne) {
|
||||||
clean_up_cond_no_else_final(function, 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;
|
function.ir2.top_form = result;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
namespace decompiler {
|
namespace decompiler {
|
||||||
|
|
||||||
// TODO - remove all these and put them in the analysis methods instead.
|
// 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;
|
bool changed = true;
|
||||||
while (changed) {
|
while (changed) {
|
||||||
changed = false;
|
changed = false;
|
||||||
|
@ -30,6 +30,9 @@ void clean_up_ifs(Form* top_level_form) {
|
||||||
assert(me != parent_vector.end());
|
assert(me != parent_vector.end());
|
||||||
|
|
||||||
// now insert the fake condition
|
// 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());
|
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
|
||||||
top_condition->elts() = {real_condition};
|
top_condition->elts() = {real_condition};
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -54,6 +57,9 @@ void clean_up_ifs(Form* top_level_form) {
|
||||||
assert(me != parent_vector.end());
|
assert(me != parent_vector.end());
|
||||||
|
|
||||||
// now insert the fake condition
|
// 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());
|
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
|
||||||
top_condition->elts() = {real_condition};
|
top_condition->elts() = {real_condition};
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -81,6 +87,9 @@ void clean_up_ifs(Form* top_level_form) {
|
||||||
assert(me != parent_vector.end());
|
assert(me != parent_vector.end());
|
||||||
|
|
||||||
// now insert the fake condition
|
// 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());
|
parent_vector.insert(me, top_condition->elts().begin(), top_condition->elts().end());
|
||||||
top_condition->elts() = {real_condition};
|
top_condition->elts() = {real_condition};
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -153,7 +162,7 @@ bool convert_to_expressions(Form* top_level_form,
|
||||||
// fmt::print("Before clean:\n{}\n",
|
// fmt::print("Before clean:\n{}\n",
|
||||||
// pretty_print::to_string(top_level_form->to_form(f.ir2.env)));
|
// pretty_print::to_string(top_level_form->to_form(f.ir2.env)));
|
||||||
// fix up stuff
|
// fix up stuff
|
||||||
clean_up_ifs(top_level_form);
|
clean_up_ifs(top_level_form, f.ir2.env);
|
||||||
|
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
std::string warning = fmt::format("Expression building failed: {}", e.what());
|
std::string warning = fmt::format("Expression building failed: {}", e.what());
|
||||||
|
|
|
@ -56,6 +56,10 @@
|
||||||
(define-extern *enable-method-set* int)
|
(define-extern *enable-method-set* int)
|
||||||
(define-extern install-debug-handler (function int object symbol))
|
(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 ;;;;;;;;;;;;;;;;;;;
|
;;;; GCOMMON ;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -740,6 +744,7 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||||
|
|
||||||
|
|
||||||
(deftype bit-array (basic)
|
(deftype bit-array (basic)
|
||||||
((length int32 :offset-assert 4)
|
((length int32 :offset-assert 4)
|
||||||
(allocated-length int32 :offset-assert 8)
|
(allocated-length int32 :offset-assert 8)
|
||||||
|
@ -914,7 +919,8 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
(deftype vector (structure)
|
(deftype vector (structure)
|
||||||
((data float 4 :offset-assert 0)
|
(
|
||||||
|
(data float 4 :offset-assert 0)
|
||||||
(x float :offset 0)
|
(x float :offset 0)
|
||||||
(y float :offset 4)
|
(y float :offset 4)
|
||||||
(z float :offset 8)
|
(z float :offset 8)
|
||||||
|
@ -1793,6 +1799,7 @@
|
||||||
; ;; likely a bitfield type
|
; ;; likely a bitfield type
|
||||||
; )
|
; )
|
||||||
|
|
||||||
|
|
||||||
; ;; dma-h
|
; ;; dma-h
|
||||||
(deftype dma-bucket (structure)
|
(deftype dma-bucket (structure)
|
||||||
((tag uint64 :offset-assert 0)
|
((tag uint64 :offset-assert 0)
|
||||||
|
@ -2219,24 +2226,109 @@
|
||||||
|
|
||||||
(define-extern *display* display)
|
(define-extern *display* display)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||||
;; file-io
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;
|
;;;; VECTOR ;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||||
|
|
||||||
;; todo
|
(define-extern sin (function float float))
|
||||||
; (deftype file-stream (basic)
|
(define-extern cos (function float float))
|
||||||
; ((flags uint32 :offset-assert 4)
|
(define-extern atan (function float float float))
|
||||||
; (mode basic :offset-assert 8)
|
|
||||||
; (name basic :offset-assert 12)
|
(define-extern vector-cross! (function vector vector vector vector))
|
||||||
; (file uint32 :offset-assert 16)
|
(define-extern vector+float! (function vector vector float vector))
|
||||||
; )
|
(define-extern vector*! (function vector vector vector vector))
|
||||||
; :method-count-assert 9
|
(define-extern vector+*! (function vector vector vector float vector))
|
||||||
; :size-assert #x14
|
(define-extern vector-*! (function vector vector vector float vector))
|
||||||
; :flag-assert #x900000014
|
(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)
|
(deftype file-info (basic)
|
||||||
((file-type basic :offset-assert 4)
|
((file-type symbol :offset-assert 4)
|
||||||
(file-name basic :offset-assert 8)
|
(file-name basic :offset-assert 8)
|
||||||
(major-version uint32 :offset-assert 12)
|
(major-version uint32 :offset-assert 12)
|
||||||
(minor-version uint32 :offset-assert 16)
|
(minor-version uint32 :offset-assert 16)
|
||||||
|
@ -2249,6 +2341,12 @@
|
||||||
:flag-assert #x900000020
|
: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
|
;; loader-h
|
||||||
;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;
|
||||||
|
@ -31396,14 +31494,11 @@
|
||||||
(define-extern matrix-translate! function)
|
(define-extern matrix-translate! function)
|
||||||
(define-extern matrix-4x4-inverse! function)
|
(define-extern matrix-4x4-inverse! function)
|
||||||
(define-extern matrix-! function)
|
(define-extern matrix-! function)
|
||||||
(define-extern atan function)
|
|
||||||
(define-extern vector-sincos! function)
|
(define-extern vector-sincos! function)
|
||||||
(define-extern cos function)
|
|
||||||
(define-extern sin function)
|
|
||||||
(define-extern trs-matrix-calc! function)
|
(define-extern trs-matrix-calc! function)
|
||||||
(define-extern transform-matrix-parent-calc! function)
|
(define-extern transform-matrix-parent-calc! function)
|
||||||
(define-extern transform-matrix-calc! function)
|
(define-extern transform-matrix-calc! function)
|
||||||
(define-extern vector-identity! function)
|
|
||||||
(define-extern quaternion-zero! function)
|
(define-extern quaternion-zero! function)
|
||||||
(define-extern quaternion-set! function)
|
(define-extern quaternion-set! function)
|
||||||
(define-extern matrix->quaternion function)
|
(define-extern matrix->quaternion function)
|
||||||
|
@ -31457,15 +31552,15 @@
|
||||||
(define-extern quaternion-i! function)
|
(define-extern quaternion-i! function)
|
||||||
(define-extern sincos-rad! function)
|
(define-extern sincos-rad! function)
|
||||||
(define-extern vector-sincos-rad! function)
|
(define-extern vector-sincos-rad! function)
|
||||||
(define-extern vector-xz-normalize! function)
|
|
||||||
(define-extern atan-series-rad function)
|
(define-extern atan-series-rad function)
|
||||||
(define-extern atan2-rad function)
|
(define-extern atan2-rad function)
|
||||||
(define-extern quaternion-from-two-vectors-max-angle! 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-rad<-vector-deg/2! function)
|
||||||
(define-extern vector-sin-rad! function)
|
(define-extern vector-sin-rad! function)
|
||||||
(define-extern acos-rad function)
|
(define-extern acos-rad function)
|
||||||
(define-extern vector-xz-length function)
|
|
||||||
(define-extern acos function)
|
(define-extern acos function)
|
||||||
(define-extern quat->eul function)
|
(define-extern quat->eul function)
|
||||||
(define-extern set-eul! function)
|
(define-extern set-eul! function)
|
||||||
|
@ -31514,15 +31609,7 @@
|
||||||
(define-extern forward-down-nopitch->inv-matrix function)
|
(define-extern forward-down-nopitch->inv-matrix function)
|
||||||
(define-extern vector-reflect-flat-above! function)
|
(define-extern vector-reflect-flat-above! function)
|
||||||
(define-extern vector-circle-tangent-new 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 coserp function)
|
||||||
(define-extern sinerp-clamp function)
|
(define-extern sinerp-clamp function)
|
||||||
;;(define-extern exp-slead object) ;; unknown type
|
;;(define-extern exp-slead object) ;; unknown type
|
||||||
|
@ -31773,72 +31860,9 @@
|
||||||
;;(define-extern draw-env object) ;; unknown type
|
;;(define-extern draw-env object) ;; unknown type
|
||||||
;;(define-extern *pre-draw-hook* object) ;; unknown type
|
;;(define-extern *pre-draw-hook* object) ;; unknown type
|
||||||
(define-extern set-display function)
|
(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 *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 load-dir object) ;; unknown type
|
||||||
;;(define-extern external-art-buffer object) ;; unknown type
|
;;(define-extern external-art-buffer object) ;; unknown type
|
||||||
;;(define-extern load-dir-art-group 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-strip-lines* object) ;; unknown type
|
||||||
;;(define-extern *display-process-anim* object) ;; unknown type
|
;;(define-extern *display-process-anim* object) ;; unknown type
|
||||||
;;(define-extern *display-actor-marks* 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-load-boundaries* object) ;; unknown type
|
||||||
;;(define-extern *display-water-marks* object) ;; unknown type
|
;;(define-extern *display-water-marks* object) ;; unknown type
|
||||||
;;(define-extern *artist-flip-visible* 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.
|
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`
|
## `label`
|
||||||
Create a named label for `goto` or `goto-when`.
|
Create a named label for `goto` or `goto-when`.
|
||||||
```lisp
|
```lisp
|
||||||
|
@ -1290,7 +1297,16 @@ This code generation is identical to using a `(set! dst src)` form.
|
||||||
(.nop.vf)
|
(.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`
|
## `.lvf`
|
||||||
```lisp
|
```lisp
|
||||||
|
|
|
@ -425,7 +425,8 @@ u64 kopen(u64 fs, u64 name, u64 mode) {
|
||||||
file_stream->flags = 0;
|
file_stream->flags = 0;
|
||||||
printf("****** CALL TO kopen() ******\n");
|
printf("****** CALL TO kopen() ******\n");
|
||||||
char buffer[128];
|
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")) {
|
if (!strcmp(info(Ptr<Symbol>(mode))->str->data(), "read")) {
|
||||||
file_stream->file = sceOpen(buffer, SCE_RDONLY);
|
file_stream->file = sceOpen(buffer, SCE_RDONLY);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,3 +5,133 @@
|
||||||
;; name in dgo: main-h
|
;; name in dgo: main-h
|
||||||
;; dgos: GAME, ENGINE
|
;; 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
|
;; name in dgo: file-io
|
||||||
;; dgos: GAME, ENGINE
|
;; 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-handler
|
||||||
;; install-debug-handler
|
;; install-debug-handler
|
||||||
;; file-stream-open
|
;; file-stream-open
|
||||||
|
(define-extern file-stream-open (function file-stream basic basic file-stream))
|
||||||
;; file-stream-close
|
;; file-stream-close
|
||||||
;; file-stream-length
|
(define-extern file-stream-length (function file-stream int))
|
||||||
;; file-stream-seek
|
;; file-stream-seek
|
||||||
;; file-stream-read
|
(define-extern file-stream-read (function file-stream pointer int int))
|
||||||
;; file-stream-write
|
;; file-stream-write
|
||||||
;; scf-get-language
|
;; scf-get-language
|
||||||
;; scf-get-time
|
;; scf-get-time
|
||||||
|
|
|
@ -389,9 +389,67 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
;; todo
|
(defun nassoc ((a0-0 string) (a1-0 object))
|
||||||
;; nassoc
|
(local-vars
|
||||||
;; nassce
|
(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))
|
(defun append! ((front object) (back object))
|
||||||
"Append back to front."
|
"Append back to front."
|
||||||
|
@ -605,7 +663,7 @@
|
||||||
dst
|
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."
|
"Memset a 32-bit value n times. Total memory filled is 4 * n bytes."
|
||||||
(let ((p (the pointer dst))
|
(let ((p (the pointer dst))
|
||||||
(i 0))
|
(i 0))
|
||||||
|
|
|
@ -85,7 +85,11 @@
|
||||||
;; cat-string<-string_to_charp
|
;; cat-string<-string_to_charp
|
||||||
;; append-character-to-string
|
;; append-character-to-string
|
||||||
;; charp-basename
|
;; charp-basename
|
||||||
;; clear
|
|
||||||
|
(defun clear ((a0-0 string))
|
||||||
|
(set! (-> a0-0 data 0) 0) a0-0
|
||||||
|
)
|
||||||
|
|
||||||
;; string<?
|
;; string<?
|
||||||
;; string>?
|
;; 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_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_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_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
|
// CompilerControl
|
||||||
Val* compile_seval(const goos::Object& form, const goos::Object& rest, Env* env);
|
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
|
// Asm
|
||||||
///////////////////////
|
///////////////////////
|
||||||
|
|
|
@ -340,6 +340,16 @@ class IR_GetStackAddr : public IR {
|
||||||
int m_slot = -1;
|
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 {
|
class IR_Asm : public IR {
|
||||||
public:
|
public:
|
||||||
explicit IR_Asm(bool use_coloring);
|
explicit IR_Asm(bool use_coloring);
|
||||||
|
|
|
@ -26,6 +26,7 @@ static const std::unordered_map<
|
||||||
|
|
||||||
// INLINE ASM - VECTOR FLOAT OPERATIONS
|
// INLINE ASM - VECTOR FLOAT OPERATIONS
|
||||||
{".nop.vf", &Compiler::compile_asm_nop_vf},
|
{".nop.vf", &Compiler::compile_asm_nop_vf},
|
||||||
|
{".nop", &Compiler::compile_nop},
|
||||||
{".lvf", &Compiler::compile_asm_lvf},
|
{".lvf", &Compiler::compile_asm_lvf},
|
||||||
{".svf", &Compiler::compile_asm_svf},
|
{".svf", &Compiler::compile_asm_svf},
|
||||||
{".xor.vf", &Compiler::compile_asm_xor_vf},
|
{".xor.vf", &Compiler::compile_asm_xor_vf},
|
||||||
|
@ -70,6 +71,7 @@ static const std::unordered_map<
|
||||||
{"return-from", &Compiler::compile_return_from},
|
{"return-from", &Compiler::compile_return_from},
|
||||||
{"label", &Compiler::compile_label},
|
{"label", &Compiler::compile_label},
|
||||||
{"goto", &Compiler::compile_goto},
|
{"goto", &Compiler::compile_goto},
|
||||||
|
{"nop!", &Compiler::compile_nop},
|
||||||
|
|
||||||
// COMPILER CONTROL
|
// COMPILER CONTROL
|
||||||
{"gs", &Compiler::compile_gs},
|
{"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});
|
get_parent_env_of_type<FunctionEnv>(env)->unresolved_gotos.push_back({ir_goto.get(), label_name});
|
||||||
env->emit(std::move(ir_goto));
|
env->emit(std::move(ir_goto));
|
||||||
return get_none();
|
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;
|
return instr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Instruction nop() {
|
||||||
|
// NOP
|
||||||
|
Instruction instr(0x90);
|
||||||
|
return instr;
|
||||||
|
}
|
||||||
|
|
||||||
static Instruction nop_vf() {
|
static Instruction nop_vf() {
|
||||||
// FNOP
|
// FNOP
|
||||||
Instruction instr(0xd9);
|
Instruction instr(0xd9);
|
||||||
|
|
|
@ -234,7 +234,7 @@ TEST_F(FormRegressionTest, WhileLoop) {
|
||||||
" (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n"
|
" (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n"
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (= v1-0 a1-0)\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"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! v0-0 '#f)\n"
|
" (set! v0-0 '#f)\n"
|
||||||
|
@ -300,7 +300,7 @@ TEST_F(FormRegressionTest, Or) {
|
||||||
" )\n"
|
" )\n"
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (= a0-0 a1-0)\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"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! v0-0 '#f)\n"
|
" (set! v0-0 '#f)\n"
|
||||||
|
@ -365,9 +365,9 @@ TEST_F(FormRegressionTest, DynamicMethodAccess) {
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (begin\n"
|
" (begin\n"
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (begin (set! a2-0 object) (= a0-0 a2-0))\n" // if we reached the top
|
" (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
|
" (return (begin (set! v1-3 nothing) (set! v0-0 v1-3)))\n" // return
|
||||||
// nothing.
|
// nothing.
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! a0-0 (-> a0-0 parent))\n" // get next parent type
|
" (set! a0-0 (-> a0-0 parent))\n" // get next parent type
|
||||||
" (set! a2-2 (sll a1-0 2))\n" // fancy access
|
" (set! a2-2 (sll a1-0 2))\n" // fancy access
|
||||||
|
@ -376,9 +376,9 @@ TEST_F(FormRegressionTest, DynamicMethodAccess) {
|
||||||
// condition)
|
// condition)
|
||||||
" (zero? v0-0)\n" // is it defined?
|
" (zero? v0-0)\n" // is it defined?
|
||||||
" )\n"
|
" )\n"
|
||||||
" (return (begin (set! v1-4 nothing) (set! v0-0 v1-4)) (set! v1-2 0))\n" // also
|
" (return (begin (set! v1-4 nothing) (set! v0-0 v1-4)))\n" // also
|
||||||
// return
|
// return
|
||||||
// nothing.
|
// nothing.
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! v1-5 '#f)\n"
|
" (set! v1-5 '#f)\n"
|
||||||
|
@ -887,7 +887,7 @@ TEST_F(FormRegressionTest, TypeOf) {
|
||||||
std::string type = "(function object object)";
|
std::string type = "(function object object)";
|
||||||
std::string expected =
|
std::string expected =
|
||||||
"(begin\n"
|
"(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! t9-0 (-> v1-1 methods-by-name print))\n" // print method.
|
||||||
" (set! v0-0 (call! a0-0))\n"
|
" (set! v0-0 (call! a0-0))\n"
|
||||||
" (ret-value v0-0)\n"
|
" (ret-value v0-0)\n"
|
||||||
|
|
|
@ -461,7 +461,7 @@ TEST_F(FormRegressionTest, ExprBasicTypeP) {
|
||||||
// don't plan on supporting this.
|
// don't plan on supporting this.
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (= v1-0 a1-0)\n"
|
" (= v1-0 a1-0)\n"
|
||||||
" (return '#t (set! v1-0 0))\n"
|
" (return '#t)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" '#f\n"
|
" '#f\n"
|
||||||
|
@ -507,7 +507,7 @@ TEST_F(FormRegressionTest, FinalBasicTypeP) {
|
||||||
" (set! a0-1 object)\n"
|
" (set! a0-1 object)\n"
|
||||||
" (until\n"
|
" (until\n"
|
||||||
" (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\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"
|
" )\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
|
@ -562,7 +562,7 @@ TEST_F(FormRegressionTest, ExprTypeTypep) {
|
||||||
" (set! a0-0 (-> a0-0 parent))\n"
|
" (set! a0-0 (-> a0-0 parent))\n"
|
||||||
" (or (= a0-0 v1-0) (zero? a0-0))\n"
|
" (or (= a0-0 v1-0) (zero? a0-0))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (if (= a0-0 a1-0) (return '#t (set! v1-0 0)))\n"
|
" (if (= a0-0 a1-0) (return '#t))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" '#f\n"
|
" '#f\n"
|
||||||
" )";
|
" )";
|
||||||
|
@ -618,13 +618,13 @@ TEST_F(FormRegressionTest, ExprFindParentMethod) {
|
||||||
|
|
||||||
std::string expected =
|
std::string expected =
|
||||||
"(begin\n"
|
"(begin\n"
|
||||||
" (set! v1-2 (-> a0-0 methods a1-0))\n"
|
" (set! v1-2 (-> a0-0 method-table a1-0))\n"
|
||||||
" (until\n"
|
" (until\n"
|
||||||
" (!= v0-0 v1-2)\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! a0-0 (-> a0-0 parent))\n"
|
||||||
" (set! v0-0 (-> a0-0 methods a1-0))\n"
|
" (set! v0-0 (-> a0-0 method-table a1-0))\n"
|
||||||
" (if (zero? v0-0) (return nothing (set! v1-2 0)))\n"
|
" (if (zero? v0-0) (return nothing))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! v1-5 '#f)\n"
|
" (set! v1-5 '#f)\n"
|
||||||
" v0-0\n"
|
" v0-0\n"
|
||||||
|
@ -902,7 +902,7 @@ TEST_F(FormRegressionTest, ExprNmember) {
|
||||||
" (set! s5-0 a0-0)\n"
|
" (set! s5-0 a0-0)\n"
|
||||||
" (set! gp-0 a1-0)\n"
|
" (set! gp-0 a1-0)\n"
|
||||||
" (while\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"
|
" (set! gp-0 (cdr gp-0))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! v1-2 '#f)\n"
|
" (set! v1-2 '#f)\n"
|
||||||
|
@ -1110,7 +1110,11 @@ TEST_F(FormRegressionTest, ExprNassoc) {
|
||||||
" (= gp-0 (quote ()))\n"
|
" (= gp-0 (quote ()))\n"
|
||||||
" (begin\n"
|
" (begin\n"
|
||||||
" (set! a1-1 (car (car gp-0)))\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"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
|
@ -1213,8 +1217,11 @@ TEST_F(FormRegressionTest, ExprNassoce) {
|
||||||
" (set! s4-0 (car (car gp-0)))\n"
|
" (set! s4-0 (car (car gp-0)))\n"
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (pair? s4-0)\n"
|
" (pair? s4-0)\n"
|
||||||
" (nmember s5-0 s4-0)\n"
|
" (nmember (the-as basic s5-0) s4-0)\n"
|
||||||
" (or (name= s4-0 s5-0) (= s4-0 (quote else)))\n"
|
" (or\n"
|
||||||
|
" (name= (the-as basic s4-0) (the-as basic s5-0))\n"
|
||||||
|
" (= s4-0 (quote else))\n"
|
||||||
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
|
@ -2063,7 +2070,7 @@ TEST_F(FormRegressionTest, ExprPrint) {
|
||||||
" daddiu sp, sp, 16";
|
" daddiu sp, sp, 16";
|
||||||
std::string type = "(function object object)";
|
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);
|
test_with_expr(func, type, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2112,7 +2119,7 @@ TEST_F(FormRegressionTest, ExprPrintl) {
|
||||||
"(begin\n"
|
"(begin\n"
|
||||||
" (set! gp-0 a0-0)\n"
|
" (set! gp-0 a0-0)\n"
|
||||||
" (set! a0-1 gp-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"
|
" (format (quote #t) L324)\n"
|
||||||
" gp-0\n"
|
" gp-0\n"
|
||||||
" )";
|
" )";
|
||||||
|
@ -2143,7 +2150,7 @@ TEST_F(FormRegressionTest, ExprInspect) {
|
||||||
" daddiu sp, sp, 16";
|
" daddiu sp, sp, 16";
|
||||||
std::string type = "(function object object)";
|
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);
|
test_with_expr(func, type, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2334,13 +2341,13 @@ TEST_F(FormRegressionTest, ExprPrintName) {
|
||||||
"(cond\n"
|
"(cond\n"
|
||||||
" ((= a0-0 a1-0) (quote #t))\n"
|
" ((= a0-0 a1-0) (quote #t))\n"
|
||||||
" ((and (= (-> a0-0 type) string) (= (-> a1-0 type) string))\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"
|
" )\n"
|
||||||
" ((and (= (-> a0-0 type) string) (= (-> a1-0 type) symbol))\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"
|
" )\n"
|
||||||
" ((and (= (-> a1-0 type) string) (= (-> a0-0 type) symbol))\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"
|
" )\n"
|
||||||
" )";
|
" )";
|
||||||
test_with_expr(func, type, expected, false, "", {},
|
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"
|
" (if s4-0 (set! v1-24 (format s5-0 L318 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" ((and (= s3-0 type) (!= (type-of gp-0) type))\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 (type-of gp-0))))\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"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (else\n"
|
" (else\n"
|
||||||
|
@ -2011,16 +2011,16 @@ TEST_F(FormRegressionTest, ExprValid) {
|
||||||
" v1-33\n"
|
" v1-33\n"
|
||||||
" (and\n"
|
" (and\n"
|
||||||
" (!= s3-0 type)\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"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" (v1-33\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"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" ((not (type-type? (type-of gp-0) s3-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 (type-of gp-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"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" ((= s3-0 symbol)\n"
|
" ((= s3-0 symbol)\n"
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
(let* ((base-addr #x6000000)
|
(let* ((base-addr #x6000000)
|
||||||
(word-cnt 23)
|
(word-cnt 23)
|
||||||
(base (the (pointer int32) base-addr))
|
(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)))))
|
(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)
|
(if (!= dst base)
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
(set! (-> b x) 2.)
|
(set! (-> b x) 2.)
|
||||||
(set! (-> b y) 3.)
|
(set! (-> b y) 3.)
|
||||||
(set! (-> b z) 4.)
|
(set! (-> b z) 4.)
|
||||||
|
(.nop)
|
||||||
|
(nop!)
|
||||||
(expect-true (= 20.0 (vector-dot-vu a b)))
|
(expect-true (= 20.0 (vector-dot-vu a b)))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue