[Decomp] Decompile gcommon, gstring-h, and gkernel-h (#249)

* begin decomp

* untabify

* finish decomp of gcommon

* warning with function name

* clean up gkernel-h

* fix all types
This commit is contained in:
water111
2021-02-11 09:49:15 -05:00
committed by GitHub
parent 6e0ff4c9d0
commit 43c1d223a6
19 changed files with 1403 additions and 519 deletions
+1 -1
View File
@@ -474,7 +474,7 @@ void insertSpecialBreaks(NodePool& pool, PrettyPrinterNode* node) {
}
}
if (name == "defun" || name == "defmethod") {
if (name == "defun" || name == "defmethod" || name == "defun-debug") {
auto* parent_type_dec = getNextListOnLine(node);
if (parent_type_dec) {
insertNewlineAfter(pool, parent_type_dec->paren, 0);
+4
View File
@@ -91,6 +91,10 @@ TP_Type SimpleAtom::get_type(const TypeState& input,
return TP_Type::make_type_object(TypeSpec(m_string));
}
if (type->second == TypeSpec("function")) {
lg::warn("Function {} has unknown type", m_string);
}
// otherwise, just return a normal typespec
return TP_Type::make_from_ts(type->second);
}
+4 -4
View File
@@ -704,12 +704,12 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
allow_side_effects);
break;
case SimpleExpression::Kind::RIGHT_SHIFT_LOGIC:
update_from_stack_force_ui_2(env, FixedOperatorKind::SHR, pool, stack, result,
allow_side_effects);
update_from_stack_copy_first_int_2(env, FixedOperatorKind::SHR, pool, stack, result,
allow_side_effects);
break;
case SimpleExpression::Kind::RIGHT_SHIFT_ARITH:
update_from_stack_force_si_2(env, FixedOperatorKind::SAR, pool, stack, result,
allow_side_effects);
update_from_stack_copy_first_int_2(env, FixedOperatorKind::SAR, pool, stack, result,
allow_side_effects);
break;
case SimpleExpression::Kind::MUL_UNSIGNED:
update_from_stack_force_ui_2(env, FixedOperatorKind::MULTIPLICATION, pool, stack, result,
+46
View File
@@ -89,6 +89,15 @@ Matcher Matcher::symbol(const std::string& name) {
return m;
}
Matcher Matcher::if_with_else(const Matcher& condition,
const Matcher& true_case,
const Matcher& false_case) {
Matcher m;
m.m_kind = Kind::IF_WITH_ELSE;
m.m_sub_matchers = {condition, true_case, false_case};
return m;
}
Matcher Matcher::deref(const Matcher& root,
bool is_addr_of,
const std::vector<DerefTokenMatcher>& tokens) {
@@ -367,6 +376,30 @@ bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out) const {
}
} break;
case Kind::IF_WITH_ELSE: {
auto as_cond = dynamic_cast<CondWithElseElement*>(input->try_as_single_element());
if (!as_cond) {
return false;
}
if (as_cond->entries.size() != 1) {
return false;
}
if (!m_sub_matchers.at(0).do_match(as_cond->entries.front().condition, maps_out)) {
return false;
}
if (!m_sub_matchers.at(1).do_match(as_cond->entries.front().body, maps_out)) {
return false;
}
if (!m_sub_matchers.at(2).do_match(as_cond->else_ir, maps_out)) {
return false;
}
return true;
} break;
default:
assert(false);
return false;
@@ -429,6 +462,13 @@ GenericOpMatcher GenericOpMatcher::func(const Matcher& func_matcher) {
return m;
}
GenericOpMatcher GenericOpMatcher::condition(IR2_Condition::Kind condition) {
GenericOpMatcher m;
m.m_kind = Kind::CONDITION;
m.m_condition_kind = condition;
return m;
}
bool GenericOpMatcher::do_match(GenericOperator& input, MatchResult::Maps* maps_out) const {
switch (m_kind) {
case Kind::FIXED:
@@ -441,8 +481,14 @@ bool GenericOpMatcher::do_match(GenericOperator& input, MatchResult::Maps* maps_
return m_func_matcher.do_match(input.func(), maps_out);
}
return false;
case Kind::CONDITION:
if (input.kind() == GenericOperator::Kind::CONDITION_OPERATOR) {
return input.condition_kind() == m_condition_kind;
}
return false;
default:
assert(false);
}
}
} // namespace decompiler
+7 -1
View File
@@ -40,6 +40,9 @@ class Matcher {
static Matcher deref(const Matcher& root,
bool is_addr_of,
const std::vector<DerefTokenMatcher>& tokens);
static Matcher if_with_else(const Matcher& condition,
const Matcher& true_case,
const Matcher& false_case);
enum class Kind {
ANY_REG, // matching any register
@@ -55,6 +58,7 @@ class Matcher {
SET,
ANY_LABEL,
SYMBOL,
IF_WITH_ELSE,
INVALID
};
@@ -95,14 +99,16 @@ class GenericOpMatcher {
public:
static GenericOpMatcher fixed(FixedOperatorKind kind);
static GenericOpMatcher func(const Matcher& func_matcher);
static GenericOpMatcher condition(IR2_Condition::Kind condition);
enum class Kind { FIXED, FUNC, INVALID };
enum class Kind { FIXED, FUNC, CONDITION, INVALID };
bool do_match(GenericOperator& input, MatchResult::Maps* maps_out) const;
private:
Kind m_kind = Kind::INVALID;
FixedOperatorKind m_fixed_kind = FixedOperatorKind::INVALID;
IR2_Condition::Kind m_condition_kind = IR2_Condition::Kind::INVALID;
Matcher m_func_matcher;
};
+5
View File
@@ -199,6 +199,11 @@ bool convert_to_expressions(Form* top_level_form,
map2 = var_map->second;
}
f.ir2.env.map_args_from_config(config_map->second, map2);
} else {
auto var_map = get_config().function_var_names.find(f.guessed_name.to_string());
if (var_map != get_config().function_var_names.end()) {
f.ir2.env.map_args_from_config({}, var_map->second);
}
}
// strip out coloring moves
+43 -4
View File
@@ -21,7 +21,10 @@ void append(goos::Object& _in, const goos::Object& add) {
}
} // namespace
std::string final_defun_out(const Function& func, const Env& env, const DecompilerTypeSystem& dts) {
std::string final_defun_out(const Function& func,
const Env& env,
const DecompilerTypeSystem& dts,
FunctionDefSpecials special_mode) {
std::vector<goos::Object> inline_body;
func.ir2.top_form->inline_forms(inline_body, env);
@@ -39,8 +42,14 @@ std::string final_defun_out(const Function& func, const Env& env, const Decompil
auto arguments = pretty_print::build_list(argument_elts);
if (func.guessed_name.kind == FunctionName::FunctionKind::GLOBAL) {
std::string def_name = "defun";
if (special_mode == FunctionDefSpecials::DEFUN_DEBUG) {
def_name = "defun-debug";
} else {
assert(special_mode == FunctionDefSpecials::NONE);
}
std::vector<goos::Object> top;
top.push_back(pretty_print::to_symbol("defun"));
top.push_back(pretty_print::to_symbol(def_name));
top.push_back(pretty_print::to_symbol(func.guessed_name.to_string()));
top.push_back(arguments);
auto top_form = pretty_print::build_list(top);
@@ -54,6 +63,7 @@ std::string final_defun_out(const Function& func, const Env& env, const Decompil
}
if (func.guessed_name.kind == FunctionName::FunctionKind::METHOD) {
assert(special_mode == FunctionDefSpecials::NONE);
std::vector<goos::Object> top;
top.push_back(pretty_print::to_symbol("defmethod"));
auto method_info =
@@ -72,6 +82,7 @@ std::string final_defun_out(const Function& func, const Env& env, const Decompil
}
if (func.guessed_name.kind == FunctionName::FunctionKind::TOP_LEVEL_INIT) {
assert(special_mode == FunctionDefSpecials::NONE);
std::vector<goos::Object> top;
top.push_back(pretty_print::to_symbol("top-level-function"));
top.push_back(arguments);
@@ -88,7 +99,10 @@ std::string final_defun_out(const Function& func, const Env& env, const Decompil
}
namespace {
std::string careful_function_to_string(const Function* func, const DecompilerTypeSystem& dts) {
std::string careful_function_to_string(
const Function* func,
const DecompilerTypeSystem& dts,
FunctionDefSpecials special_mode = FunctionDefSpecials::NONE) {
auto& env = func->ir2.env;
if (!func->ir2.top_form) {
return ";; ERROR: function was not converted to expressions. Cannot decompile.\n\n";
@@ -105,7 +119,7 @@ std::string careful_function_to_string(const Function* func, const DecompilerTyp
return ";; ERROR: function has no register use analysis. Cannot decompile.\n\n";
}
return final_defun_out(*func, func->ir2.env, dts) + "\n\n";
return final_defun_out(*func, func->ir2.env, dts, special_mode) + "\n\n";
}
} // namespace
@@ -151,6 +165,14 @@ std::string write_from_top_level(const Function& top_level,
Matcher::op_with_rest(GenericOpMatcher::fixed(FixedOperatorKind::TYPE_NEW),
{Matcher::any_quoted_symbol(type_name)});
// (if *debug-segment* (set! mem-print L347) (set! mem-print nothing))
auto debug_seg_matcher = Matcher::op(GenericOpMatcher::condition(IR2_Condition::Kind::TRUTHY),
{Matcher::symbol("*debug-segment*")});
auto debug_def_matcher = Matcher::set(Matcher::any_symbol(0), Matcher::any_label(1));
auto non_debug_def_matcher = Matcher::set(Matcher::any_symbol(2), Matcher::symbol("nothing"));
auto defun_debug_matcher =
Matcher::if_with_else(debug_seg_matcher, debug_def_matcher, non_debug_def_matcher);
for (auto& x : top_form->elts()) {
bool something_matched = false;
Form f;
@@ -190,6 +212,23 @@ std::string write_from_top_level(const Function& top_level,
}
}
if (!something_matched) {
auto debug_match_result = match(defun_debug_matcher, &f);
if (debug_match_result.matched) {
auto first_name = debug_match_result.maps.strings.at(0);
auto second_name = debug_match_result.maps.strings.at(2);
if (first_name == second_name) {
auto func = file.try_get_function_at_label(debug_match_result.maps.label.at(1));
if (func) {
something_matched = true;
result += fmt::format(";; definition (debug) for function {}\n",
debug_match_result.maps.strings.at(0));
result += careful_function_to_string(func, dts, FunctionDefSpecials::DEFUN_DEBUG);
}
}
}
}
if (!something_matched) {
result += ";; failed to figure out what this is:\n";
result += pretty_print::to_string(x->to_form(env));
+7 -1
View File
@@ -3,7 +3,13 @@
#include "decompiler/Function/Function.h"
namespace decompiler {
std::string final_defun_out(const Function& func, const Env& env, const DecompilerTypeSystem& dts);
enum class FunctionDefSpecials { NONE, DEFUN_DEBUG };
std::string final_defun_out(const Function& func,
const Env& env,
const DecompilerTypeSystem& dts,
FunctionDefSpecials special_mode = FunctionDefSpecials::NONE);
std::string write_from_top_level(const Function& top_level,
const DecompilerTypeSystem& dts,
const LinkedObjectFile& file);
+12 -5
View File
@@ -155,7 +155,7 @@
(define-extern valid? (function object type basic basic object symbol))
;; has issues:
(define-extern breakpoint-range-set! function)
(define-extern breakpoint-range-set! (function uint uint uint int))
@@ -224,8 +224,12 @@
;; gkernel-h
(deftype cpu-thread (thread)
((rreg uint64 8 :offset-assert 40)
(freg float 6 :offset-assert 104)
(
;;(rreg uint64 8 :offset-assert 40)
;;(freg float 6 :offset-assert 104)
;; changed from GOAL, see gkernel-h.gc
(rreg uint64 7 :offset-assert 40)
(freg float 8)
(stack uint8 :dynamic :offset-assert 128)
)
@@ -378,8 +382,11 @@
(deftype catch-frame (stack-frame)
((sp int32 :offset-assert 12)
(ra int32 :offset-assert 16)
(freg float 6 :offset-assert 20)
(rreg uint128 8 :offset-assert 48)
;; changed from GOAL, see gkernel-h.gc
(freg float 10 :offset-assert 20)
(rreg uint128 7)
;;(freg float 6 :offset-assert 20)
;;(rreg uint128 8 :offset-assert 48)
)
(:methods
@@ -93,10 +93,6 @@
"part-tracker"],
"no_type_analysis_functions_by_name":[
"(method 2 vec4s)", // 128-bit bitfield.
"(method 3 vec4s)", // 128-bit bitfield
"qmem-copy<-!", // 128-bit loads and stores
"qmem-copy->!", // 128-bit loads and stores
"breakpoint-range-set!", // messing with COP0 registers
"(method 0 catch-frame)", // kernel asm
"throw-dispatch", // kernel asm
@@ -32,9 +32,10 @@
],
"(method 2 handle)":[
[10, ["a3", "process"]],
[11, ["v1", "int"]],
[15, ["gp", "int"]]
[10, ["a2", "(pointer process)"]],
[11, ["a3", "process"]],
[12, ["v1", "int"]],
[16, ["gp", "int"]]
],
"(method 3 handle)":[
@@ -83,74 +83,115 @@
},
"ref":{
"args":["lst", "index"]
"args":["lst", "index"],
"vars":{"v1-0":"count"}
},
"(method 4 pair)": {
"vars":{"v0-0":"result", "v1-1":"iter"}
},
"last":{
"args":["lst"]
"args":["lst"],
"vars":{"v0-0":"iter"}
},
"member":{
"args":["obj", "lst"]
"args":["obj", "lst"],
"vars":{"v1-0":"iter"}
},
"nmember":{
"args":["obj", "lst"]
},
"assoc":{
"args":["item", "alist"]
"args":["item", "alist"],
"vars":{"v1-0":"iter"}
},
"assoce":{
"args":["item", "alist"]
"args":["item", "alist"],
"vars":{"v1-0":"iter"}
},
"nassoc":{
"args":["item-name", "alist"]
"args":["item-name", "alist"],
"vars":{"a1-1":"key"}
},
"nassoce":{
"args":["item-name", "alist"]
"args":["item-name", "alist"],
"vars":{"s4-0":"key"}
},
"append!":{
"args":["front", "back"]
"args":["front", "back"],
"vars":{"v1-1":"iter"}
},
"delete!":{
"args":["item", "lst"]
"args":["item", "lst"],
"vars":{"a2-0":"iter", "v1-1":"iter-prev"}
},
"delete-car!":{
"args":["item", "lst"]
"args":["item", "lst"],
"vars":{"a2-0":"iter", "v1-2":"iter-prev"}
},
"insert-cons!":{
"args":["kv", "alist"]
"args":["kv", "alist"],
"vars":{"a3-0":"updated-list"}
},
"sort":{
"args":["lst", "compare-func"]
"args":["lst", "compare-func"],
"vars":{"s4-0":"unsorted-count", "s3-0":"iter", "s2-0":"first-elt", "s1-0":"seoncd-elt", "v1-1":"compare-result"}
},
"(method 0 inline-array)":{
"args":["allocation", "type-to-make", "size"]
"(method 0 inline-array-class)":{
"args":["allocation", "type-to-make", "size"],
"vars":{"v0-0":"obj"}
},
"(method 0 array)":{
"args":["allocation", "type-to-make", "content-type", "size"]
"args":["allocation", "type-to-make", "content-type", "len"],
"vars":{"v0-1":"obj"}
},
"(method 2 array)":{
"vars":{"v1-1":"content-type-sym","s5-0":"i","s5-1":"i","s5-2":"i"
,"s5-3":"i","s5-4":"i","s5-5":"i","s5-6":"i","s5-7":"i","s5-8":"i",
"s5-9":"i","s5-10":"i","s5-11":"i"}
},
"(method 3 array)":{
"vars":{"v1-1":"content-type-sym","s5-0":"i","s5-1":"i","s5-2":"i"
,"s5-3":"i","s5-4":"i","s5-5":"i","s5-6":"i","s5-7":"i","s5-8":"i","s5-9":"i","s5-10":"i","s5-11":"i"}
},
"mem-copy!":{
"args":["dst", "src", "size"]
"args":["dst", "src", "size"],
"vars":{"v0-0":"result", "v1-0":"i"}
},
"qmem-copy<-!":{
"args":["dst", "src", "size"]
"args":["dst", "src", "size"],
"vars":{"v0-0":"result", "v1-1":"qwc", "a2-1":"value"}
},
"qmem-copy->!":{
"args":["dst", "src", "size"]
"args":["dst", "src", "size"],
"vars":{"v0-0":"result", "v1-1":"qwc", "a0-1":"src-ptr", "a1-1":"dst-ptr", "a2-3":"value"}
},
"mem-set32!":{
"args":["dst", "size", "value"]
"args":["dst", "size", "value"],
"vars":{"v0-0":"result", "v1-0":"i"}
},
"mem-or!":{
"args":["dst", "src", "size"]
"args":["dst", "src", "size"],
"vars":{"v0-0":"result", "v1-0":"i"}
},
"fact":{
"args":["x"]
},
"mem-print":{
"args":["data", "word-count"],
"vars":{"s4-0":"current-qword"}
},
"print-tree-bitmask":{
"args":["bits", "count"]
"args":["bits", "count"],
"vars":{"s4-0":"i"}
},
"valid?":{
"args":["obj", "expected-type", "name", "allow-false", "print-dest"]
"args":["obj", "expected-type", "name", "allow-false", "print-dest"],
"vars":{"v1-1":"in-goal-mem"}
}
+6 -1
View File
@@ -396,7 +396,12 @@
(defmacro pair? (obj)
;; todo, make this more efficient
`(= 2 (logand (the integer ,obj) #b111))
;`(= 2 (logand (the integer ,obj) #b111))
`(< (shl (the-as int ,obj) 62) 0)
)
(defmacro not-pair? (obj)
`(>= (shl (the-as int ,obj) 62) 0)
)
(defmacro binteger? (obj)
+1060 -358
View File
File diff suppressed because it is too large Load Diff
+135 -109
View File
@@ -54,34 +54,35 @@
;; ENUMS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; bitfield enum to indicate proprties about a process-tree
(defenum process-mask :bitfield #t :type int32
(execute 0) ; 1
(draw 1) ; 2
(pause 2) ; 4
(menu 3) ; 8
(progress 4) ; 16
(actor-pause 5) ; 32
(sleep 6) ; 64
(sleep-code 7) ; 128
(process-tree 8) ; 256 ; not an actual process, just a "tree node" for organization
(heap-shrunk 9) ; 512
(going 10) ; 1024
(movie 11) ; 2048
(movie-subject 12) ; 4096
(target 13) ; 8192
(sidekick 14) ; 16384
(crate 15) ; 32768
(collectable 16) ; 65536
(enemy 17) ; 131072
(camera 18) ; 262144
(platform 19) ; 524288
(ambient 20) ; 1048576
(entity 21) ; 2097152
(projectile 22) ; 4194304
(attackable 23) ; 8388608
(death 24) ; 16777216
)
;; bitfield enum to indicate proprties about a process-tree
(defenum process-mask
:bitfield #t :type int32
(execute 0) ;; 1
(draw 1) ;; 2
(pause 2) ;; 4
(menu 3) ;; 8
(progress 4) ;; 16
(actor-pause 5) ;; 32
(sleep 6) ;; 64
(sleep-code 7) ;; 128
(process-tree 8) ;; 256 not an actual process, just a "tree node" for organization
(heap-shrunk 9) ;; 512
(going 10) ;; 1024
(movie 11) ;; 2048
(movie-subject 12) ;; 4096
(target 13) ;; 8192
(sidekick 14) ;; 16384
(crate 15) ;; 32768
(collectable 16) ;; 65536
(enemy 17) ;; 131072
(camera 18) ;; 262144
(platform 19) ;; 524288
(ambient 20) ;; 1048576
(entity 21) ;; 2097152
(projectile 22) ;; 4194304
(attackable 23) ;; 8388608
(death 24) ;; 16777216
)
;; -961
(defconstant PROCESS_CLEAR_MASK
@@ -96,10 +97,8 @@
`(/ 0 0)
)
;; todo, process check and set
(defmacro msg-err (&rest args)
;"Print a message to stdout immediately. This won't appear in the compiler."
;; "Print a message to stdout immediately. This won't appear in the compiler."
`(format 0 ,@args)
)
@@ -107,12 +106,6 @@
`(format 0 ,@args)
)
;; todo process pointer
;; todo process memory usage
;; with pp
;; todo suspend
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TYPES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -123,7 +116,7 @@
(require-for-run uint32 :offset-assert 8)
(allow-to-run uint32 :offset-assert 12)
(next-pid int32 :offset-assert 16)
(fast-stack-top pointer :offset-assert 20)
(fast-stack-top pointer :offset-assert 20)
(current-process basic :offset-assert 24)
(relocating-process basic :offset-assert 28)
(relocating-min int32 :offset-assert 32)
@@ -151,23 +144,23 @@
; DANGER - this type is created in kscheme.cpp. It has room for 12 methods and size 0x28 bytes.
(deftype thread (basic)
((name basic :offset-assert 4) ;; name of the thread (usually a symbol?)
(process process :offset-assert 8) ;; process that the thread belongs to
(previous thread :offset-assert 12) ;; previous thread that was running in the process
(suspend-hook (function cpu-thread none) :offset-assert 16) ;; function to suspend this thread
(resume-hook (function cpu-thread none) :offset-assert 20) ;; function to resume this thread
(pc pointer :offset-assert 24) ;; program counter of the thread
(sp pointer :offset-assert 28) ;; stack pointer of the thread (actual stack)
(stack-top pointer :offset-assert 32) ;; top of the thread's stack (actual stack)
(stack-size int32 :offset-assert 36) ;; size of the thread's stack (backup stack)
((name basic :offset-assert 4) ;; name of the thread (usually a symbol?)
(process process :offset-assert 8) ;; process that the thread belongs to
(previous thread :offset-assert 12) ;; previous thread that was running in the process
(suspend-hook (function cpu-thread none) :offset-assert 16) ;; function to suspend this thread
(resume-hook (function cpu-thread none) :offset-assert 20) ;; function to resume this thread
(pc pointer :offset-assert 24) ;; program counter of the thread
(sp pointer :offset-assert 28) ;; stack pointer of the thread (actual stack)
(stack-top pointer :offset-assert 32) ;; top of the thread's stack (actual stack)
(stack-size int32 :offset-assert 36) ;; size of the thread's stack (backup stack)
)
(:methods
;; todo, triple check these method numbers.
(stack-size-set! ((this thread) (stack-size int)) none 9)
(thread-suspend ((this _type_)) none 10) ;; only safe on a cpu-thread, but slot exists for thread
(thread-resume ((to-resume _type_)) none 11) ;; only safe on a cpu-thread, but slot exists for thread
)
;; todo, triple check these method numbers.
(stack-size-set! ((this thread) (stack-size int)) none 9)
(thread-suspend ((this _type_)) none 10) ;; only safe on a cpu-thread, but slot exists for thread
(thread-resume ((to-resume _type_)) none 11) ;; only safe on a cpu-thread, but slot exists for thread
)
:size-assert #x28
:method-count-assert 12
@@ -177,16 +170,24 @@
;; A CPU thread is a thread which has some memory to save registers and a stack
(deftype cpu-thread (thread)
((rreg uint64 8 :offset-assert 40) ;; general purpose saved registers
(freg float 6 :offset-assert 104) ;; floating point registers
(stack uint8 :dynamic :offset-assert 128) ;; stack memory (dynamic array)
(
;; This is what GOAL did:
;; (rreg uint64 8 :offset-assert 40) ;; general purpose saved registers
;; (freg float 6 :offset-assert 104) ;; floating point registers
;; OpenGOAL has only 5 saved registers but 8 fregs, so we swap a rreg for 2 fregs.
(rreg uint64 7 :offset-assert 40)
(freg float 8)
;; This is the same between GOAL and OpenGOAL
(stack uint8 :dynamic :offset-assert 128) ;; stack memory (dynamic array)
)
(:methods
(new ((allocation symbol) (type-to-make type) (parent-process process) (name symbol) (stack-size int) (stack-top pointer)) _type_ 0)
(thread-suspend ((this _type_)) none 10)
(thread-resume ((to-resume _type_)) none 11)
)
(new ((allocation symbol) (type-to-make type) (parent-process process) (name symbol) (stack-size int) (stack-top pointer)) _type_ 0)
(thread-suspend ((this _type_)) none 10)
(thread-resume ((to-resume _type_)) none 11)
)
:size-assert #x80
:method-count-assert 12
@@ -207,13 +208,13 @@
)
(:methods
(new ((allocation symbol) (type-to-make type) (name basic)) _type_ 0)
(activate ((obj _type_) (dest process-tree) (name basic) (stack-top pointer)) process-tree 9)
(deactivate ((obj _type_)) none 10)
(dummy-method-11 () none 11)
(run-logic? ((obj _type_)) symbol 12)
(dummy-method () none 13)
)
(new ((allocation symbol) (type-to-make type) (name basic)) _type_ 0)
(activate ((obj _type_) (dest process-tree) (name basic) (stack-top pointer)) process-tree 9)
(deactivate ((obj _type_)) none 10)
(dummy-method-11 () none 11)
(run-logic? ((obj _type_)) symbol 12)
(dummy-method () none 13)
)
:size-assert #x20
:method-count-assert 14
@@ -244,13 +245,13 @@
)
(:methods
(new ((allocation symbol) (type-to-make type) (name basic) (stack-size int)) _type_ 0)
(activate ((obj _type_) (dest process-tree) (name basic) (stack-top pointer)) process-tree 9)
(deactivate ((obj process)) none 10)
(dummy-method-11 () none 11)
(run-logic? ((obj process)) symbol 12)
(dummy-method () none 13)
)
(new ((allocation symbol) (type-to-make type) (name basic) (stack-size int)) _type_ 0)
(activate ((obj _type_) (dest process-tree) (name basic) (stack-top pointer)) process-tree 9)
(deactivate ((obj process)) none 10)
(dummy-method-11 () none 11)
(run-logic? ((obj process)) symbol 12)
(dummy-method () none 13)
)
:size-assert #x70
:method-count-assert 14
@@ -264,10 +265,10 @@
;; nothing new!
)
(:methods
(new ((allocation symbol) (type-to-make type) (count int) (stack-size int) (name basic)) _type_ 0)
(get-process ((pool _type_) (type-to-make type) (stack-size int)) process 14)
(return-process ((pool _type_) (proc process)) none 15)
)
(new ((allocation symbol) (type-to-make type) (count int) (stack-size int) (name basic)) _type_ 0)
(get-process ((pool _type_) (type-to-make type) (stack-size int)) process 14)
(return-process ((pool _type_) (proc process)) none 15)
)
:size-assert #x20
:method-count-assert 16
:flag-assert #x1000000020
@@ -299,28 +300,28 @@
(fill-percent float :offset-assert #x30) ;; ??
(first-gap dead-pool-heap-rec :offset-assert #x34) ;; ??
(first-shrink dead-pool-heap-rec :offset-assert #x38) ;; ??
(heap kheap :inline :offset-assert 64) ;; ??
(alive-list dead-pool-heap-rec :inline :offset-assert 80) ;; ??
(heap kheap :inline :offset-assert 64) ;; ??
(alive-list dead-pool-heap-rec :inline :offset-assert 80) ;; ??
(last dead-pool-heap-rec :offset #x54 :offset-assert #x54) ;; overlay of (-> alive-list prev)
;; note - the placement of dead-list at 92 here is used to determine the packing behavior.
;; see TypeSystem::get_size_in_type().
(dead-list dead-pool-heap-rec :inline :offset-assert 92) ;; ??
(dead-list dead-pool-heap-rec :inline :offset-assert 92) ;; ??
(process-list dead-pool-heap-rec :inline :dynamic :offset-assert 104)
)
(:methods
(new ((allocation symbol) (type-to-make type) (name basic) (allocated-length int) (heap-size int)) _type_ 0)
(compact ((this dead-pool-heap) (count int)) none 16)
(shrink-heap ((this dead-pool-heap) (proc process)) dead-pool-heap 17)
(churn ((this dead-pool-heap) (count int)) none 18)
(memory-used ((this dead-pool-heap)) int 19)
(memory-total ((this dead-pool-heap)) int 20)
(gap-size ((this dead-pool-heap) (rec dead-pool-heap-rec)) int 21)
(gap-location ((this dead-pool-heap) (rec dead-pool-heap-rec)) pointer 22)
(find-gap ((this dead-pool-heap) (rec dead-pool-heap-rec)) dead-pool-heap-rec 23)
(find-gap-by-size ((this dead-pool-heap) (size int)) dead-pool-heap-rec 24)
(memory-free ((this dead-pool-heap)) int 25)
(compact-time ((this dead-pool-heap)) uint 26)
)
(new ((allocation symbol) (type-to-make type) (name basic) (allocated-length int) (heap-size int)) _type_ 0)
(compact ((this dead-pool-heap) (count int)) none 16)
(shrink-heap ((this dead-pool-heap) (proc process)) dead-pool-heap 17)
(churn ((this dead-pool-heap) (count int)) none 18)
(memory-used ((this dead-pool-heap)) int 19)
(memory-total ((this dead-pool-heap)) int 20)
(gap-size ((this dead-pool-heap) (rec dead-pool-heap-rec)) int 21)
(gap-location ((this dead-pool-heap) (rec dead-pool-heap-rec)) pointer 22)
(find-gap ((this dead-pool-heap) (rec dead-pool-heap-rec)) dead-pool-heap-rec 23)
(find-gap-by-size ((this dead-pool-heap) (size int)) dead-pool-heap-rec 24)
(memory-free ((this dead-pool-heap)) int 25)
(compact-time ((this dead-pool-heap)) uint 26)
)
:size-assert #x68
:method-count-assert #x1b
@@ -338,23 +339,28 @@
:size-assert #xc
:method-count-assert 9
:flag-assert #x90000000c
:no-runtime-type ;; already constructed, don't do it again.
)
;; A catch frame is a frame you can "throw" to, by name.
;; You can "throw" out of a function and into another function.
(deftype catch-frame (stack-frame)
((sp int32 :offset 12) ;; where to reset the stack when throwing.
(ra int32 :offset 16) ;; where to jump when throwing
((sp int32 :offset 12) ;; where to reset the stack when throwing.
(ra int32 :offset 16) ;; where to jump when throwing
;; todo - rework for x86-64.
(freg float 6 :offset-assert 20) ;; saved floating point registers from "catch" statement
(rreg uint128 8 :offset-assert 48) ;; saved GPRs from "catch" statement (ugh they are 128s)
;; In GOAL
;; (freg float 6 :offset-assert 20) ;; saved floating point registers from "catch" statement
;; (rreg uint128 8 :offset-assert 48) ;; saved GPRs from "catch" statement (ugh they are 128s)
;; In OpenGOAL, we swap a rreg for 4 more fregs.
(freg float 10 :offset-assert 20) ;; only use 8
(rreg uint128 7) ;; only use 5
)
(:methods
(new ((allocation symbol) (type-to-make type) (name symbol) (func function) (params (pointer uint64))) object 0)
)
(new ((allocation symbol) (type-to-make type) (name symbol) (func function) (params (pointer uint64))) object 0)
)
:size-assert #xb0
:method-count-assert 9
:flag-assert #x9000000b0
@@ -365,15 +371,23 @@
((exit (function object) :offset-assert 12)) ;; function to call to clean up
(:methods
(new ((allocation symbol) (type-to-make type) (func (function object))) protect-frame)
)
(new ((allocation symbol) (type-to-make type) (func (function object))) protect-frame)
)
:size-assert 16
:method-count-assert 9
:flag-assert #x900000010
)
;; A handle is a reference to a _specific_ process.
;; There are two tricks here:
;; 1). A process can be relocated in memory, so we can't just store a process.
;; Instead, we use a (pointer process) that points to a non-moving record.
;; dead-pool-heap takes care of maintaining these.
;; 2). Process memory can be reused. We don't want to get confused by this.
;; So we also store a unique PID to the specific activation of a process.
;; This way we can check the handle's PID against the PID in the process.
(deftype handle (uint64)
((process (pointer process) :offset 0)
((process (pointer process) :offset 0) ;; set to #f for null.
(pid int32 :offset 32)
(u64 uint64 :offset 0)
)
@@ -390,10 +404,10 @@
(defmacro get-process-from-handle (handle)
;; the actual implementation is more clever than this.
;; Checks PID.
`(if (-> ,handle process)
(let ((proc (-> (-> ,handle process))))
(if (= (-> ,handle pid)
(-> proc pid))
(if (= (-> ,handle pid) (-> proc pid))
proc
)
)
@@ -421,9 +435,9 @@
(event basic :offset-assert 32)
)
(:methods
(new ((allocation symbol) (type-to-make type) (name basic) (code function)
(trans function) (enter function) (exit (function object)) (event function)) _type_ 0)
)
(new ((allocation symbol) (type-to-make type) (name basic) (code function)
(trans function) (enter function) (exit (function object)) (event function)) _type_ 0)
)
:method-count-assert 9
:size-assert #x24
:flag-assert #x900000024
@@ -445,6 +459,10 @@
)
(defmacro as-process (ppointer)
;; convert a (pointer process) to a process.
;; this uses the self field, which seems to always just get set to the object.
;; perhaps when deleting a process you could have it set self to #f?
;; I don't see this happen anywhere though, so it's not clear.
`(if ,ppointer
(-> (-> ,ppointer) self)
)
@@ -488,20 +506,28 @@
)
(defmacro process-mask-set! (mask enum-value)
;; sets the given bits in the process mask (with or)
`(set! ,mask (logior ,mask (process-mask ,enum-value)))
)
(defmacro suspend ()
;; suspend the current process.
`(rlet ((pp :reg r13 :reset-here #t))
;; we pass the current thread to the kernel with the pp register.
;; so it should be backed up on the stack here.
(.push pp)
;; set to the current thread
(set! pp (-> (the process pp) top-thread))
;; call the suspend hook (put nothing as the argument)
((-> (the cpu-thread pp) suspend-hook) (the cpu-thread 0))
;; now we've been resumed, restore pp.
(.pop pp)
)
)
(defmacro process-deactivate ()
;; deactivate the current process
`(rlet ((pp :reg r13 :reset-here #t :type process))
(deactivate pp)
)
)
)
+1 -1
View File
@@ -479,7 +479,7 @@ Val* Compiler::compile_deref(const goos::Object& form, const goos::Object& _rest
// array-indexable and a structure, we treat it like a structure only if the
// deref thing is one of the field names. Otherwise, array.
if (field_name == "content-type" || field_name == "length" ||
field_name == "allocated-length" || field_name == "type") {
field_name == "allocated-length" || field_name == "type" || field_name == "data") {
result = get_field_of_structure(struct_type, result, field_name, env);
continue;
}
+1 -1
View File
@@ -2207,7 +2207,7 @@ TEST_F(FormRegressionTest, ExprPrintTreeBitmask) {
" (format (quote #t) \" \")\n"
" (format (quote #t) \"| \")\n"
" )\n"
" (set! arg0 (shr (the-as uint arg0) 1))\n"
" (set! arg0 (shr arg0 1))\n"
" (set! s4-0 (+ s4-0 1))\n"
" )\n"
" (set! v1-3 (quote #f))\n"
@@ -17,6 +17,6 @@
(format #t "TEST FAIL~%~%")
)
(print test-result)
(printl test-result)
)
0
+3 -3
View File
@@ -13,17 +13,17 @@ TEST(GameNoDebugSegment, Init) {
compiler.run_test_from_string("(inspect *kernel-context*)");
// these should be equal, both the fallback inspect method
EXPECT_TRUE(compiler.run_test_from_string("(print (eq? (method-of-type kernel-context inspect) "
EXPECT_TRUE(compiler.run_test_from_string("(printl (eq? (method-of-type kernel-context inspect) "
"(method-of-type cpu-thread inspect))) 0") ==
std::vector<std::string>{"#t\n0\n"});
// should be below the debug heap.
EXPECT_TRUE(compiler.run_test_from_string("(print (< (the uint (method-of-type kernel-context "
EXPECT_TRUE(compiler.run_test_from_string("(printl (< (the uint (method-of-type kernel-context "
"inspect)) (the uint (-> debug base)))) 0") ==
std::vector<std::string>{"#t\n0\n"});
// debug segment flag should be disabled.
EXPECT_TRUE(compiler.run_test_from_string("(print *debug-segment*) 0") ==
EXPECT_TRUE(compiler.run_test_from_string("(printl *debug-segment*) 0") ==
std::vector<std::string>{"#f\n0\n"});
compiler.shutdown_target();