mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-23 06:09:57 +00:00
add declare-file debug (#1004)
This commit is contained in:
parent
a10f9da8b8
commit
f6b40637a3
@ -4,7 +4,7 @@
|
||||
// if you want to filter to only some object names.
|
||||
// it will make the decompiler much faster.
|
||||
"allowed_objects": [],
|
||||
"banned_objects": [],
|
||||
"banned_objects": ["collide-mesh"],
|
||||
|
||||
////////////////////////////
|
||||
// CODE ANALYSIS OPTIONS
|
||||
|
@ -206,4 +206,5 @@
|
||||
- Using `->` on a plain `pointer` or `inline-array` now generates an error instead of crashing the compiler
|
||||
- It is now possible to use a macro to provide a static inline array element definition
|
||||
- It is now possible to have symbol names that have a `#` in the middle of them
|
||||
- `go-hook` now returns the return value of the `enter-state` function it calls
|
||||
- `go-hook` now returns the return value of the `enter-state` function it calls
|
||||
- Added a `(declare-file (debug))` to put things in the debug segment by default. This only changes _static_ objects. Dynamic allocation with forms like `cons` will continue to use the main segment like before.
|
@ -5,6 +5,8 @@
|
||||
;; name in dgo: cam-layout
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(declare-file (debug))
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; this file is debug only
|
||||
|
@ -8,6 +8,8 @@
|
||||
;; NOTES - removed one of the 2 inspects
|
||||
;; - also fixed up a basic file-stream constructor on the stack
|
||||
|
||||
(declare-file (debug))
|
||||
|
||||
(declare-type list-control structure)
|
||||
(define-extern anim-test-anim-list-handler (function int list-control symbol))
|
||||
(define-extern anim-test-edit-sequence-list-handler (function int list-control symbol))
|
||||
|
@ -5,6 +5,8 @@
|
||||
;; name in dgo: default-menu
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(declare-file (debug))
|
||||
|
||||
;; Forward declarations for stuff we haven't written yet:
|
||||
(define-extern *edit-instance* string)
|
||||
|
||||
|
@ -125,7 +125,7 @@ class Compiler {
|
||||
Val* compile_float(float value, Env* env, int seg);
|
||||
Val* compile_symbol(const goos::Object& form, Env* env);
|
||||
Val* compile_string(const goos::Object& form, Env* env);
|
||||
Val* compile_string(const std::string& str, Env* env, int seg = MAIN_SEGMENT);
|
||||
Val* compile_string(const std::string& str, Env* env, int seg);
|
||||
Val* compile_get_symbol_value(const goos::Object& form, const std::string& name, Env* env);
|
||||
Val* compile_function_or_method_call(const goos::Object& form, Env* env);
|
||||
|
||||
@ -233,15 +233,20 @@ class Compiler {
|
||||
Env* env,
|
||||
bool call_constructor);
|
||||
|
||||
StaticResult fill_static_array(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
StaticResult fill_static_array(const goos::Object& form,
|
||||
const goos::Object& rest,
|
||||
Env* env,
|
||||
int seg);
|
||||
|
||||
StaticResult fill_static_boxed_array(const goos::Object& form,
|
||||
const goos::Object& rest,
|
||||
Env* env);
|
||||
Env* env,
|
||||
int seg);
|
||||
|
||||
StaticResult fill_static_inline_array(const goos::Object& form,
|
||||
const goos::Object& rest,
|
||||
Env* env);
|
||||
Env* env,
|
||||
int seg);
|
||||
|
||||
void fill_static_inline_array_inline(const goos::Object& form,
|
||||
const TypeSpec& content_type,
|
||||
@ -330,10 +335,11 @@ class Compiler {
|
||||
Val* compile_new_static_structure_or_basic(const goos::Object& form,
|
||||
const TypeSpec& type,
|
||||
const goos::Object& field_defs,
|
||||
Env* env);
|
||||
Val* compile_static_pair(const goos::Object& form, Env* env);
|
||||
Env* env,
|
||||
int seg);
|
||||
Val* compile_static_pair(const goos::Object& form, Env* env, int seg);
|
||||
StaticResult compile_static(const goos::Object& form, Env* env);
|
||||
StaticResult compile_static_no_eval_for_pairs(const goos::Object& form, Env* env);
|
||||
StaticResult compile_static_no_eval_for_pairs(const goos::Object& form, Env* env, int seg);
|
||||
|
||||
Val* compile_bitfield_definition(const goos::Object& form,
|
||||
const TypeSpec& type,
|
||||
@ -343,7 +349,8 @@ class Compiler {
|
||||
StaticResult compile_new_static_structure(const goos::Object& form,
|
||||
const TypeSpec& type,
|
||||
const goos::Object& _field_defs,
|
||||
Env* env);
|
||||
Env* env,
|
||||
int seg);
|
||||
|
||||
void compile_static_structure_inline(const goos::Object& form,
|
||||
const TypeSpec& type,
|
||||
@ -606,6 +613,7 @@ class Compiler {
|
||||
Val* compile_inline(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_declare(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_local_vars(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_declare_file(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
||||
// Type
|
||||
Val* compile_deftype(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
@ -118,12 +118,16 @@ class FileEnv : public Env {
|
||||
return (T*)m_vals.back().get();
|
||||
}
|
||||
|
||||
int default_segment() const { return m_default_segment; }
|
||||
void set_debug_file() { m_default_segment = DEBUG_SEGMENT; }
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
std::vector<std::shared_ptr<FunctionEnv>> m_functions;
|
||||
std::vector<std::unique_ptr<StaticObject>> m_statics;
|
||||
int m_anon_func_counter = 0;
|
||||
std::vector<std::unique_ptr<Val>> m_vals;
|
||||
int m_default_segment = MAIN_SEGMENT;
|
||||
|
||||
// statics
|
||||
FunctionEnv* m_top_level_func = nullptr;
|
||||
@ -192,6 +196,14 @@ class FunctionEnv : public DeclareEnv {
|
||||
int align_bytes);
|
||||
int stack_slots_used_for_stack_vars() const { return m_stack_var_slots_used; }
|
||||
|
||||
int segment_for_static_data() {
|
||||
if (segment == TOP_LEVEL_SEGMENT) {
|
||||
return file_env()->default_segment();
|
||||
} else {
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
|
||||
int idx_in_file = -1;
|
||||
|
||||
template <typename T, class... Args>
|
||||
|
@ -208,6 +208,7 @@ const std::unordered_map<
|
||||
{"declare", &Compiler::compile_declare},
|
||||
{"inline", &Compiler::compile_inline},
|
||||
{"local-vars", &Compiler::compile_local_vars},
|
||||
{"declare-file", &Compiler::compile_declare_file},
|
||||
// {"with-inline", &Compiler::compile_with_inline},
|
||||
// {"get-ra-ptr", &Compiler::compile_get_ra_ptr},
|
||||
|
||||
@ -428,14 +429,12 @@ Val* Compiler::compile_symbol(const goos::Object& form, Env* env) {
|
||||
}
|
||||
|
||||
/*!
|
||||
* Compile a string constant. The constant is placed in the same segment as the parent function.
|
||||
* Compile a string constant. The constant is placed in the same segment as the parent function. For
|
||||
* top-level functions, the string is placed in the file's default segment.
|
||||
*/
|
||||
Val* Compiler::compile_string(const goos::Object& form, Env* env) {
|
||||
auto segment = env->function_env()->segment;
|
||||
if (segment == TOP_LEVEL_SEGMENT) {
|
||||
segment = MAIN_SEGMENT;
|
||||
}
|
||||
return compile_string(form.as_string()->data, env, segment);
|
||||
return compile_string(form.as_string()->data, env,
|
||||
env->function_env()->segment_for_static_data());
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -456,12 +455,10 @@ Val* Compiler::compile_string(const std::string& str, Env* env, int seg) {
|
||||
* of the code, at least in Jak 1.
|
||||
*/
|
||||
Val* Compiler::compile_float(const goos::Object& code, Env* env) {
|
||||
auto segment = env->function_env()->segment;
|
||||
if (segment == TOP_LEVEL_SEGMENT) {
|
||||
segment = MAIN_SEGMENT;
|
||||
}
|
||||
assert(code.is_float());
|
||||
return compile_float(code.float_obj.value, env, segment);
|
||||
// TODO: this will put top-level only floats in main. Which is conservative because I
|
||||
// don't think we can take the address of a float constant.
|
||||
return compile_float(code.float_obj.value, env, env->function_env()->segment_for_static_data());
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -149,11 +149,7 @@ Val* Compiler::compile_lambda(const goos::Object& form, const goos::Object& rest
|
||||
args.has_named("inline-only") && symbol_string(args.get_named("inline-only")) != "#f";
|
||||
|
||||
// pick default segment to store function in.
|
||||
int segment = MAIN_SEGMENT;
|
||||
if (fe->segment == DEBUG_SEGMENT) {
|
||||
// make anonymous lambdas in debug functions also go to debug
|
||||
segment = DEBUG_SEGMENT;
|
||||
}
|
||||
int segment = fe->segment_for_static_data();
|
||||
|
||||
// override default segment.
|
||||
if (args.has_named("segment")) {
|
||||
@ -714,3 +710,34 @@ Val* Compiler::compile_declare(const goos::Object& form, const goos::Object& res
|
||||
});
|
||||
return get_none();
|
||||
}
|
||||
|
||||
Val* Compiler::compile_declare_file(const goos::Object& /*form*/,
|
||||
const goos::Object& rest,
|
||||
Env* env) {
|
||||
for_each_in_list(rest, [&](const goos::Object& o) {
|
||||
if (!o.is_pair()) {
|
||||
throw_compiler_error(o, "Invalid declare-file specification.");
|
||||
}
|
||||
|
||||
auto first = o.as_pair()->car;
|
||||
auto rrest = &o.as_pair()->cdr;
|
||||
|
||||
if (!first.is_symbol()) {
|
||||
throw_compiler_error(
|
||||
first, "Invalid declare option specification, expected a symbol, but got {} instead.",
|
||||
first.print());
|
||||
}
|
||||
|
||||
if (first.as_symbol()->name == "debug") {
|
||||
if (!rrest->is_empty_list()) {
|
||||
throw_compiler_error(first, "Invalid debug declare");
|
||||
}
|
||||
env->file_env()->set_debug_file();
|
||||
|
||||
} else {
|
||||
throw_compiler_error(first, "Unrecognized declare-file option {}.", first.print());
|
||||
}
|
||||
});
|
||||
|
||||
return get_none();
|
||||
}
|
@ -146,7 +146,7 @@ Val* Compiler::compile_quote(const goos::Object& form, const goos::Object& rest,
|
||||
return empty_pair;
|
||||
}
|
||||
case goos::ObjectType::PAIR:
|
||||
return compile_static_pair(thing, env);
|
||||
return compile_static_pair(thing, env, env->function_env()->segment_for_static_data());
|
||||
default:
|
||||
throw_compiler_error(form, "Quote is not yet implemented for {}.", thing.print());
|
||||
}
|
||||
|
@ -264,14 +264,15 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
|
||||
StaticResult Compiler::compile_new_static_structure(const goos::Object& form,
|
||||
const TypeSpec& type,
|
||||
const goos::Object& _field_defs,
|
||||
Env* env) {
|
||||
Env* env,
|
||||
int seg) {
|
||||
std::unique_ptr<StaticStructure> obj;
|
||||
if (is_basic(type)) {
|
||||
obj = std::make_unique<StaticBasic>(MAIN_SEGMENT, type.base_type());
|
||||
obj = std::make_unique<StaticBasic>(seg, type.base_type());
|
||||
} else {
|
||||
// if we ever find this type of static data outside of MAIN_SEGMENT, we can create an option
|
||||
// in the new form to pick the segment.
|
||||
obj = std::make_unique<StaticStructure>(MAIN_SEGMENT);
|
||||
obj = std::make_unique<StaticStructure>(seg);
|
||||
}
|
||||
|
||||
auto type_info = dynamic_cast<StructureType*>(m_ts.lookup_type(type));
|
||||
@ -554,22 +555,19 @@ Val* Compiler::compile_bitfield_definition(const goos::Object& form,
|
||||
* - Integers
|
||||
* - Strings
|
||||
*/
|
||||
StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form, Env* env) {
|
||||
StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form,
|
||||
Env* env,
|
||||
int seg) {
|
||||
auto fie = env->file_env();
|
||||
auto fe = env->function_env();
|
||||
auto segment = fe->segment;
|
||||
if (segment == TOP_LEVEL_SEGMENT) {
|
||||
segment = MAIN_SEGMENT;
|
||||
}
|
||||
if (form.is_pair()) {
|
||||
if (form.as_pair()->car.is_symbol() && (form.as_pair()->car.as_symbol()->name == "new" ||
|
||||
form.as_pair()->car.as_symbol()->name == "the" ||
|
||||
form.as_pair()->car.as_symbol()->name == "lambda")) {
|
||||
return compile_static(form, env);
|
||||
}
|
||||
auto car = compile_static_no_eval_for_pairs(form.as_pair()->car, env);
|
||||
auto cdr = compile_static_no_eval_for_pairs(form.as_pair()->cdr, env);
|
||||
auto pair_structure = std::make_unique<StaticPair>(car, cdr, segment);
|
||||
auto car = compile_static_no_eval_for_pairs(form.as_pair()->car, env, seg);
|
||||
auto cdr = compile_static_no_eval_for_pairs(form.as_pair()->cdr, env, seg);
|
||||
auto pair_structure = std::make_unique<StaticPair>(car, cdr, seg);
|
||||
auto result =
|
||||
StaticResult::make_structure_reference(pair_structure.get(), m_ts.make_typespec("pair"));
|
||||
fie->add_static(std::move(pair_structure));
|
||||
@ -588,7 +586,7 @@ StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form
|
||||
return StaticResult::make_symbol("_empty_");
|
||||
} else if (form.is_string()) {
|
||||
// todo - this should eventually work with a string pool
|
||||
auto obj = std::make_unique<StaticString>(form.as_string()->data, segment);
|
||||
auto obj = std::make_unique<StaticString>(form.as_string()->data, seg);
|
||||
auto result = StaticResult::make_structure_reference(obj.get(), m_ts.make_typespec("string"));
|
||||
fie->add_static(std::move(obj));
|
||||
return result;
|
||||
@ -599,7 +597,7 @@ StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form
|
||||
}
|
||||
|
||||
/*!
|
||||
* Generic copmilation function to handle:
|
||||
* Generic compilation function to handle:
|
||||
* - (new 'static <structure-or-basic>), a reference
|
||||
*
|
||||
* - (new 'static '<bitfield>), an integer constant
|
||||
@ -616,10 +614,7 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env
|
||||
auto form = expand_macro_completely(form_before_macro, env);
|
||||
auto fie = env->file_env();
|
||||
auto fe = env->function_env();
|
||||
auto segment = fe->segment;
|
||||
if (segment == TOP_LEVEL_SEGMENT) {
|
||||
segment = MAIN_SEGMENT;
|
||||
}
|
||||
auto segment = fe->segment_for_static_data();
|
||||
|
||||
if (form.is_symbol()) {
|
||||
// constant, #t, or #f
|
||||
@ -660,7 +655,7 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env
|
||||
throw_compiler_error(form, "The form {} is an invalid quoted form.", form.print());
|
||||
}
|
||||
if (second.is_pair() || second.is_empty_list()) {
|
||||
return compile_static_no_eval_for_pairs(second, env);
|
||||
return compile_static_no_eval_for_pairs(second, env, segment);
|
||||
} else {
|
||||
throw_compiler_error(form, "Could not evaluate the quoted form {} at compile time.",
|
||||
second.print());
|
||||
@ -685,11 +680,11 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env
|
||||
}
|
||||
|
||||
if (unquote(args.at(1)).as_symbol()->name == "boxed-array") {
|
||||
return fill_static_boxed_array(form, rest, env);
|
||||
return fill_static_boxed_array(form, rest, env, segment);
|
||||
} else if (unquote(args.at(1)).as_symbol()->name == "array") {
|
||||
return fill_static_array(form, rest, env);
|
||||
return fill_static_array(form, rest, env, segment);
|
||||
} else if (unquote(args.at(1)).as_symbol()->name == "inline-array") {
|
||||
return fill_static_inline_array(form, rest, env);
|
||||
return fill_static_inline_array(form, rest, env, segment);
|
||||
} else {
|
||||
auto ts = parse_typespec(unquote(args.at(1)));
|
||||
if (ts == TypeSpec("string")) {
|
||||
@ -710,7 +705,7 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env
|
||||
compile_bitfield_definition(form, ts, constructor_args, false, env));
|
||||
return StaticResult::make_constant_data(val->value(), val->type());
|
||||
} else if (is_structure(ts)) {
|
||||
return compile_new_static_structure(form, ts, constructor_args, env);
|
||||
return compile_new_static_structure(form, ts, constructor_args, env, segment);
|
||||
} else {
|
||||
throw_compiler_error(form, "Cannot construct a static {}.", ts.print());
|
||||
}
|
||||
@ -831,7 +826,8 @@ void Compiler::fill_static_array_inline(const goos::Object& form,
|
||||
|
||||
StaticResult Compiler::fill_static_array(const goos::Object& form,
|
||||
const goos::Object& rest,
|
||||
Env* env) {
|
||||
Env* env,
|
||||
int seg) {
|
||||
auto fie = env->file_env();
|
||||
// (new 'static 'boxed-array ...)
|
||||
// get all arguments now
|
||||
@ -851,10 +847,9 @@ StaticResult Compiler::fill_static_array(const goos::Object& form,
|
||||
assert(deref_info.can_deref);
|
||||
assert(deref_info.mem_deref);
|
||||
auto array_data_size_bytes = length * deref_info.stride;
|
||||
// todo, segments
|
||||
std::unique_ptr<StaticStructure> obj;
|
||||
|
||||
obj = std::make_unique<StaticStructure>(MAIN_SEGMENT);
|
||||
obj = std::make_unique<StaticStructure>(seg);
|
||||
|
||||
obj->data.resize(array_data_size_bytes);
|
||||
|
||||
@ -870,7 +865,8 @@ StaticResult Compiler::fill_static_array(const goos::Object& form,
|
||||
|
||||
StaticResult Compiler::fill_static_boxed_array(const goos::Object& form,
|
||||
const goos::Object& rest,
|
||||
Env* env) {
|
||||
Env* env,
|
||||
int seg) {
|
||||
auto fie = env->file_env();
|
||||
// (new 'static 'boxed-array ...)
|
||||
// get all arguments now
|
||||
@ -923,7 +919,7 @@ StaticResult Compiler::fill_static_boxed_array(const goos::Object& form,
|
||||
auto array_data_size_bytes = allocated_length * deref_info.stride;
|
||||
// todo, segments
|
||||
std::unique_ptr<StaticStructure> obj;
|
||||
obj = std::make_unique<StaticBasic>(MAIN_SEGMENT, "array");
|
||||
obj = std::make_unique<StaticBasic>(seg, "array");
|
||||
|
||||
int array_header_size = 16;
|
||||
obj->data.resize(array_header_size + array_data_size_bytes);
|
||||
@ -1002,7 +998,8 @@ void Compiler::fill_static_inline_array_inline(const goos::Object& form,
|
||||
|
||||
StaticResult Compiler::fill_static_inline_array(const goos::Object& form,
|
||||
const goos::Object& rest,
|
||||
Env* env) {
|
||||
Env* env,
|
||||
int seg) {
|
||||
auto fie = env->file_env();
|
||||
// (new 'static 'inline-array ...)
|
||||
// get all arguments now
|
||||
@ -1021,8 +1018,7 @@ StaticResult Compiler::fill_static_inline_array(const goos::Object& form,
|
||||
auto deref_info = m_ts.get_deref_info(inline_array_type);
|
||||
assert(deref_info.can_deref);
|
||||
assert(!deref_info.mem_deref);
|
||||
// todo
|
||||
auto obj = std::make_unique<StaticStructure>(MAIN_SEGMENT);
|
||||
auto obj = std::make_unique<StaticStructure>(seg);
|
||||
obj->set_offset(is_basic(content_type) ? 4 : 0);
|
||||
obj->data.resize(length * deref_info.stride);
|
||||
|
||||
@ -1035,9 +1031,9 @@ StaticResult Compiler::fill_static_inline_array(const goos::Object& form,
|
||||
return result;
|
||||
}
|
||||
|
||||
Val* Compiler::compile_static_pair(const goos::Object& form, Env* env) {
|
||||
Val* Compiler::compile_static_pair(const goos::Object& form, Env* env, int seg) {
|
||||
assert(form.is_pair()); // (quote PAIR)
|
||||
auto result = compile_static_no_eval_for_pairs(form, env);
|
||||
auto result = compile_static_no_eval_for_pairs(form, env, seg);
|
||||
assert(result.is_reference());
|
||||
auto fe = env->function_env();
|
||||
auto static_result = fe->alloc_val<StaticVal>(result.reference(), result.typespec());
|
||||
@ -1047,9 +1043,10 @@ Val* Compiler::compile_static_pair(const goos::Object& form, Env* env) {
|
||||
Val* Compiler::compile_new_static_structure_or_basic(const goos::Object& form,
|
||||
const TypeSpec& type,
|
||||
const goos::Object& field_defs,
|
||||
Env* env) {
|
||||
Env* env,
|
||||
int seg) {
|
||||
auto fe = env->function_env();
|
||||
auto sr = compile_new_static_structure(form, type, field_defs, env);
|
||||
auto sr = compile_new_static_structure(form, type, field_defs, env, seg);
|
||||
auto result = fe->alloc_val<StaticVal>(sr.reference(), type);
|
||||
return result;
|
||||
}
|
||||
|
@ -485,7 +485,7 @@ Val* Compiler::compile_defmethod(const goos::Object& form, const goos::Object& _
|
||||
place->func = nullptr;
|
||||
|
||||
auto new_func_env = std::make_unique<FunctionEnv>(env, lambda.debug_name, &m_goos.reader);
|
||||
new_func_env->set_segment(MAIN_SEGMENT); // todo, how do we set debug?
|
||||
new_func_env->set_segment(env->function_env()->segment_for_static_data());
|
||||
new_func_env->method_of_type_name = symbol_string(type_name);
|
||||
|
||||
// set up arguments
|
||||
@ -1060,7 +1060,8 @@ Val* Compiler::compile_static_new(const goos::Object& form,
|
||||
} else {
|
||||
auto type_of_object = parse_typespec(unquote(type));
|
||||
if (is_structure(type_of_object)) {
|
||||
return compile_new_static_structure_or_basic(form, type_of_object, *rest, env);
|
||||
return compile_new_static_structure_or_basic(form, type_of_object, *rest, env,
|
||||
env->function_env()->segment_for_static_data());
|
||||
}
|
||||
|
||||
if (is_bitfield(type_of_object)) {
|
||||
|
Loading…
Reference in New Issue
Block a user