mirror of
https://github.com/open-goal/jak-project
synced 2026-08-20 06:16:35 -04:00
Merge branch 'master' of https://github.com/water111/jak-project into w/type-pass-2
This commit is contained in:
+22
-7
@@ -103,20 +103,35 @@ void initialize() {
|
||||
assert(!gLogger.initialized);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Always enable VIRTUAL_TERMINAL_PROCESSING, this console mode allows the console (stdout) to
|
||||
// support ANSI colors in the outputted text, which are used by the logging tool.
|
||||
// This mode may not be enabled by default, and changing that involves modifying the registry,
|
||||
// so it seems like a better solution would be enabling it ourselves.
|
||||
// Enable some console terminal flags. Some of these may not be enabled by default, unless
|
||||
// the user edits their registry. This is clearly unwanted, so we just set them here ourselves.
|
||||
|
||||
// VIRTUAL_TERMINAL_PROCESSING enables support for ANSI colors in the stdout text, used by the
|
||||
// logging tool.
|
||||
// ENABLE_QUICK_EDIT_MODE enables various mouse-related stdin functions, such as right-click for
|
||||
// copy-paste, scroll wheel to - shocker - scroll, etc.
|
||||
|
||||
// Get handle to stdout
|
||||
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
// get current stdout mode
|
||||
DWORD modeStdOut;
|
||||
GetConsoleMode(hStdOut, &modeStdOut);
|
||||
// enable VIRTUAL_TERMINAL_PROCESSING. As a bitwise OR it will not do anything if it is
|
||||
// already set
|
||||
// printf("stdout mode is: %08x", modeStdOut);
|
||||
|
||||
// Get handle to stdin
|
||||
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
// get current stdin mode
|
||||
DWORD modeStdIn;
|
||||
GetConsoleMode(hStdIn, &modeStdIn);
|
||||
// printf("stdin mode is: %08x", modeStdIn);
|
||||
|
||||
// enable VIRTUAL_TERMINAL_PROCESSING on stdout
|
||||
modeStdOut |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
SetConsoleMode(hStdOut, modeStdOut);
|
||||
|
||||
// enable ENABLE_QUICK_EDIT_MODE on stdin
|
||||
modeStdIn |= ENABLE_QUICK_EDIT_MODE;
|
||||
SetConsoleMode(hStdIn, modeStdIn);
|
||||
#endif
|
||||
|
||||
gLogger.initialized = true;
|
||||
@@ -132,4 +147,4 @@ void finish() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lg
|
||||
} // namespace lg
|
||||
|
||||
@@ -38,6 +38,16 @@ TypeSystem::TypeSystem() {
|
||||
* throw_on_redefine is set. The type should be fully set up (fields, etc) before running this.
|
||||
*/
|
||||
Type* TypeSystem::add_type(const std::string& name, std::unique_ptr<Type> type) {
|
||||
auto method_kv = m_forward_declared_method_counts.find(name);
|
||||
if (method_kv != m_forward_declared_method_counts.end()) {
|
||||
int method_count = get_next_method_id(type.get());
|
||||
if (method_count != method_kv->second) {
|
||||
throw_typesystem_error(
|
||||
"Type {} was defined with {} methods, but was forward declared with {}\n", name,
|
||||
method_count, method_kv->second);
|
||||
}
|
||||
}
|
||||
|
||||
auto kv = m_types.find(name);
|
||||
if (kv != m_types.end()) {
|
||||
// exists already
|
||||
@@ -177,6 +187,53 @@ void TypeSystem::forward_declare_type_as(const std::string& new_type,
|
||||
}
|
||||
}
|
||||
|
||||
void TypeSystem::forward_declare_type_method_count(const std::string& name, int num_methods) {
|
||||
auto existing_fwd = m_forward_declared_method_counts.find(name);
|
||||
if (existing_fwd != m_forward_declared_method_counts.end() &&
|
||||
existing_fwd->second != num_methods) {
|
||||
throw_typesystem_error(
|
||||
"Type {} was originally forward declared with {} methods and is now being forward declared "
|
||||
"with {} methods",
|
||||
name, existing_fwd->second, num_methods);
|
||||
}
|
||||
|
||||
auto existing_type = m_types.find(name);
|
||||
if (existing_type != m_types.end()) {
|
||||
int existing_count = get_next_method_id(existing_type->second.get());
|
||||
if (existing_count != num_methods) {
|
||||
throw_typesystem_error(
|
||||
"Type {} was defined with {} methods and is now being forward declared with {} methods",
|
||||
name, existing_fwd->second, num_methods);
|
||||
}
|
||||
}
|
||||
|
||||
m_forward_declared_method_counts[name] = num_methods;
|
||||
}
|
||||
|
||||
int TypeSystem::get_type_method_count(const std::string& name) const {
|
||||
auto result = try_get_type_method_count(name);
|
||||
if (result) {
|
||||
return *result;
|
||||
}
|
||||
throw_typesystem_error("Tried to find the number of methods on type {}, but it is not defined.",
|
||||
name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::optional<int> TypeSystem::try_get_type_method_count(const std::string& name) const {
|
||||
auto type_it = m_types.find(name);
|
||||
if (type_it != m_types.end()) {
|
||||
return get_next_method_id(type_it->second.get());
|
||||
}
|
||||
|
||||
auto fwd_it = m_forward_declared_method_counts.find(name);
|
||||
if (fwd_it != m_forward_declared_method_counts.end()) {
|
||||
return fwd_it->second;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the runtime type (as a name string) of a TypeSpec. Gets the runtime type of the primary
|
||||
* type of the TypeSpec.
|
||||
|
||||
@@ -126,6 +126,9 @@ class TypeSystem {
|
||||
Type* add_type(const std::string& name, std::unique_ptr<Type> type);
|
||||
void forward_declare_type_as_type(const std::string& name);
|
||||
void forward_declare_type_as(const std::string& new_type, const std::string& parent_type);
|
||||
void forward_declare_type_method_count(const std::string& name, int num_methods);
|
||||
int get_type_method_count(const std::string& name) const;
|
||||
std::optional<int> try_get_type_method_count(const std::string& name) const;
|
||||
std::string get_runtime_type(const TypeSpec& ts);
|
||||
|
||||
DerefInfo get_deref_info(const TypeSpec& ts) const;
|
||||
@@ -258,6 +261,8 @@ class TypeSystem {
|
||||
|
||||
std::unordered_map<std::string, std::unique_ptr<Type>> m_types;
|
||||
std::unordered_map<std::string, std::string> m_forward_declared_types;
|
||||
std::unordered_map<std::string, int> m_forward_declared_method_counts;
|
||||
|
||||
std::vector<std::unique_ptr<Type>> m_old_types;
|
||||
|
||||
bool m_allow_redefinition = false;
|
||||
|
||||
@@ -642,8 +642,10 @@ Form* LoadVarOp::get_load_src(FormPool& pool, const Env& env) const {
|
||||
u64 value;
|
||||
memcpy(&value, &word0.data, 4);
|
||||
memcpy(((u8*)&value) + 4, &word1.data, 4);
|
||||
return pool.alloc_single_element_form<SimpleAtomElement>(
|
||||
nullptr, SimpleAtom::make_int_constant(value));
|
||||
return pool.alloc_single_element_form<CastElement>(
|
||||
nullptr, TypeSpec("uint"),
|
||||
pool.alloc_single_element_form<SimpleAtomElement>(
|
||||
nullptr, SimpleAtom::make_int_constant(value)));
|
||||
}
|
||||
|
||||
// is it a constant bitfield?
|
||||
@@ -797,4 +799,4 @@ FormElement* StackSpillStoreOp::get_as_form(FormPool& pool, const Env& env) cons
|
||||
|
||||
return pool.alloc_element<StackSpillStoreElement>(m_value, m_size, m_offset, cast_type);
|
||||
}
|
||||
} // namespace decompiler
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -547,7 +547,7 @@ std::vector<Form*> compact_nested_logiors(GenericElement* input, const Env&) {
|
||||
while (next) {
|
||||
assert(next->elts().size() == 2);
|
||||
result.push_back(next->elts().at(1));
|
||||
auto next_next = next->elts().at(0);
|
||||
auto next_next = strip_int_or_uint_cast(next->elts().at(0));
|
||||
next = next_next->try_as_element<GenericElement>();
|
||||
if (!next || !next->op().is_fixed(FixedOperatorKind::LOGIOR)) {
|
||||
result.push_back(next_next);
|
||||
@@ -778,4 +778,4 @@ Form* cast_to_bitfield_enum(const EnumType* type_info, FormPool& pool, const Env
|
||||
return pool.alloc_single_element_form<GenericElement>(nullptr, oper, form_elts);
|
||||
}
|
||||
|
||||
} // namespace decompiler
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -760,10 +760,8 @@ static void link_v3(LinkedObjectFile& f,
|
||||
link_ptr--;
|
||||
s_name = (const char*)(&data.at(link_ptr));
|
||||
} else {
|
||||
// methods todo
|
||||
|
||||
s_name = (const char*)(&data.at(link_ptr));
|
||||
// get_type_info().inform_type_method_count(s_name, reloc & 0x7f); todo
|
||||
dts.ts.forward_declare_type_method_count(s_name, reloc & 0x7f);
|
||||
kind = SymbolLinkKind::TYPE;
|
||||
}
|
||||
|
||||
|
||||
@@ -12736,7 +12736,7 @@
|
||||
(deftype entity-actor (entity)
|
||||
(
|
||||
(nav-mesh nav-mesh :offset-assert 52)
|
||||
(etype basic :offset-assert 56) ;; probably type
|
||||
(etype type :offset-assert 56) ;; probably type
|
||||
(task uint8 :offset-assert 60)
|
||||
(vis-id uint16 :offset-assert 62)
|
||||
(quat quaternion :inline :offset-assert 64)
|
||||
@@ -12754,9 +12754,9 @@
|
||||
)
|
||||
|
||||
(deftype entity-info (basic)
|
||||
((ptype basic :offset-assert 4)
|
||||
((ptype type :offset-assert 4)
|
||||
(package basic :offset-assert 8)
|
||||
(art-group basic :offset-assert 12)
|
||||
(art-group pair :offset-assert 12)
|
||||
(pool basic :offset-assert 16)
|
||||
(heap-size int32 :offset-assert 20)
|
||||
)
|
||||
@@ -15988,7 +15988,7 @@
|
||||
|
||||
;; - Unknowns
|
||||
|
||||
;;(define-extern *entity-info* object) ;; unknown type
|
||||
(define-extern *entity-info* (array entity-info))
|
||||
|
||||
|
||||
;; ----------------------
|
||||
|
||||
@@ -520,10 +520,6 @@
|
||||
["L10", "debug-sphere-table", true]
|
||||
],
|
||||
|
||||
"generic": [
|
||||
["L11", "(array generic-dma-foreground-sink)", true],
|
||||
["L12", "uint64", true]
|
||||
],
|
||||
"entity": [
|
||||
["L324", "float", true]
|
||||
],
|
||||
@@ -581,5 +577,15 @@
|
||||
["L227", "uint64", true],
|
||||
["L228", "uint64", true],
|
||||
["L229", "uint64", true]
|
||||
],
|
||||
|
||||
"generic": [
|
||||
["L10", "generic-dma-foreground-sink", true],
|
||||
["L11", "(array generic-dma-foreground-sink)", true],
|
||||
["L12", "uint64", true]
|
||||
],
|
||||
|
||||
"entity-table": [
|
||||
["L8", "(array entity-info)", true]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -686,5 +686,8 @@
|
||||
],
|
||||
"drawable-frag-count": [
|
||||
[[14, 20], "s5", "drawable-group"]
|
||||
],
|
||||
"generic-init-buffers": [
|
||||
[[39, 44], "v1", "dma-packet"]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2033,7 +2033,11 @@
|
||||
"v1-11":["v1-11", "dma-packet"]
|
||||
}
|
||||
},
|
||||
"add-debug-light": { "vars": { "s1-0":["s1-0", "rgba"]} }
|
||||
|
||||
|
||||
"add-debug-light": { "vars": { "s1-0":["s1-0", "rgba"]} },
|
||||
|
||||
"generic-init-buffers": {
|
||||
"vars": {
|
||||
"v1-8": ["packet", "dma-packet"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "data_decompile.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "common/type_system/Type.h"
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
#include "common/util/math_util.h"
|
||||
#include "common/log/log.h"
|
||||
@@ -269,15 +270,12 @@ goos::Object decompile_structure(const TypeSpec& type,
|
||||
|
||||
// check alignment
|
||||
auto offset_location = label.offset - type_info->get_offset();
|
||||
// if ((offset_location % 8) == 2) {
|
||||
// // TEMP HACK
|
||||
// lg::error("Data decompile was looking for a structure, but it looks like a pair instead.");
|
||||
// return decompile_pair(label, labels, words, ts);
|
||||
// }
|
||||
if (offset_location % 8) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("Structure type {} (type offset {}) has alignment {}, which is not valid.",
|
||||
type_info->get_name(), type_info->get_offset(), (offset_location % 8)));
|
||||
throw std::runtime_error(fmt::format(
|
||||
"Tried to decompile a structure with type type {} (type offset {}) at label {}, but it has "
|
||||
"alignment {}, which is not valid. {}",
|
||||
type_info->get_name(), type_info->get_offset(), label.name, (offset_location % 8),
|
||||
(offset_location & 0b10) ? "Maybe it is actually a pair?" : ""));
|
||||
}
|
||||
|
||||
// check enough room
|
||||
@@ -517,6 +515,17 @@ goos::Object decompile_structure(const TypeSpec& type,
|
||||
}
|
||||
} else if (word.kind == LinkedWord::EMPTY_PTR) {
|
||||
field_defs_out.emplace_back(field.name(), pretty_print::to_symbol("'()"));
|
||||
} else if (word.kind == LinkedWord::TYPE_PTR) {
|
||||
if (field.type() != TypeSpec("type")) {
|
||||
throw std::runtime_error(
|
||||
fmt::format("Field {} in type {} offset {} had a reference to type {}, but the "
|
||||
"type of the field is not type.",
|
||||
field.name(), actual_type.print(), field.offset(), word.symbol_name));
|
||||
}
|
||||
int method_count = ts.get_type_method_count(word.symbol_name);
|
||||
field_defs_out.emplace_back(
|
||||
field.name(), pretty_print::to_symbol(fmt::format("(type-ref {} :method-count {})",
|
||||
word.symbol_name, method_count)));
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
fmt::format("Field {} in type {} offset {} did not have a proper reference",
|
||||
|
||||
@@ -164,4 +164,5 @@
|
||||
- GOOS supports `string-ref`, `string-length`, `ash`, and characters can now be treated as a signed 8-bit number
|
||||
- Fixed a bug where saved xmm registers might be clobbered when calling a C++ function that wasn't `format`.
|
||||
- The `declare-type` form now supports any parent type. The type system will do a better job of trying to make things work out when only part of the type hierarchy is defined, and you can now chain type forward declarations. The compiler is stricter and will not accept forward declarations that are possibly incompatible. Instead, forward declare enough types and their parents for the compiler to be able to figure it out.
|
||||
- The `deftype` form is more strict and will throw an error if the type definition is in any way incompatible with existing forward declarations of types.
|
||||
- The `deftype` form is more strict and will throw an error if the type definition is in any way incompatible with existing forward declarations of types.
|
||||
- Added a `type-ref` form to insert a reference to a type into a static structure and optionally forward declare the number of methods
|
||||
@@ -160,7 +160,7 @@
|
||||
(declare-type nav-mesh basic)
|
||||
(deftype entity-actor (entity)
|
||||
((nav-mesh nav-mesh :offset-assert 52)
|
||||
(etype basic :offset-assert 56)
|
||||
(etype type :offset-assert 56)
|
||||
(task uint8 :offset-assert 60)
|
||||
(vis-id uint16 :offset-assert 62)
|
||||
(quat quaternion :inline :offset-assert 64)
|
||||
@@ -178,9 +178,9 @@
|
||||
|
||||
;; definition of type entity-info
|
||||
(deftype entity-info (basic)
|
||||
((ptype basic :offset-assert 4)
|
||||
((ptype type :offset-assert 4)
|
||||
(package basic :offset-assert 8)
|
||||
(art-group basic :offset-assert 12)
|
||||
(art-group pair :offset-assert 12)
|
||||
(pool basic :offset-assert 16)
|
||||
(heap-size int32 :offset-assert 20)
|
||||
)
|
||||
|
||||
@@ -5,3 +5,150 @@
|
||||
;; name in dgo: generic
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
; This is actually defined in generic-vu1.gc but this file builds first
|
||||
(define-extern generic-init-buf (function dma-buffer int uint none))
|
||||
|
||||
;; definition for symbol *generic-foreground-sinks*, type (array generic-dma-foreground-sink)
|
||||
(define
|
||||
*generic-foreground-sinks*
|
||||
(the-as (array generic-dma-foreground-sink)
|
||||
(new
|
||||
'static
|
||||
'boxed-array
|
||||
:type generic-dma-foreground-sink :length 0 :allocated-length 9
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 0)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level0 foreground-sink-group 0 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 1)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level0 foreground-sink-group 1 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 2)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level1 foreground-sink-group 0 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 3)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level1 foreground-sink-group 1 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 4)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level-default foreground-sink-group 0 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 5)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level-default foreground-sink-group 1 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 6)
|
||||
(new 'static 'generic-dma-foreground-sink :bucket 30)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 7)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level0 foreground-sink-group 2 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 8)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level1 foreground-sink-group 2 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function generic-dma-foreground-sink-init
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun generic-dma-foreground-sink-init ((arg0 generic-dma-foreground-sink))
|
||||
(set! (-> arg0 state gifbuf-adr) (the-as uint 837))
|
||||
(set! (-> arg0 state inbuf-adr) (the-as uint 9))
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function generic-init-buffers
|
||||
(defun generic-init-buffers ()
|
||||
(vu-lights-default! *default-lights*)
|
||||
(let ((gp-0 #x10001c0)
|
||||
(s5-0 (the-as uint #x1010001c0))
|
||||
)
|
||||
(dotimes (s4-0 9)
|
||||
(let ((s1-0 (-> *generic-foreground-sinks* s4-0)))
|
||||
(when s1-0
|
||||
(let* ((s3-0 (-> s1-0 bucket))
|
||||
(s0-0
|
||||
(-> *display* frames (-> *display* on-screen) frame global-buf)
|
||||
)
|
||||
(s2-0 (-> s0-0 base))
|
||||
)
|
||||
(if (>= s4-0 7)
|
||||
(generic-init-buf s0-0 1 s5-0)
|
||||
(generic-init-buf s0-0 1 (the-as uint gp-0))
|
||||
)
|
||||
(generic-dma-foreground-sink-init s1-0)
|
||||
(let ((a3-0 (-> s0-0 base)))
|
||||
(let ((packet (the-as dma-packet (-> s0-0 base))))
|
||||
(set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> packet vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s0-0 base) (&+ (the-as pointer packet) 16))
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) frame bucket-group)
|
||||
s3-0
|
||||
s2-0
|
||||
(the-as (pointer dma-tag) a3-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
#f
|
||||
)
|
||||
|
||||
;; definition for function generic-sink
|
||||
(defun generic-sink ((arg0 int))
|
||||
(-> *generic-foreground-sinks* arg0)
|
||||
)
|
||||
|
||||
@@ -215,4 +215,13 @@ StaticResult StaticResult::make_symbol(const std::string& name) {
|
||||
result.m_symbol = name;
|
||||
result.m_ts = TypeSpec("symbol");
|
||||
return result;
|
||||
}
|
||||
|
||||
StaticResult StaticResult::make_type_ref(const std::string& type_name, int method_count) {
|
||||
StaticResult result;
|
||||
result.m_kind = Kind::TYPE;
|
||||
result.m_symbol = type_name;
|
||||
result.m_method_count = method_count;
|
||||
result.m_ts = TypeSpec("type");
|
||||
return result;
|
||||
}
|
||||
@@ -101,13 +101,13 @@ class StaticResult {
|
||||
static StaticResult make_constant_data(const ConstantValue& data, TypeSpec ts);
|
||||
static StaticResult make_constant_data(u64 data, const TypeSpec& ts);
|
||||
static StaticResult make_symbol(const std::string& name);
|
||||
|
||||
std::string print() const;
|
||||
static StaticResult make_type_ref(const std::string& type_name, int method_count);
|
||||
|
||||
const TypeSpec& typespec() const { return m_ts; }
|
||||
bool is_reference() const { return m_kind == Kind::STRUCTURE_REFERENCE; }
|
||||
bool is_constant_data() const { return m_kind == Kind::CONSTANT_DATA; }
|
||||
bool is_symbol() const { return m_kind == Kind::SYMBOL; }
|
||||
bool is_type() const { return m_kind == Kind::TYPE; }
|
||||
|
||||
StaticStructure* reference() const {
|
||||
assert(is_reference());
|
||||
@@ -121,10 +121,15 @@ class StaticResult {
|
||||
}
|
||||
|
||||
const std::string& symbol_name() const {
|
||||
assert(is_symbol());
|
||||
assert(is_symbol() || is_type());
|
||||
return m_symbol;
|
||||
}
|
||||
|
||||
int method_count() const {
|
||||
assert(is_type());
|
||||
return m_method_count;
|
||||
}
|
||||
|
||||
u64 constant_u64() const {
|
||||
assert(is_constant_data() && m_constant_data && m_constant_data->size() == 8);
|
||||
return m_constant_data->value_64();
|
||||
@@ -145,10 +150,19 @@ class StaticResult {
|
||||
// used for only constant data
|
||||
std::optional<ConstantValue> m_constant_data;
|
||||
|
||||
// used for only symbol
|
||||
// used for only symbol and type
|
||||
std::string m_symbol;
|
||||
|
||||
enum class Kind { STRUCTURE_REFERENCE, CONSTANT_DATA, SYMBOL, INVALID } m_kind = Kind::INVALID;
|
||||
// used only for type
|
||||
int m_method_count = -1;
|
||||
|
||||
enum class Kind {
|
||||
STRUCTURE_REFERENCE,
|
||||
CONSTANT_DATA,
|
||||
SYMBOL,
|
||||
TYPE,
|
||||
INVALID
|
||||
} m_kind = Kind::INVALID;
|
||||
};
|
||||
|
||||
class StaticPair : public StaticStructure {
|
||||
|
||||
@@ -205,6 +205,12 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
|
||||
typecheck(form, field_info.type, sr.typespec());
|
||||
structure->add_pointer_record(field_offset, sr.reference(),
|
||||
sr.reference()->get_addr_offset());
|
||||
} else if (sr.is_type()) {
|
||||
if (field_info.type != TypeSpec("type")) {
|
||||
throw_compiler_error(form, "Cannot put a type reference in a field with type {}",
|
||||
field_info.type.print());
|
||||
}
|
||||
structure->add_type_record(sr.symbol_name(), field_offset);
|
||||
} else {
|
||||
throw_compiler_error(form, "Unsupported field value {}.", field_value.print());
|
||||
}
|
||||
@@ -669,6 +675,37 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (first.is_symbol("type-ref")) {
|
||||
auto args = get_va(form, rest);
|
||||
va_check(form, args, {goos::ObjectType::SYMBOL},
|
||||
{{{"method-count", {false, goos::ObjectType::INTEGER}}}});
|
||||
|
||||
auto type_name = args.unnamed.at(0).as_symbol()->name;
|
||||
|
||||
std::optional<int> expected_method_count = m_ts.try_get_type_method_count(type_name);
|
||||
int method_count = -1;
|
||||
|
||||
if (args.has_named("method-count")) {
|
||||
method_count = args.get_named("method-count").as_int();
|
||||
if (expected_method_count && (method_count != *expected_method_count)) {
|
||||
throw_compiler_error(
|
||||
form, "type-ref wanted {} methods for type {}, but the type system thinks it has {}",
|
||||
method_count, type_name, *expected_method_count);
|
||||
}
|
||||
} else {
|
||||
if (!expected_method_count) {
|
||||
throw_compiler_error(
|
||||
form,
|
||||
"Cannot create a static type reference for type {}. The type-ref form did not have a "
|
||||
":method-count argument and the type system does not know how many methods it has.",
|
||||
type_name);
|
||||
}
|
||||
method_count = *expected_method_count;
|
||||
}
|
||||
|
||||
m_ts.forward_declare_type_method_count(type_name, method_count);
|
||||
|
||||
return StaticResult::make_type_ref(type_name, method_count);
|
||||
} else {
|
||||
// maybe an enum
|
||||
s64 int_out;
|
||||
|
||||
@@ -124,7 +124,7 @@ void Compiler::generate_field_description(const goos::Object& form,
|
||||
const Field& f) {
|
||||
std::string str_template;
|
||||
std::vector<RegVal*> format_args = {};
|
||||
if (m_ts.tc(m_ts.make_typespec("type"), f.type())) {
|
||||
if (f.name() == "type" && f.offset() == 0) {
|
||||
// type
|
||||
return;
|
||||
} else if (f.is_array() && !f.is_dynamic()) {
|
||||
|
||||
@@ -458,7 +458,7 @@ void ObjectGenerator::emit_link_type_pointer(int seg, const TypeSystem* ts) {
|
||||
out.push_back(0);
|
||||
|
||||
// method count
|
||||
out.push_back(ts->get_next_method_id(ts->lookup_type(rec.first)));
|
||||
out.push_back(ts->get_type_method_count(rec.first));
|
||||
|
||||
// number of links
|
||||
push_data<u32>(size, out);
|
||||
|
||||
@@ -264,7 +264,7 @@
|
||||
(defun clear-vu0-mem ()
|
||||
(let ((v1-0 (the-as (pointer uint32) #x11004000)))
|
||||
(dotimes (a0-0 1024)
|
||||
(set! (-> v1-0 a0-0) #xabadbeef)
|
||||
(set! (-> v1-0 a0-0) (the-as uint #xabadbeef))
|
||||
)
|
||||
)
|
||||
(let ((v0-0 0))
|
||||
@@ -277,7 +277,7 @@
|
||||
(defun clear-vu1-mem ()
|
||||
(let ((v1-0 (the-as (pointer uint32) #x1100c000)))
|
||||
(dotimes (a0-0 4096)
|
||||
(set! (-> v1-0 a0-0) #xabadbeef)
|
||||
(set! (-> v1-0 a0-0) (the-as uint #xabadbeef))
|
||||
)
|
||||
)
|
||||
(let ((v0-0 0))
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
;; definition of type entity-actor
|
||||
(deftype entity-actor (entity)
|
||||
((nav-mesh nav-mesh :offset-assert 52)
|
||||
(etype basic :offset-assert 56)
|
||||
(etype type :offset-assert 56)
|
||||
(task uint8 :offset-assert 60)
|
||||
(vis-id uint16 :offset-assert 62)
|
||||
(quat quaternion :inline :offset-assert 64)
|
||||
@@ -252,9 +252,9 @@
|
||||
|
||||
;; definition of type entity-info
|
||||
(deftype entity-info (basic)
|
||||
((ptype basic :offset-assert 4)
|
||||
((ptype type :offset-assert 4)
|
||||
(package basic :offset-assert 8)
|
||||
(art-group basic :offset-assert 12)
|
||||
(art-group pair :offset-assert 12)
|
||||
(pool basic :offset-assert 16)
|
||||
(heap-size int32 :offset-assert 20)
|
||||
)
|
||||
|
||||
@@ -100,7 +100,3 @@
|
||||
(defun get-aspect-ratio ()
|
||||
(-> *setting-control* current aspect-ratio)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
;; definition for symbol *generic-foreground-sinks*, type (array generic-dma-foreground-sink)
|
||||
(define
|
||||
*generic-foreground-sinks*
|
||||
(the-as (array generic-dma-foreground-sink)
|
||||
(new
|
||||
'static
|
||||
'boxed-array
|
||||
:type generic-dma-foreground-sink :length 0 :allocated-length 9
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 0)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level0 foreground-sink-group 0 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 1)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level0 foreground-sink-group 1 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 2)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level1 foreground-sink-group 0 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 3)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level1 foreground-sink-group 1 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 4)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level-default foreground-sink-group 0 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 5)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level-default foreground-sink-group 1 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 6)
|
||||
(new 'static 'generic-dma-foreground-sink :bucket 30)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 7)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level0 foreground-sink-group 2 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set!
|
||||
(-> *generic-foreground-sinks* 8)
|
||||
(the-as
|
||||
generic-dma-foreground-sink
|
||||
(-> *level* level1 foreground-sink-group 2 merc-sink)
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function generic-dma-foreground-sink-init
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun generic-dma-foreground-sink-init ((arg0 generic-dma-foreground-sink))
|
||||
(set! (-> arg0 state gifbuf-adr) (the-as uint 837))
|
||||
(set! (-> arg0 state inbuf-adr) (the-as uint 9))
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function generic-init-buffers
|
||||
(defun generic-init-buffers ()
|
||||
(vu-lights-default! *default-lights*)
|
||||
(let ((gp-0 #x10001c0)
|
||||
(s5-0 (the-as uint #x1010001c0))
|
||||
)
|
||||
(dotimes (s4-0 9)
|
||||
(let ((s1-0 (-> *generic-foreground-sinks* s4-0)))
|
||||
(when s1-0
|
||||
(let* ((s3-0 (-> s1-0 bucket))
|
||||
(s0-0
|
||||
(-> *display* frames (-> *display* on-screen) frame global-buf)
|
||||
)
|
||||
(s2-0 (-> s0-0 base))
|
||||
)
|
||||
(if (>= s4-0 7)
|
||||
(generic-init-buf s0-0 1 s5-0)
|
||||
(generic-init-buf s0-0 1 (the-as uint gp-0))
|
||||
)
|
||||
(generic-dma-foreground-sink-init s1-0)
|
||||
(let ((a3-0 (-> s0-0 base)))
|
||||
(let ((packet (the-as dma-packet (-> s0-0 base))))
|
||||
(set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
||||
(set! (-> packet vif0) (new 'static 'vif-tag))
|
||||
(set! (-> packet vif1) (new 'static 'vif-tag))
|
||||
(set! (-> s0-0 base) (&+ (the-as pointer packet) 16))
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) frame bucket-group)
|
||||
s3-0
|
||||
s2-0
|
||||
(the-as (pointer dma-tag) a3-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
#f
|
||||
)
|
||||
|
||||
;; definition for function generic-sink
|
||||
(defun generic-sink ((arg0 int))
|
||||
(-> *generic-foreground-sinks* arg0)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
(defun destroy-mem ((arg0 (pointer uint32)) (arg1 (pointer uint32)))
|
||||
(while (< (the-as int arg0) (the-as int arg1))
|
||||
(set! (-> arg0 0) #xffffffff)
|
||||
(set! (-> arg0 0) (the-as uint #xffffffff))
|
||||
(set! arg0 (&-> arg0 1))
|
||||
)
|
||||
(let ((v0-0 0))
|
||||
|
||||
@@ -160,7 +160,10 @@
|
||||
;; definition for method 5 of type type
|
||||
;; INFO: Return type mismatch uint vs int.
|
||||
(defmethod asize-of type ((obj type))
|
||||
(the-as int (logand #xfffffff0 (+ (* (-> obj allocated-length) 4) 43)))
|
||||
(the-as
|
||||
int
|
||||
(logand (the-as uint #xfffffff0) (+ (* (-> obj allocated-length) 4) 43))
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function basic-type?
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
;; define a type with fields that hold a type.
|
||||
(deftype test-type-with-type-field (basic)
|
||||
((name string)
|
||||
(some-type-1 type)
|
||||
(some-type-2 type))
|
||||
)
|
||||
|
||||
(let ((obj (new 'static 'test-type-with-type-field
|
||||
:name "test"
|
||||
:some-type-2 (type-ref some-unknown-type :method-count 20)
|
||||
:some-type-1 (type-ref string :method-count 9)))
|
||||
(old-string string))
|
||||
(format #t "~A ~A ~A ~A ~D ~D~%"
|
||||
(-> obj some-type-1 symbol)
|
||||
(= (-> obj some-type-1) old-string) ;; should not reallocate string
|
||||
(-> obj some-type-1 parent)
|
||||
(-> obj some-type-2 symbol) ;; should fill out type symbol
|
||||
(-> obj some-type-2 allocated-length) ;; and method length
|
||||
(-> obj some-type-2 parent) ;; but other stuff should be 0's
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -621,6 +621,12 @@ TEST_F(WithGameTests, StaticArrayField) {
|
||||
"0\n"});
|
||||
}
|
||||
|
||||
TEST_F(WithGameTests, TypeReference) {
|
||||
runner.run_static_test(env, testCategory, "test-type-ref.gc",
|
||||
{"string #t basic some-unknown-type 20 0\n"
|
||||
"0\n"});
|
||||
}
|
||||
|
||||
TEST_F(WithGameTests, StaticFieldInlineArray) {
|
||||
runner.run_static_test(env, testCategory, "test-static-field-inline-arrays.gc",
|
||||
{"\"second\" \"first\"\n"
|
||||
|
||||
Reference in New Issue
Block a user