From 1becf37170b13dd9d2ddcbeb56ae5a23d3fec0e9 Mon Sep 17 00:00:00 2001 From: water Date: Sat, 6 Mar 2021 13:14:49 -0500 Subject: [PATCH 1/3] fix up pretty printing --- common/goos/PrettyPrinter.cpp | 73 ++- decompiler/analysis/inline_asm_rewrite.cpp | 4 +- decompiler/analysis/insert_lets.cpp | 41 ++ test/decompiler/reference/gcommon_REF.gc | 650 +++++++++++-------- test/decompiler/test_FormExpressionBuild.cpp | 2 +- 5 files changed, 499 insertions(+), 271 deletions(-) diff --git a/common/goos/PrettyPrinter.cpp b/common/goos/PrettyPrinter.cpp index 7b7e915c7a..e074a7f55c 100644 --- a/common/goos/PrettyPrinter.cpp +++ b/common/goos/PrettyPrinter.cpp @@ -289,7 +289,7 @@ static PrettyPrinterNode* propagatePretty(NodePool& pool, for (auto* n = list; n; n = n->next) { if (n->is_line_separator) { previous_line_sep = true; - offset = indentStack.back() += n->specialIndentDelta; + offset = indentStack.back() + n->specialIndentDelta; } else { if (previous_line_sep) { line_start = n; @@ -483,6 +483,12 @@ void breakList(NodePool& pool, PrettyPrinterNode* leftParen, PrettyPrinterNode* } } +namespace { +const std::unordered_set control_flow_start_forms = { + "while", "dotimes", "until", "if", "when", +}; +} + void insertSpecialBreaks(NodePool& pool, PrettyPrinterNode* node) { for (; node; node = node->next) { if (!node->is_line_separator && node->tok->kind == FormToken::TokenKind::STRING) { @@ -494,12 +500,75 @@ void insertSpecialBreaks(NodePool& pool, PrettyPrinterNode* node) { } } - if (name == "defun" || name == "defmethod" || name == "defun-debug") { + if (name == "defun" || name == "defmethod" || name == "defun-debug" || name == "let" || + name == "let*") { + auto* parent_type_dec = getNextListOnLine(node); + if (parent_type_dec) { + insertNewlineAfter(pool, parent_type_dec->paren, 0); + breakList(pool, node->paren, parent_type_dec); + } + + if ((name == "let" || name == "let*") && parent_type_dec) { + if (parent_type_dec->tok->kind == FormToken::TokenKind::OPEN_PAREN) { + breakList(pool, parent_type_dec); + } + auto open_paren = node->prev; + if (open_paren && open_paren->tok->kind == FormToken::TokenKind::OPEN_PAREN) { + // insertNewlineBefore(pool, open_paren, 0); + if (open_paren->prev) { + breakList(pool, open_paren->prev->paren, open_paren); + } + } + } + } + + if (control_flow_start_forms.find(name) != control_flow_start_forms.end()) { auto* parent_type_dec = getNextListOnLine(node); if (parent_type_dec) { insertNewlineAfter(pool, parent_type_dec->paren, 0); breakList(pool, node->paren, parent_type_dec); + auto open_paren = node->prev; + if (open_paren && open_paren->tok->kind == FormToken::TokenKind::OPEN_PAREN) { + if (open_paren->prev && !open_paren->prev->is_line_separator) { + if (open_paren->prev) { + breakList(pool, open_paren->prev->paren, open_paren); + } + } + } + } + } + + if (name == "cond") { + auto* start_of_case = getNextListOnLine(node); + while (true) { + // let's break this case: + assert(start_of_case->tok->kind == FormToken::TokenKind::OPEN_PAREN); + auto end_of_case = start_of_case->paren; + assert(end_of_case->tok->kind == FormToken::TokenKind::CLOSE_PAREN); + // get the first thing in the case + + // and break there. + breakList(pool, start_of_case); + // now, look for the next case. + auto next = end_of_case->next; + while (next && + (next->is_line_separator || next->tok->kind == FormToken::TokenKind::WHITESPACE)) { + next = next->next; + } + if (!next) { + break; + } + if (next->tok->kind == FormToken::TokenKind::CLOSE_PAREN) { + break; + } + if (next->tok->kind != FormToken::TokenKind::OPEN_PAREN) { + break; + } + start_of_case = next; } + + // break cond into a multi-line always + breakList(pool, node->paren); } } } diff --git a/decompiler/analysis/inline_asm_rewrite.cpp b/decompiler/analysis/inline_asm_rewrite.cpp index 2a82674f0e..7ce8278183 100644 --- a/decompiler/analysis/inline_asm_rewrite.cpp +++ b/decompiler/analysis/inline_asm_rewrite.cpp @@ -37,7 +37,7 @@ bool rewrite_inline_asm_instructions(Form* top_level_form, // If its an invalid or unsupported exception, skip it /*lg::warn("[ASM Re-Write] - Unsupported inline assembly instruction kind - [{}]", asmOp.instr.kind);*/ - f.warnings.general_warning(";; Unsupported inline assembly instruction kind - [{}]", + f.warnings.general_warning("Unsupported inline assembly instruction kind - [{}]", asmOp.instr.kind); new_entries.push_back(entry); continue; @@ -51,7 +51,7 @@ bool rewrite_inline_asm_instructions(Form* top_level_form, // If its an invalid or unsupported exception, skip it /*lg::warn("[ASM Re-Write] - Inline assembly instruction marked with TODO - [{}]", asmOp.full_function_name());*/ - f.warnings.general_warning(";; Inline assembly instruction marked with TODO - [{}]", + f.warnings.general_warning("Inline assembly instruction marked with TODO - [{}]", asmOp.full_function_name()); } diff --git a/decompiler/analysis/insert_lets.cpp b/decompiler/analysis/insert_lets.cpp index 08351cfd83..61817cc765 100644 --- a/decompiler/analysis/insert_lets.cpp +++ b/decompiler/analysis/insert_lets.cpp @@ -163,6 +163,42 @@ FormElement* rewrite_as_dotimes(LetElement* in, const Env& env, FormPool& pool) mr.maps.forms.at(1), body); } +FormElement* fix_up_abs(LetElement* in, const Env& env, FormPool& pool) { + /* + (let ((v0-0 x) + ) + (abs v0-0) + ) + */ + + if (in->entries().size() != 1) { + return nullptr; + } + + // look for setting a temp. + auto temp = in->entries().at(0).dest; + auto temp_name = env.get_variable_name(temp); + + Form* src = in->entries().at(0).src; + + auto body_matcher = + Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ABS), {Matcher::any_reg(0)}); + auto mr = match(body_matcher, in->body()); + if (!mr.matched) { + return nullptr; + } + + assert(mr.maps.regs.at(0)); + auto abs_var_name = env.get_variable_name(*mr.maps.regs.at(0)); + if (abs_var_name != temp_name) { + return nullptr; + } + + // success! + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::ABS), + src); +} + /*! * Attempt to rewrite a let as another form. If it cannot be rewritten, this will return nullptr. */ @@ -172,6 +208,11 @@ FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool) { return as_dotimes; } + auto as_abs = fix_up_abs(in, env, pool); + if (as_abs) { + return as_abs; + } + // nothing matched. return nullptr; } diff --git a/test/decompiler/reference/gcommon_REF.gc b/test/decompiler/reference/gcommon_REF.gc index 1be8947f74..e282f15e3e 100644 --- a/test/decompiler/reference/gcommon_REF.gc +++ b/test/decompiler/reference/gcommon_REF.gc @@ -48,7 +48,7 @@ ;; definition for function abs (defun abs ((x int)) - (let ((v0-0 x)) (abs v0-0)) + (abs x) ) ;; definition for function min @@ -110,6 +110,13 @@ ;; definition for method of type vec4s ;; INFO: Return type mismatch int vs vec4s. +;; WARN: Unsupported inline assembly instruction kind - [131] +;; WARN: Unsupported inline assembly instruction kind - [131] +;; WARN: Unsupported inline assembly instruction kind - [73] +;; WARN: Unsupported inline assembly instruction kind - [132] +;; WARN: Unsupported inline assembly instruction kind - [73] +;; WARN: Unsupported inline assembly instruction kind - [132] +;; WARN: Unsupported inline assembly instruction kind - [131] (defmethod inspect vec4s ((obj vec4s)) (local-vars (r0-0 none) @@ -122,25 +129,33 @@ (gp-0 int) ) (.por gp-0 obj r0-0) - (let - ((t9-0 format) (a0-1 #t) (a1-0 "[~8x] ~A~%")) + (let ((t9-0 format) + (a0-1 #t) + (a1-0 "[~8x] ~A~%") + ) (.por a2-0 gp-0 r0-0) (t9-0 a0-1 a1-0 a2-0 'vec4s) ) - (let - ((t9-1 format) (a0-2 #t) (a1-1 "~Tx: ~f~%")) + (let ((t9-1 format) + (a0-2 #t) + (a1-1 "~Tx: ~f~%") + ) (.sllv a2-1 gp-0 r0-0) (t9-1 a0-2 a1-1 a2-1) ) (format #t "~Ty: ~f~%" (sar gp-0 32)) - (let - ((t9-3 format) (a0-4 #t) (a1-3 "~Tz: ~f~%")) + (let ((t9-3 format) + (a0-4 #t) + (a1-3 "~Tz: ~f~%") + ) (.pcpyud v1-0 gp-0 r0-0) (.sllv a2-3 v1-0 r0-0) (t9-3 a0-4 a1-3 a2-3) ) - (let - ((t9-4 format) (a0-5 #t) (a1-4 "~Tw: ~f~%")) + (let ((t9-4 format) + (a0-5 #t) + (a1-4 "~Tw: ~f~%") + ) (.pcpyud v1-1 gp-0 r0-0) (t9-4 a0-5 a1-4 (sar v1-1 32)) ) @@ -150,6 +165,13 @@ ;; definition for method of type vec4s ;; INFO: Return type mismatch int vs vec4s. +;; WARN: Unsupported inline assembly instruction kind - [131] +;; WARN: Unsupported inline assembly instruction kind - [73] +;; WARN: Unsupported inline assembly instruction kind - [132] +;; WARN: Unsupported inline assembly instruction kind - [73] +;; WARN: Unsupported inline assembly instruction kind - [132] +;; WARN: Unsupported inline assembly instruction kind - [131] +;; WARN: Unsupported inline assembly instruction kind - [131] (defmethod print vec4s ((obj vec4s)) (local-vars (r0-0 none) @@ -162,16 +184,18 @@ (gp-0 int) ) (.por gp-0 obj r0-0) - (let - ((t9-0 format) (a0-1 #t) (a1-0 "#")) + (let ((t9-0 format) + (a0-1 #t) + (a1-0 "#") + ) (.sllv a2-0 gp-0 r0-0) - (let - ((a3-0 (sar gp-0 32))) + (let ((a3-0 (sar gp-0 32)) + ) (.pcpyud v1-0 gp-0 r0-0) (.sllv t0-0 v1-0 r0-0) (.pcpyud v1-1 gp-0 r0-0) - (let - ((t1-0 (sar v1-1 32))) + (let ((t1-0 (sar v1-1 32)) + ) (.por t2-0 gp-0 r0-0) (t9-0 a0-1 a1-0 a2-0 a3-0 t0-0 t1-0 t2-0) ) @@ -212,11 +236,13 @@ ;; definition for function basic-type? (defun basic-type? ((obj basic) (parent-type type)) - (let - ((obj-type (-> obj type)) (end-type object)) - (until - (begin (set! obj-type (-> obj-type parent)) (= obj-type end-type)) - (if (= obj-type parent-type) (return #t)) + (let ((obj-type (-> obj type)) + (end-type object) + ) + (until (begin (set! obj-type (-> obj-type parent)) (= obj-type end-type)) + (if (= obj-type parent-type) + (return #t) + ) ) ) #f @@ -224,14 +250,16 @@ ;; definition for function type-type? (defun type-type? ((child-type type) (parent-type type)) - (let - ((end-type object)) + (let ((end-type object) + ) (until (begin (set! child-type (-> child-type parent)) (or (= child-type end-type) (zero? child-type)) ) - (if (= child-type parent-type) (return #t)) + (if (= child-type parent-type) + (return #t) + ) ) ) #f @@ -240,14 +268,17 @@ ;; definition for function find-parent-method (defun find-parent-method ((child-type type) (method-id int)) (local-vars (current-method function)) - (let - ((original-method (-> child-type method-table method-id))) - (until - (!= current-method original-method) - (if (= child-type object) (return nothing)) + (let ((original-method (-> child-type method-table method-id)) + ) + (until (!= current-method original-method) + (if (= child-type object) + (return nothing) + ) (set! child-type (-> child-type parent)) (set! current-method (-> child-type method-table method-id)) - (if (zero? current-method) (return nothing)) + (if (zero? current-method) + (return nothing) + ) ) ) current-method @@ -255,7 +286,11 @@ ;; definition for function ref (defun ref ((lst object) (index int)) - (dotimes (count index) (nop!) (nop!) (set! lst (cdr lst))) + (dotimes (count index) + (nop!) + (nop!) + (set! lst (cdr lst)) + ) (car lst) ) @@ -263,13 +298,14 @@ (defmethod length pair ((obj pair)) (local-vars (result int)) (cond - ((= obj '()) (set! result 0)) + ((= obj '()) + (set! result 0) + ) (else - (let - ((iter (cdr obj))) + (let ((iter (cdr obj)) + ) (set! result 1) - (while - (and (!= iter '()) (< (shl (the-as int iter) 62) 0)) + (while (and (!= iter '()) (< (shl (the-as int iter) 62) 0)) (+! result 1) (set! iter (cdr iter)) ) @@ -287,106 +323,123 @@ ;; definition for function last (defun last ((lst object)) - (let - ((iter lst)) - (while (!= (cdr iter) '()) (nop!) (nop!) (set! iter (cdr iter))) + (let ((iter lst) + ) + (while (!= (cdr iter) '()) + (nop!) + (nop!) + (set! iter (cdr iter)) + ) iter ) ) ;; definition for function member (defun member ((obj object) (lst object)) - (let - ((iter lst)) - (while (not (or (= iter '()) (= (car iter) obj))) (set! iter (cdr iter))) - (if (!= iter '()) iter) + (let ((iter lst) + ) + (while (not (or (= iter '()) (= (car iter) obj))) + (set! iter (cdr iter)) + ) + (if (!= iter '()) + iter + ) ) ) ;; definition for function nmember (defun nmember ((obj basic) (lst object)) - (while - (not (or (= lst '()) (name= (the-as basic (car lst)) obj))) + (while (not (or (= lst '()) (name= (the-as basic (car lst)) obj))) (set! lst (cdr lst)) ) - (if (!= lst '()) lst) + (if (!= lst '()) + lst + ) ) ;; definition for function assoc (defun assoc ((item object) (alist object)) - (let - ((iter alist)) - (while - (not (or (= iter '()) (= (car (car iter)) item))) + (let ((iter alist) + ) + (while (not (or (= iter '()) (= (car (car iter)) item))) (set! iter (cdr iter)) ) - (if (!= iter '()) (car iter)) + (if (!= iter '()) + (car iter) + ) ) ) ;; definition for function assoce (defun assoce ((item object) (alist object)) - (let - ((iter alist)) + (let ((iter alist) + ) (while (not (or (= iter '()) (= (car (car iter)) item) (= (car (car iter)) 'else))) (set! iter (cdr iter)) ) - (if (!= iter '()) (car iter)) + (if (!= iter '()) + (car iter) + ) ) ) ;; definition for function nassoc (defun nassoc ((item-name string) (alist object)) - (while - (not - (or - (= alist '()) - (let - ((key (car (car alist)))) - (if - (pair? key) - (nmember item-name key) - (name= (the-as basic key) item-name) - ) - ) - ) - ) + (while (not (or (= alist '()) (let ((key (car (car alist))) + ) + (if (pair? key) + (nmember item-name key) + (name= (the-as basic key) item-name) + ) + ) + ) + ) (set! alist (cdr alist)) ) - (if (!= alist '()) (car alist)) + (if (!= alist '()) + (car alist) + ) ) ;; definition for function nassoce (defun nassoce ((item-name string) (alist object)) - (while - (not - (or - (= alist '()) - (let - ((key (car (car alist)))) - (if - (pair? key) - (nmember item-name key) - (or (name= (the-as basic key) item-name) (= key 'else)) - ) - ) - ) - ) + (while (not (or (= alist '()) (let ((key (car (car alist))) + ) + (if (pair? key) + (nmember item-name key) + (or + (name= (the-as basic key) item-name) + (= key 'else) + ) + ) + ) + ) + ) (set! alist (cdr alist)) ) - (if (!= alist '()) (car alist)) + (if (!= alist '()) + (car alist) + ) ) ;; definition for function append! (defun append! ((front object) (back object)) (cond - ((= front '()) back) + ((= front '()) + back + ) (else - (let - ((iter front)) - (while (!= (cdr iter) '()) (nop!) (nop!) (set! iter (cdr iter))) - (if (!= iter '()) (set! (cdr iter) back)) + (let ((iter front) + ) + (while (!= (cdr iter) '()) + (nop!) + (nop!) + (set! iter (cdr iter)) + ) + (if (!= iter '()) + (set! (cdr iter) back) + ) ) front ) @@ -396,39 +449,45 @@ ;; definition for function delete! ;; INFO: Return type mismatch object vs pair. (defun delete! ((item object) (lst object)) - (the-as - pair - (cond - ((= item (car lst)) (cdr lst)) - (else - (let - ((iter-prev lst) (iter (cdr lst))) - (while - (not (or (= iter '()) (= (car iter) item))) - (set! iter-prev iter) - (set! iter (cdr iter)) - ) - (if (!= iter '()) (set! (cdr iter-prev) (cdr iter))) - ) - lst - ) - ) + (the-as pair (cond + ((= item (car lst)) + (cdr lst) + ) + (else + (let ((iter-prev lst) + (iter (cdr lst)) + ) + (while (not (or (= iter '()) (= (car iter) item))) + (set! iter-prev iter) + (set! iter (cdr iter)) + ) + (if (!= iter '()) + (set! (cdr iter-prev) (cdr iter)) + ) + ) + lst + ) + ) ) ) ;; definition for function delete-car! (defun delete-car! ((item object) (lst object)) (cond - ((= item (car (car lst))) (cdr lst)) + ((= item (car (car lst))) + (cdr lst) + ) (else - (let - ((iter-prev lst) (iter (cdr lst))) - (while - (not (or (= iter '()) (= (car (car iter)) item))) + (let ((iter-prev lst) + (iter (cdr lst)) + ) + (while (not (or (= iter '()) (= (car (car iter)) item))) (set! iter-prev iter) (set! iter (cdr iter)) ) - (if (!= iter '()) (set! (cdr iter-prev) (cdr iter))) + (if (!= iter '()) + (set! (cdr iter-prev) (cdr iter)) + ) ) lst ) @@ -437,25 +496,26 @@ ;; definition for function insert-cons! (defun insert-cons! ((kv object) (alist object)) - (let ((updated-list (delete-car! (car kv) alist))) (cons kv updated-list)) + (let ((updated-list (delete-car! (car kv) alist)) + ) + (cons kv updated-list) + ) ) ;; definition for function sort (defun sort ((lst object) (compare-func (function object object object))) - (let - ((unsorted-count -1)) - (while - (nonzero? unsorted-count) + (let ((unsorted-count -1) + ) + (while (nonzero? unsorted-count) (set! unsorted-count 0) - (let - ((iter lst)) + (let ((iter lst) + ) (while (not (or (= (cdr iter) '()) (>= (shl (the-as int (cdr iter)) 62) 0))) - (let* - ((first-elt (car iter)) - (seoncd-elt (car (cdr iter))) - (compare-result (compare-func first-elt seoncd-elt)) - ) + (let* ((first-elt (car iter)) + (seoncd-elt (car (cdr iter))) + (compare-result (compare-func first-elt seoncd-elt)) + ) (when (and (or (not compare-result) (> (the-as int compare-result) 0)) @@ -518,8 +578,7 @@ ) ) ) - (when - (nonzero? obj) + (when (nonzero? obj) (set! (-> obj length) size) (set! (-> obj allocated-length) size) ) @@ -561,9 +620,11 @@ int (+ (-> type-to-make size) - (the-as - uint - (* len (if (type-type? content-type number) (-> content-type size) 4)) + (the-as uint (* len (if (type-type? content-type number) + (-> content-type size) + 4 + ) + ) ) ) ) @@ -578,6 +639,7 @@ ) ;; definition for method of type array +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] (defmethod print array ((obj array)) (local-vars (a2-8 int) @@ -595,42 +657,53 @@ (i int) ) (format #t "#(") - (if - (type-type? (-> obj content-type) integer) - (let - ((content-type-sym (-> obj content-type symbol))) + (if (type-type? (-> obj content-type) integer) + (let ((content-type-sym (-> obj content-type symbol)) + ) (cond ((= content-type-sym 'int32) (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int32) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array int32) obj) i) + ) (+! i 1) ) ) ((= content-type-sym 'uint32) (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array uint32) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array uint32) obj) i) + ) (+! i 1) ) ) ((= content-type-sym 'int64) (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int64) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array int64) obj) i) + ) (+! i 1) ) ) ((= content-type-sym 'uint64) (set! i 0) - (while - (< i (-> obj length)) - (format - #t - (if (zero? i) "#x~X" " #x~X") + (while (< i (-> obj length)) + (format #t (if (zero? i) + "#x~X" + " #x~X" + ) (-> (the-as (array uint64) obj) i) ) (+! i 1) @@ -638,33 +711,49 @@ ) ((= content-type-sym 'int8) (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int8) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array int8) obj) i) + ) (+! i 1) ) ) ((= content-type-sym 'uint8) (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array uint8) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array uint8) obj) i) + ) (+! i 1) ) ) ((= content-type-sym 'int16) (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int16) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array int16) obj) i) + ) (+! i 1) ) ) ((= content-type-sym 'uint16) (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array uint16) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array uint16) obj) i) + ) (+! i 1) ) ) @@ -672,13 +761,18 @@ (cond ((or (= content-type-sym 'uint128) (= content-type-sym 'int128)) (set! i 0) - (while - (< i (-> obj length)) - (let - ((t9-10 format) (a0-21 #t) (a1-11 (if (zero? i) "#x~X" " #x~X"))) - (let - ((v1-42 (+ (shl i 4) (the-as int (the-as (array uint128) obj))))) - (.lq a2-8 12 v1-42) + (while (< i (-> obj length)) + (let ((t9-10 format) + (a0-21 #t) + (a1-11 (if (zero? i) + "#x~X" + " #x~X" + ) + ) + ) + (let ((v1-42 (+ (shl i 4) (the-as int (the-as (array uint128) obj)))) + ) + (TODO.LQ a2-8 v1-42 :offset 12) ) (t9-10 a0-21 a1-11 a2-8) ) @@ -687,9 +781,13 @@ ) (else (set! i 0) - (while - (< i (-> obj length)) - (format #t (if (zero? i) "~D" " ~D") (-> (the-as (array int32) obj) i)) + (while (< i (-> obj length)) + (format #t (if (zero? i) + "~D" + " ~D" + ) + (-> (the-as (array int32) obj) i) + ) (+! i 1) ) ) @@ -700,10 +798,8 @@ (cond ((= (-> obj content-type) float) (set! i 0) - (while - (< i (-> obj length)) - (if - (zero? i) + (while (< i (-> obj length)) + (if (zero? i) (format #t "~f" (-> (the-as (array float) obj) i)) (format #t " ~f" (-> (the-as (array float) obj) i)) ) @@ -712,10 +808,8 @@ ) (else (set! i 0) - (while - (< i (-> obj length)) - (if - (zero? i) + (while (< i (-> obj length)) + (if (zero? i) (format #t "~A" (-> (the-as (array basic) obj) i)) (format #t " ~A" (-> (the-as (array basic) obj) i)) ) @@ -729,6 +823,7 @@ ) ;; definition for method of type array +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] (defmethod inspect array ((obj array)) (local-vars (a3-10 int) @@ -750,71 +845,62 @@ (format #t "~Tlength: ~D~%" (-> obj length)) (format #t "~Tcontent-type: ~A~%" (-> obj content-type)) (format #t "~Tdata[~D]: @ #x~X~%" (-> obj allocated-length) (-> obj data)) - (if - (type-type? (-> obj content-type) integer) - (let - ((content-type-sym (-> obj content-type symbol))) + (if (type-type? (-> obj content-type) integer) + (let ((content-type-sym (-> obj content-type symbol)) + ) (cond ((= content-type-sym 'int32) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> (the-as (array int32) obj) i)) (+! i 1) ) ) ((= content-type-sym 'uint32) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> (the-as (array uint32) obj) i)) (+! i 1) ) ) ((= content-type-sym 'int64) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> (the-as (array int64) obj) i)) (+! i 1) ) ) ((= content-type-sym 'uint64) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] #x~X~%" i (-> (the-as (array uint64) obj) i)) (+! i 1) ) ) ((= content-type-sym 'int8) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) (+! i 1) ) ) ((= content-type-sym 'uint8) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) (+! i 1) ) ) ((= content-type-sym 'int16) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> (the-as (array int16) obj) i)) (+! i 1) ) ) ((= content-type-sym 'uint16) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> (the-as (array uint16) obj) i)) (+! i 1) ) @@ -823,11 +909,16 @@ (cond ((or (= content-type-sym 'int128) (= content-type-sym 'uint128)) (set! i 0) - (while - (< i (-> obj length)) - (let - ((t9-14 format) (a0-25 #t) (a1-15 "~T [~D] #x~X~%") (a2-13 i)) - (let ((v1-42 (+ (shl i 4) (the-as int obj)))) (.lq a3-10 12 v1-42)) + (while (< i (-> obj length)) + (let ((t9-14 format) + (a0-25 #t) + (a1-15 "~T [~D] #x~X~%") + (a2-13 i) + ) + (let ((v1-42 (+ (shl i 4) (the-as int obj))) + ) + (TODO.LQ a3-10 v1-42 :offset 12) + ) (t9-14 a0-25 a1-15 a2-13 a3-10) ) (+! i 1) @@ -835,8 +926,7 @@ ) (else (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~D~%" i (-> obj i)) (+! i 1) ) @@ -848,16 +938,14 @@ (cond ((= (-> obj content-type) float) (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~f~%" i (-> obj i)) (+! i 1) ) ) (else (set! i 0) - (while - (< i (-> obj length)) + (while (< i (-> obj length)) (format #t "~T [~D] ~A~%" i (-> obj i)) (+! i 1) ) @@ -881,13 +969,10 @@ (-> array size) (the-as uint - (* - (-> obj allocated-length) - (if - (type-type? (-> obj content-type) number) - (-> obj content-type size) - 4 - ) + (* (-> obj allocated-length) (if (type-type? (-> obj content-type) number) + (-> obj content-type size) + 4 + ) ) ) ) @@ -896,10 +981,9 @@ ;; definition for function mem-copy! (defun mem-copy! ((dst pointer) (src pointer) (size int)) - (let - ((result dst)) - (dotimes - (i size) + (let ((result dst) + ) + (dotimes (i size) (set! (-> (the-as (pointer int8) dst)) (-> (the-as (pointer uint8) src))) (&+! dst 1) (&+! src 1) @@ -909,17 +993,18 @@ ) ;; definition for function qmem-copy<-! +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ] (defun qmem-copy<-! ((dst pointer) (src pointer) (size int)) (local-vars (value int)) - (let - ((result dst)) - (let - ((qwc (sar (+ size 15) 4))) - (while - (nonzero? qwc) + (let ((result dst) + ) + (let ((qwc (sar (+ size 15) 4)) + ) + (while (nonzero? qwc) (+! qwc -1) - (.lq value 0 src) - (.sq value 0 dst) + (TODO.LQ value src) + (TODO.SQ value dst) (&+! dst 16) (&+! src 16) ) @@ -929,21 +1014,22 @@ ) ;; definition for function qmem-copy->! +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ] (defun qmem-copy->! ((dst pointer) (src pointer) (size int)) (local-vars (src-ptr pointer) (dst-ptr pointer) (value int)) - (let - ((result dst)) - (let - ((qwc (sar (+ size 15) 4))) + (let ((result dst) + ) + (let ((qwc (sar (+ size 15) 4)) + ) (&+! dst (shl qwc 4)) (&+! src (shl qwc 4)) - (while - (nonzero? qwc) + (while (nonzero? qwc) (+! qwc -1) (&+! src-ptr -16) (&+! dst-ptr -16) - (.lq value 0 dst-ptr) - (.sq value 0 src-ptr) + (TODO.LQ value dst-ptr) + (TODO.SQ value src-ptr) ) ) result @@ -952,10 +1038,9 @@ ;; definition for function mem-set32! (defun mem-set32! ((dst pointer) (size int) (value int)) - (let - ((result dst)) - (dotimes - (i size) + (let ((result dst) + ) + (dotimes (i size) (set! (-> (the-as (pointer int32) dst)) value) (&+! dst 4) (nop!) @@ -966,10 +1051,9 @@ ;; definition for function mem-or! (defun mem-or! ((dst pointer) (src pointer) (size int)) - (let - ((result dst)) - (dotimes - (i size) + (let ((result dst) + ) + (dotimes (i size) (set! (-> (the-as (pointer int8) dst)) (logior @@ -989,7 +1073,10 @@ ;; definition for function fact (defun fact ((x int)) - (if (= x 1) 1 (* x (fact (+ x -1)))) + (if (= x 1) + 1 + (* x (fact (+ x -1))) + ) ) ;; definition for symbol *print-column*, type binteger @@ -1002,7 +1089,10 @@ ;; definition for function printl (defun printl ((arg0 object)) - (let ((a0-1 arg0)) ((method-of-type (rtype-of a0-1) print) a0-1)) + (let ((a0-1 arg0) + ) + ((method-of-type (rtype-of a0-1) print) a0-1) + ) (format #t "~%") arg0 ) @@ -1014,8 +1104,7 @@ ;; definition (debug) for function mem-print (defun-debug mem-print ((data (pointer uint32)) (word-count int)) - (dotimes - (current-qword (sar word-count 2)) + (dotimes (current-qword (sar word-count 2)) (format 0 "~X: ~X ~X ~X ~X~%" @@ -1034,15 +1123,20 @@ ;; definition for function print-tree-bitmask (defun print-tree-bitmask ((bits int) (count int)) - (dotimes - (i count) - (if (zero? (logand bits 1)) (format #t " ") (format #t "| ")) + (dotimes (i count) + (if (zero? (logand bits 1)) + (format #t " ") + (format #t "| ") + ) (set! bits (shr bits 1)) ) #f ) ;; definition for function breakpoint-range-set! +;; WARN: Unsupported inline assembly instruction kind - [48] +;; WARN: Unsupported inline assembly instruction kind - [50] +;; WARN: Unsupported inline assembly instruction kind - [51] (defun breakpoint-range-set! ((arg0 uint) (arg1 uint) (arg2 uint)) (.mtc0 Debug arg0) (.mtdab arg1) @@ -1051,6 +1145,9 @@ ) ;; definition for function valid? +;; WARN: Unsupported inline assembly instruction kind - [3] +;; WARN: Unsupported inline assembly instruction kind - [3] +;; WARN: Unsupported inline assembly instruction kind - [3] (defun valid? ((obj object) @@ -1095,10 +1192,14 @@ ) #f ) - (else #t) + (else + #t + ) ) ) - ((and allow-false (not obj)) #t) + ((and allow-false (not obj)) + #t + ) (else (cond ((= expected-type structure) @@ -1116,12 +1217,12 @@ ) #f ) - ((or - (not in-goal-mem) - (begin - (let ((v1-10 #x8000)) (.daddu v1-11 v1-10 s7-0)) - (< (the-as uint obj) (the-as uint v1-11)) - ) + ((or (not in-goal-mem) (begin (let ((v1-10 #x8000) + ) + (.daddu v1-11 v1-10 s7-0) + ) + (< (the-as uint obj) (the-as uint v1-11)) + ) ) (if name @@ -1135,7 +1236,9 @@ ) #f ) - (else #t) + (else + #t + ) ) ) ((= expected-type pair) @@ -1166,12 +1269,16 @@ ) #f ) - (else #t) + (else + #t + ) ) ) ((= expected-type binteger) (cond - ((zero? (logand (the-as int obj) 7)) #t) + ((zero? (logand (the-as int obj) 7)) + #t + ) (else (if name @@ -1261,7 +1368,10 @@ #f ) ((= expected-type symbol) - (let ((v1-43 #x8000)) (.daddu v1-44 v1-43 s7-0)) + (let ((v1-43 #x8000) + ) + (.daddu v1-44 v1-43 s7-0) + ) (cond ((>= (the-as uint obj) (the-as uint v1-44)) (if @@ -1276,11 +1386,15 @@ ) #f ) - (else #t) + (else + #t + ) ) ) - ((begin - (let ((v1-47 #x8000)) (.daddu v1-48 v1-47 s7-0)) + ((begin (let ((v1-47 #x8000) + ) + (.daddu v1-48 v1-47 s7-0) + ) (< (the-as uint obj) (the-as uint v1-48)) ) (if @@ -1295,7 +1409,9 @@ ) #f ) - (else #t) + (else + #t + ) ) ) ) @@ -1305,4 +1421,6 @@ ) ;; failed to figure out what this is: -(let ((v0-3 0))) +(let ((v0-3 0) + ) + ) \ No newline at end of file diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index a643af2a22..ff04febd28 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -266,7 +266,7 @@ TEST_F(FormRegressionTest, ExprAbs) { " jr ra\n" " daddu sp, sp, r0"; std::string type = "(function int int)"; - std::string expected = "(let ((v0-0 arg0)) (abs v0-0))"; + std::string expected = "(abs arg0)"; test_with_expr(func, type, expected); } From 5f949ffc5db6af4aff86430198faf925c5771e3e Mon Sep 17 00:00:00 2001 From: water Date: Sat, 6 Mar 2021 15:28:50 -0500 Subject: [PATCH 2/3] wip --- common/goos/Object.cpp | 3 +- common/goos/PrettyPrinter.cpp | 5 +- decompiler/IR2/Form.cpp | 4 + decompiler/IR2/Form.h | 17 ++- decompiler/IR2/FormExpressionAnalysis.cpp | 126 ++++++++++++++++--- decompiler/IR2/IR2_common.h | 16 ++- decompiler/IR2/OpenGoalMapping.h | 2 +- decompiler/analysis/cfg_builder.cpp | 8 +- decompiler/analysis/final_output.cpp | 9 +- decompiler/analysis/inline_asm_rewrite.cpp | 2 +- decompiler/analysis/insert_lets.cpp | 3 +- test/decompiler/reference/gcommon_REF.gc | 82 ++++++------ test/decompiler/test_FormExpressionBuild.cpp | 46 +++---- test/offline/offline_test_main.cpp | 9 +- 14 files changed, 230 insertions(+), 102 deletions(-) diff --git a/common/goos/Object.cpp b/common/goos/Object.cpp index d8bcc9446b..89f3b379ad 100644 --- a/common/goos/Object.cpp +++ b/common/goos/Object.cpp @@ -38,6 +38,7 @@ * */ +#include #include "Object.h" #include "common/util/FileUtil.h" #include "third-party/fmt/core.h" @@ -92,7 +93,7 @@ std::string fixed_to_string(FloatType x) { // it's an integer number, so let's just get this over with asap if (exact_int) { - sprintf(buff, "%lld.0", rounded); + sprintf(buff, "%" PRId64 ".0", rounded); return {buff}; } else { // not an integer - see how many decimal cases we need diff --git a/common/goos/PrettyPrinter.cpp b/common/goos/PrettyPrinter.cpp index e074a7f55c..7655208dfc 100644 --- a/common/goos/PrettyPrinter.cpp +++ b/common/goos/PrettyPrinter.cpp @@ -531,7 +531,10 @@ void insertSpecialBreaks(NodePool& pool, PrettyPrinterNode* node) { if (open_paren && open_paren->tok->kind == FormToken::TokenKind::OPEN_PAREN) { if (open_paren->prev && !open_paren->prev->is_line_separator) { if (open_paren->prev) { - breakList(pool, open_paren->prev->paren, open_paren); + auto to_break = open_paren->prev->paren; + if (to_break->tok && to_break->tok->kind == FormToken::TokenKind::OPEN_PAREN) { + breakList(pool, open_paren->prev->paren, open_paren); + } } } } diff --git a/decompiler/IR2/Form.cpp b/decompiler/IR2/Form.cpp index bb0afbfc0d..97b1a04342 100644 --- a/decompiler/IR2/Form.cpp +++ b/decompiler/IR2/Form.cpp @@ -1467,6 +1467,10 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) { return "!="; case FixedOperatorKind::METHOD_OF_OBJECT: return "method-of-object"; + case FixedOperatorKind::NULLP: + return "null?"; + case FixedOperatorKind::PAIRP: + return "pair?"; default: assert(false); } diff --git a/decompiler/IR2/Form.h b/decompiler/IR2/Form.h index 428129abdc..f127600bc8 100644 --- a/decompiler/IR2/Form.h +++ b/decompiler/IR2/Form.h @@ -436,11 +436,26 @@ class ConditionElement : public FormElement { FormPool& pool, const std::vector& source_forms, const std::vector& types); - FormElement* make_zero_check_generic(const Env& env, FormPool& pool, const std::vector& source_forms, const std::vector& types); + FormElement* make_equal_check_generic(const Env& env, + FormPool& pool, + const std::vector& source_forms, + const std::vector& types); + FormElement* make_not_equal_check_generic(const Env& env, + FormPool& pool, + const std::vector& source_forms, + const std::vector& types); + FormElement* make_less_than_zero_signed_check_generic(const Env& env, + FormPool& pool, + const std::vector& source_forms, + const std::vector& types); + FormElement* make_geq_zero_signed_check_generic(const Env& env, + FormPool& pool, + const std::vector& source_forms, + const std::vector& types); private: IR2_Condition::Kind m_kind; diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index 6312966cc3..b2fb6b8ea9 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -1878,7 +1878,7 @@ FormElement* ConditionElement::make_zero_check_generic(const Env&, const std::vector& source_forms, const std::vector&) { // (zero? (+ thing small-integer)) -> (= thing (- small-integer)) - + assert(source_forms.size() == 1); auto mr = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION), {Matcher::any(0), Matcher::any_integer(1)}), source_forms.at(0)); @@ -1893,6 +1893,109 @@ FormElement* ConditionElement::make_zero_check_generic(const Env&, } } +FormElement* ConditionElement::make_equal_check_generic(const Env&, + FormPool& pool, + const std::vector& source_forms, + const std::vector&) { + assert(source_forms.size() == 2); + // (= thing '()) + auto ref = source_forms.at(1); + auto ref_atom = form_as_atom(ref); + if (ref_atom && ref_atom->get_kind() == SimpleAtom::Kind::EMPTY_LIST) { + // null? + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::NULLP), + source_forms.at(0)); + } else { + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::EQ), + source_forms); + } +} + +FormElement* ConditionElement::make_not_equal_check_generic(const Env&, + FormPool& pool, + const std::vector& source_forms, + const std::vector&) { + assert(source_forms.size() == 2); + // (!= thing '()) + auto ref = source_forms.at(1); + auto ref_atom = form_as_atom(ref); + if (ref_atom && ref_atom->get_kind() == SimpleAtom::Kind::EMPTY_LIST) { + // null? + return pool.alloc_element( + GenericOperator::make_compare(IR2_Condition::Kind::FALSE), + pool.alloc_single_element_form( + nullptr, GenericOperator::make_fixed(FixedOperatorKind::NULLP), source_forms.at(0))); + } else { + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::NEQ), + source_forms); + } +} + +FormElement* ConditionElement::make_less_than_zero_signed_check_generic( + const Env&, + FormPool& pool, + const std::vector& source_forms, + const std::vector& types) { + assert(source_forms.size() == 1); + // (< (shl (the-as int iter) 62) 0) -> (pair? iter) + + // match (shl [(the-as int [x]) | [x]] 62) + auto shift_match = + match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHL), + { + Matcher::match_or({Matcher::cast("int", Matcher::any(0)), + Matcher::any(0)}), // the val + Matcher::integer(62) // get the bit in the highest position. + }), + source_forms.at(0)); + + if (shift_match.matched) { + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::PAIRP), + shift_match.maps.forms.at(0)); + } else { + auto casted = make_cast(source_forms, types, TypeSpec("int"), pool); + auto zero = pool.alloc_single_element_form(nullptr, + SimpleAtom::make_int_constant(0)); + casted.push_back(zero); + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::LT), + casted); + } +} + +FormElement* ConditionElement::make_geq_zero_signed_check_generic( + const Env&, + FormPool& pool, + const std::vector& source_forms, + const std::vector& types) { + assert(source_forms.size() == 1); + // (>= (shl (the-as int iter) 62) 0) -> (not (pair? iter)) + + // match (shl [(the-as int [x]) | [x]] 62) + auto shift_match = + match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHL), + { + Matcher::match_or({Matcher::cast("int", Matcher::any(0)), + Matcher::any(0)}), // the val + Matcher::integer(62) // get the bit in the highest position. + }), + source_forms.at(0)); + + if (shift_match.matched) { + return pool.alloc_element( + GenericOperator::make_compare(IR2_Condition::Kind::FALSE), + pool.alloc_single_element_form( + nullptr, GenericOperator::make_fixed(FixedOperatorKind::PAIRP), + shift_match.maps.forms.at(0))); + } else { + auto casted = make_cast(source_forms, types, TypeSpec("int"), pool); + auto zero = pool.alloc_single_element_form(nullptr, + SimpleAtom::make_int_constant(0)); + casted.push_back(zero); + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::GEQ), + casted); + } +} + FormElement* ConditionElement::make_generic(const Env& env, FormPool& pool, const std::vector& source_forms, @@ -1911,11 +2014,10 @@ FormElement* ConditionElement::make_generic(const Env& env, return pool.alloc_element(GenericOperator::make_compare(m_kind), source_forms); case IR2_Condition::Kind::EQUAL: - return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::EQ), - source_forms); + return make_equal_check_generic(env, pool, source_forms, types); + case IR2_Condition::Kind::NOT_EQUAL: - return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::NEQ), - source_forms); + return make_not_equal_check_generic(env, pool, source_forms, types); case IR2_Condition::Kind::LESS_THAN_SIGNED: return pool.alloc_element( @@ -1937,12 +2039,7 @@ FormElement* ConditionElement::make_generic(const Env& env, make_cast(source_forms, types, TypeSpec("int"), pool)); case IR2_Condition::Kind::LESS_THAN_ZERO_SIGNED: { - auto casted = make_cast(source_forms, types, TypeSpec("int"), pool); - auto zero = pool.alloc_single_element_form( - nullptr, SimpleAtom::make_int_constant(0)); - casted.push_back(zero); - return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::LT), - casted); + return make_less_than_zero_signed_check_generic(env, pool, source_forms, types); } case IR2_Condition::Kind::LEQ_ZERO_SIGNED: { @@ -1955,12 +2052,7 @@ FormElement* ConditionElement::make_generic(const Env& env, } case IR2_Condition::Kind::GEQ_ZERO_SIGNED: { - auto casted = make_cast(source_forms, types, TypeSpec("int"), pool); - auto zero = pool.alloc_single_element_form( - nullptr, SimpleAtom::make_int_constant(0)); - casted.push_back(zero); - return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::GEQ), - casted); + return make_geq_zero_signed_check_generic(env, pool, source_forms, types); } case IR2_Condition::Kind::GREATER_THAN_ZERO_UNSIGNED: { diff --git a/decompiler/IR2/IR2_common.h b/decompiler/IR2/IR2_common.h index a4b344f782..b5073c5bfd 100644 --- a/decompiler/IR2/IR2_common.h +++ b/decompiler/IR2/IR2_common.h @@ -136,6 +136,8 @@ enum class FixedOperatorKind { NEQ, CONS, METHOD_OF_OBJECT, + NULLP, + PAIRP, INVALID }; @@ -154,23 +156,29 @@ struct UseDefInfo { void disable_use(int op_id) { for (auto& x : uses) { if (x.op_id == op_id) { - assert(!x.disabled); + if (x.disabled) { + throw std::runtime_error("Invalid disable use twice"); + } x.disabled = true; return; } } - assert(false); + + throw std::runtime_error("Invalid disable use"); } void disable_def(int op_id) { for (auto& x : defs) { if (x.op_id == op_id) { - assert(!x.disabled); + if (x.disabled) { + throw std::runtime_error("Invalid disable def twice"); + } x.disabled = true; return; } } - assert(false); + + throw std::runtime_error("Invalid disable def"); } int use_count() const { diff --git a/decompiler/IR2/OpenGoalMapping.h b/decompiler/IR2/OpenGoalMapping.h index d029143f53..88a117a2f3 100644 --- a/decompiler/IR2/OpenGoalMapping.h +++ b/decompiler/IR2/OpenGoalMapping.h @@ -40,9 +40,9 @@ struct OpenGOALAsm { bool valid = true; bool todo = false; + Instruction instr; std::optional m_dst; std::vector> m_src; - Instruction instr; OpenGOALAsm::Function func; std::string full_function_name(); diff --git a/decompiler/analysis/cfg_builder.cpp b/decompiler/analysis/cfg_builder.cpp index badf03889d..7738b05a76 100644 --- a/decompiler/analysis/cfg_builder.cpp +++ b/decompiler/analysis/cfg_builder.cpp @@ -678,8 +678,12 @@ void clean_up_cond_no_else_final(Function& func, CondNoElseElement* cne) { auto reg = cne->entries.at(i).false_destination; assert(reg.has_value()); assert(branch); - assert(branch_info_i.written_and_unused.find(reg->reg()) != - branch_info_i.written_and_unused.end()); + if (branch_info_i.written_and_unused.find(reg->reg()) == + branch_info_i.written_and_unused.end()) { + throw std::runtime_error("Bad delay slot in clean_up_cond_no_else_final"); + } + // assert(branch_info_i.written_and_unused.find(reg->reg()) != + // branch_info_i.written_and_unused.end()); } } diff --git a/decompiler/analysis/final_output.cpp b/decompiler/analysis/final_output.cpp index c5718a13f5..f70b47c3aa 100644 --- a/decompiler/analysis/final_output.cpp +++ b/decompiler/analysis/final_output.cpp @@ -228,10 +228,11 @@ std::string write_from_top_level(const Function& top_level, auto method_match_result = match(method_def_matcher, &f); if (method_match_result.matched) { auto func = file.try_get_function_at_label(method_match_result.maps.label.at(method_label)); - if (func) { + if (func && func->guessed_name.kind == FunctionName::FunctionKind::METHOD) { something_matched = true; - result += fmt::format(";; definition for method of type {}\n", - method_match_result.maps.strings.at(type_name)); + result += + fmt::format(";; definition for method {} of type {}\n", func->guessed_name.method_id, + method_match_result.maps.strings.at(type_name)); if (skip_functions.find(func->guessed_name.to_string()) == skip_functions.end()) { result += careful_function_to_string(func, dts); } else { @@ -248,7 +249,7 @@ std::string write_from_top_level(const Function& top_level, if (dts.ts.fully_defined_type_exists(name)) { result += fmt::format(";; definition of type {}\n", name); result += dts.ts.generate_deftype(dts.ts.lookup_type(name)); - result += "\n\n"; + result += "\n"; } else { result += fmt::format( ";; type {} is defined here, but it is unknown to the decompiler\n\n", name); diff --git a/decompiler/analysis/inline_asm_rewrite.cpp b/decompiler/analysis/inline_asm_rewrite.cpp index 7ce8278183..df34185427 100644 --- a/decompiler/analysis/inline_asm_rewrite.cpp +++ b/decompiler/analysis/inline_asm_rewrite.cpp @@ -13,7 +13,7 @@ namespace decompiler { bool rewrite_inline_asm_instructions(Form* top_level_form, FormPool& pool, Function& f, - const DecompilerTypeSystem& dts) { + const DecompilerTypeSystem&) { assert(top_level_form); try { diff --git a/decompiler/analysis/insert_lets.cpp b/decompiler/analysis/insert_lets.cpp index 61817cc765..f052e2b3ff 100644 --- a/decompiler/analysis/insert_lets.cpp +++ b/decompiler/analysis/insert_lets.cpp @@ -280,7 +280,8 @@ LetStats insert_lets(const Function& func, Env& env, FormPool& pool, Form* top_l kv.second.lca_form->at(i)->collect_vars(ras, true); bool uses = false; for (auto& ra : ras) { - if (env.get_variable_name(ra) == kv.second.var_name) { + if ((ra.reg().get_kind() == Reg::FPR || ra.reg().get_kind() == Reg::GPR) && + env.get_variable_name(ra) == kv.second.var_name) { uses = true; } } diff --git a/test/decompiler/reference/gcommon_REF.gc b/test/decompiler/reference/gcommon_REF.gc index e282f15e3e..d229b95a81 100644 --- a/test/decompiler/reference/gcommon_REF.gc +++ b/test/decompiler/reference/gcommon_REF.gc @@ -107,8 +107,7 @@ :flag-assert #x900000010 ) - -;; definition for method of type vec4s +;; definition for method 3 of type vec4s ;; INFO: Return type mismatch int vs vec4s. ;; WARN: Unsupported inline assembly instruction kind - [131] ;; WARN: Unsupported inline assembly instruction kind - [131] @@ -163,7 +162,7 @@ (the-as vec4s v0-5) ) -;; definition for method of type vec4s +;; definition for method 2 of type vec4s ;; INFO: Return type mismatch int vs vec4s. ;; WARN: Unsupported inline assembly instruction kind - [131] ;; WARN: Unsupported inline assembly instruction kind - [73] @@ -214,21 +213,20 @@ :flag-assert #x900000008 ) - -;; definition for method of type bfloat +;; definition for method 3 of type bfloat (defmethod inspect bfloat ((obj bfloat)) (format #t "[~8x] ~A~%" obj (-> obj type)) (format #t "~Tdata: ~f~%" (-> obj data)) obj ) -;; definition for method of type bfloat +;; definition for method 2 of type bfloat (defmethod print bfloat ((obj bfloat)) (format #t "~f" (-> obj data)) obj ) -;; definition for method of type type +;; 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 (+ (shl (-> obj allocated-length) 2) 43))) @@ -294,18 +292,18 @@ (car lst) ) -;; definition for method of type pair +;; definition for method 4 of type pair (defmethod length pair ((obj pair)) (local-vars (result int)) (cond - ((= obj '()) + ((null? obj) (set! result 0) ) (else (let ((iter (cdr obj)) ) (set! result 1) - (while (and (!= iter '()) (< (shl (the-as int iter) 62) 0)) + (while (and (not (null? iter)) (pair? iter)) (+! result 1) (set! iter (cdr iter)) ) @@ -315,7 +313,7 @@ result ) -;; definition for method of type pair +;; definition for method 5 of type pair ;; INFO: Return type mismatch uint vs int. (defmethod asize-of pair ((obj pair)) (the-as int (-> pair size)) @@ -325,7 +323,7 @@ (defun last ((lst object)) (let ((iter lst) ) - (while (!= (cdr iter) '()) + (while (not (null? (cdr iter))) (nop!) (nop!) (set! iter (cdr iter)) @@ -338,10 +336,10 @@ (defun member ((obj object) (lst object)) (let ((iter lst) ) - (while (not (or (= iter '()) (= (car iter) obj))) + (while (not (or (null? iter) (= (car iter) obj))) (set! iter (cdr iter)) ) - (if (!= iter '()) + (if (not (null? iter)) iter ) ) @@ -349,10 +347,10 @@ ;; definition for function nmember (defun nmember ((obj basic) (lst object)) - (while (not (or (= lst '()) (name= (the-as basic (car lst)) obj))) + (while (not (or (null? lst) (name= (the-as basic (car lst)) obj))) (set! lst (cdr lst)) ) - (if (!= lst '()) + (if (not (null? lst)) lst ) ) @@ -361,10 +359,10 @@ (defun assoc ((item object) (alist object)) (let ((iter alist) ) - (while (not (or (= iter '()) (= (car (car iter)) item))) + (while (not (or (null? iter) (= (car (car iter)) item))) (set! iter (cdr iter)) ) - (if (!= iter '()) + (if (not (null? iter)) (car iter) ) ) @@ -375,10 +373,10 @@ (let ((iter alist) ) (while - (not (or (= iter '()) (= (car (car iter)) item) (= (car (car iter)) 'else))) + (not (or (null? iter) (= (car (car iter)) item) (= (car (car iter)) 'else))) (set! iter (cdr iter)) ) - (if (!= iter '()) + (if (not (null? iter)) (car iter) ) ) @@ -386,7 +384,7 @@ ;; definition for function nassoc (defun nassoc ((item-name string) (alist object)) - (while (not (or (= alist '()) (let ((key (car (car alist))) + (while (not (or (null? alist) (let ((key (car (car alist))) ) (if (pair? key) (nmember item-name key) @@ -397,14 +395,14 @@ ) (set! alist (cdr alist)) ) - (if (!= alist '()) + (if (not (null? alist)) (car alist) ) ) ;; definition for function nassoce (defun nassoce ((item-name string) (alist object)) - (while (not (or (= alist '()) (let ((key (car (car alist))) + (while (not (or (null? alist) (let ((key (car (car alist))) ) (if (pair? key) (nmember item-name key) @@ -418,7 +416,7 @@ ) (set! alist (cdr alist)) ) - (if (!= alist '()) + (if (not (null? alist)) (car alist) ) ) @@ -426,18 +424,18 @@ ;; definition for function append! (defun append! ((front object) (back object)) (cond - ((= front '()) + ((null? front) back ) (else (let ((iter front) ) - (while (!= (cdr iter) '()) + (while (not (null? (cdr iter))) (nop!) (nop!) (set! iter (cdr iter)) ) - (if (!= iter '()) + (if (not (null? iter)) (set! (cdr iter) back) ) ) @@ -457,11 +455,11 @@ (let ((iter-prev lst) (iter (cdr lst)) ) - (while (not (or (= iter '()) (= (car iter) item))) + (while (not (or (null? iter) (= (car iter) item))) (set! iter-prev iter) (set! iter (cdr iter)) ) - (if (!= iter '()) + (if (not (null? iter)) (set! (cdr iter-prev) (cdr iter)) ) ) @@ -481,11 +479,11 @@ (let ((iter-prev lst) (iter (cdr lst)) ) - (while (not (or (= iter '()) (= (car (car iter)) item))) + (while (not (or (null? iter) (= (car (car iter)) item))) (set! iter-prev iter) (set! iter (cdr iter)) ) - (if (!= iter '()) + (if (not (null? iter)) (set! (cdr iter-prev) (cdr iter)) ) ) @@ -510,8 +508,7 @@ (set! unsorted-count 0) (let ((iter lst) ) - (while - (not (or (= (cdr iter) '()) (>= (shl (the-as int (cdr iter)) 62) 0))) + (while (not (or (null? (cdr iter)) (not (pair? (cdr iter))))) (let* ((first-elt (car iter)) (seoncd-elt (car (cdr iter))) (compare-result (compare-func first-elt seoncd-elt)) @@ -549,8 +546,7 @@ ) ) - -;; definition for method of type inline-array-class +;; definition for method 3 of type inline-array-class (defmethod inspect inline-array-class ((obj inline-array-class)) (format #t "[~8x] ~A~%" obj (-> obj type)) (format #t "~Tlength: ~D~%" (-> obj length)) @@ -558,7 +554,7 @@ obj ) -;; definition for method of type inline-array-class +;; definition for method 0 of type inline-array-class (defmethod new inline-array-class @@ -586,12 +582,12 @@ ) ) -;; definition for method of type inline-array-class +;; definition for method 4 of type inline-array-class (defmethod length inline-array-class ((obj inline-array-class)) (-> obj length) ) -;; definition for method of type inline-array-class +;; definition for method 5 of type inline-array-class ;; INFO: Return type mismatch uint vs int. (defmethod asize-of inline-array-class ((obj inline-array-class)) (the-as @@ -606,7 +602,7 @@ ) ) -;; definition for method of type array +;; definition for method 0 of type array (defmethod new array @@ -638,7 +634,7 @@ ) ) -;; definition for method of type array +;; definition for method 2 of type array ;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] (defmethod print array ((obj array)) (local-vars @@ -822,7 +818,7 @@ obj ) -;; definition for method of type array +;; definition for method 3 of type array ;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] (defmethod inspect array ((obj array)) (local-vars @@ -955,12 +951,12 @@ obj ) -;; definition for method of type array +;; definition for method 4 of type array (defmethod length array ((obj array)) (-> obj length) ) -;; definition for method of type array +;; definition for method 5 of type array ;; INFO: Return type mismatch uint vs int. (defmethod asize-of array ((obj array)) (the-as diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index ff04febd28..ca1c8f9698 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -704,13 +704,13 @@ TEST_F(FormRegressionTest, ExprPairMethod4) { std::string expected = "(begin\n" " (cond\n" - " ((= arg0 (quote ())) (set! v0-0 0))\n" + " ((null? arg0) (set! v0-0 0))\n" " (else\n" " (let\n" " ((v1-1 (cdr arg0)))\n" " (set! v0-0 1)\n" " (while\n" - " (and (!= v1-1 (quote ())) (< (shl (the-as int v1-1) 62) 0))\n" + " (and (not (null? v1-1)) (pair? v1-1))\n" " (+! v0-0 1)\n" " (set! v1-1 (cdr v1-1))\n" " )\n" @@ -762,7 +762,7 @@ TEST_F(FormRegressionTest, ExprLast) { std::string expected = "(let\n" " ((v0-0 arg0))\n" - " (while (!= (cdr v0-0) (quote ())) (nop!) (nop!) (set! v0-0 (cdr v0-0)))\n" + " (while (not (null? (cdr v0-0))) (nop!) (nop!) (set! v0-0 (cdr v0-0)))\n" " v0-0\n" " )"; test_with_expr(func, type, expected, true, ""); @@ -812,10 +812,10 @@ TEST_F(FormRegressionTest, ExprMember) { "(let\n" " ((v1-0 arg1))\n" " (while\n" - " (not (or (= v1-0 (quote ())) (= (car v1-0) arg0)))\n" + " (not (or (null? v1-0) (= (car v1-0) arg0)))\n" " (set! v1-0 (cdr v1-0))\n" " )\n" - " (if (!= v1-0 (quote ())) v1-0)\n" + " (if (not (null? v1-0)) v1-0)\n" " )"; test_with_expr(func, type, expected, true, ""); } @@ -874,10 +874,10 @@ TEST_F(FormRegressionTest, ExprNmember) { std::string expected = "(begin\n" " (while\n" - " (not (or (= arg1 '()) (name= (the-as basic (car arg1)) arg0)))\n" + " (not (or (null? arg1) (name= (the-as basic (car arg1)) arg0)))\n" " (set! arg1 (cdr arg1))\n" " )\n" - " (if (!= arg1 '()) arg1)\n" + " (if (not (null? arg1)) arg1)\n" " )"; test_with_expr(func, type, expected, true, ""); } @@ -925,10 +925,10 @@ TEST_F(FormRegressionTest, ExprAssoc) { "(let\n" " ((v1-0 arg1))\n" " (while\n" - " (not (or (= v1-0 (quote ())) (= (car (car v1-0)) arg0)))\n" + " (not (or (null? v1-0) (= (car (car v1-0)) arg0)))\n" " (set! v1-0 (cdr v1-0))\n" " )\n" - " (if (!= v1-0 (quote ())) (car v1-0))\n" + " (if (not (null? v1-0)) (car v1-0))\n" " )"; test_with_expr(func, type, expected, true, ""); } @@ -989,14 +989,14 @@ TEST_F(FormRegressionTest, ExprAssoce) { " (while\n" " (not\n" " (or\n" - " (= v1-0 (quote ()))\n" + " (null? v1-0)\n" " (= (car (car v1-0)) arg0)\n" " (= (car (car v1-0)) (quote else))\n" " )\n" " )\n" " (set! v1-0 (cdr v1-0))\n" " )\n" - " (if (!= v1-0 (quote ())) (car v1-0))\n" + " (if (not (null? v1-0)) (car v1-0))\n" " )"; test_with_expr(func, type, expected, true, ""); } @@ -1074,7 +1074,7 @@ TEST_F(FormRegressionTest, ExprNassoc) { " (while\n" " (not\n" " (or\n" - " (= arg1 (quote ()))\n" + " (null? arg1)\n" " (let\n" " ((a1-1 (car (car arg1))))\n" " (if\n" @@ -1087,7 +1087,7 @@ TEST_F(FormRegressionTest, ExprNassoc) { " )\n" " (set! arg1 (cdr arg1))\n" " )\n" - " (if (!= arg1 (quote ())) (car arg1))\n" + " (if (not (null? arg1)) (car arg1))\n" " )"; test_with_expr(func, type, expected, true, ""); } @@ -1176,7 +1176,7 @@ TEST_F(FormRegressionTest, ExprNassoce) { " (while\n" " (not\n" " (or\n" - " (= arg1 (quote ()))\n" + " (null? arg1)\n" " (let\n" " ((s4-0 (car (car arg1))))\n" " (if\n" @@ -1192,7 +1192,7 @@ TEST_F(FormRegressionTest, ExprNassoce) { " )\n" " (set! arg1 (cdr arg1))\n" " )\n" - " (if (!= arg1 (quote ())) (car arg1))\n" + " (if (not (null? arg1)) (car arg1))\n" " )"; test_with_expr(func, type, expected, true, ""); } @@ -1243,12 +1243,12 @@ TEST_F(FormRegressionTest, ExprAppend) { std::string expected = "(cond\n" - " ((= arg0 (quote ())) arg1)\n" + " ((null? arg0) arg1)\n" " (else\n" " (let\n" " ((v1-1 arg0))\n" - " (while (!= (cdr v1-1) (quote ())) (nop!) (nop!) (set! v1-1 (cdr v1-1)))\n" - " (if (!= v1-1 (quote ())) (set! (cdr v1-1) arg1))\n" + " (while (not (null? (cdr v1-1))) (nop!) (nop!) (set! v1-1 (cdr v1-1)))\n" + " (if (not (null? v1-1)) (set! (cdr v1-1) arg1))\n" " )\n" " arg0\n" " )\n" @@ -1320,11 +1320,11 @@ TEST_F(FormRegressionTest, ExprDelete) { " (let\n" " ((v1-1 arg1) (a2-0 (cdr arg1)))\n" " (while\n" - " (not (or (= a2-0 (quote ())) (= (car a2-0) arg0)))\n" + " (not (or (null? a2-0) (= (car a2-0) arg0)))\n" " (set! v1-1 a2-0)\n" " (set! a2-0 (cdr a2-0))\n" " )\n" - " (if (!= a2-0 (quote ())) (set! (cdr v1-1) (cdr a2-0)))\n" + " (if (not (null? a2-0)) (set! (cdr v1-1) (cdr a2-0)))\n" " )\n" " arg1\n" " )\n" @@ -1399,11 +1399,11 @@ TEST_F(FormRegressionTest, ExprDeleteCar) { " (let\n" " ((v1-2 arg1) (a2-0 (cdr arg1)))\n" " (while\n" - " (not (or (= a2-0 (quote ())) (= (car (car a2-0)) arg0)))\n" + " (not (or (null? a2-0) (= (car (car a2-0)) arg0)))\n" " (set! v1-2 a2-0)\n" " (set! a2-0 (cdr a2-0))\n" " )\n" - " (if (!= a2-0 (quote ())) (set! (cdr v1-2) (cdr a2-0)))\n" + " (if (not (null? a2-0)) (set! (cdr v1-2) (cdr a2-0)))\n" " )\n" " arg1\n" " )\n" @@ -1560,7 +1560,7 @@ TEST_F(FormRegressionTest, ExprSort) { " ((s3-0 arg0))\n" " (while\n" " (not\n" - " (or (= (cdr s3-0) (quote ())) (>= (shl (the-as int (cdr s3-0)) 62) 0))\n" + " (or (null? (cdr s3-0)) (not (pair? (cdr s3-0))))\n" " )\n" " (let*\n" " ((s2-0 (car s3-0)) (s1-0 (car (cdr s3-0))) (v1-1 (arg1 s2-0 s1-0)))\n" diff --git a/test/offline/offline_test_main.cpp b/test/offline/offline_test_main.cpp index fb10d82d69..db2033fdc9 100644 --- a/test/offline/offline_test_main.cpp +++ b/test/offline/offline_test_main.cpp @@ -41,18 +41,21 @@ const std::unordered_set expected_skip_in_decompiler = { const std::unordered_set skip_in_compiling = { // these functions are not implemented by the compiler in OpenGOAL, but are in GOAL. "abs", "ash", "min", "max", "lognor", + // weird PS2 specific debug registers: + "breakpoint-range-set!", // these require 128-bit integers. We want these eventually, but disabling for now to focus // on more important issues. - "(method 3 vec4s)", "(method 2 vec4s)", + "(method 3 vec4s)", "(method 2 vec4s)", "qmem-copy<-!", "qmem-copy->!", // these should pass eventually - "(method 2 array)", "(method 3 array)", "valid?", "mem-copy!", "qmem-copy<-!", "qmem-copy->!", - "mem-or!", "breakpoint-range-set!", "print", "printl", "inspect"}; + "(method 2 array)", "(method 3 array)", "valid?", "mem-copy!", "mem-or!", "print", "printl", + "inspect"}; // The decompiler does not attempt to insert forward definitions, as this would be part of an // unimplemented full-program type analysis pass. For now, we manually specify all functions // that should have a forward definition here. const std::string g_forward_type_defs = "(define-extern name= (function basic basic symbol))\n" + // todo - check if recursive? "(define-extern fact (function int int))"; // default location for the data. It can be changed with a command line argument. From f827c05f16c2ef0edd6e81c7746fb26a56a20d3b Mon Sep 17 00:00:00 2001 From: water Date: Sat, 6 Mar 2021 19:48:57 -0500 Subject: [PATCH 3/3] fix pointer cast signed vs unsigned issue --- decompiler/IR2/AtomicOpForm.cpp | 7 + .../jak1_ntsc_black_label/var_names.jsonc | 7 +- test/decompiler/reference/gcommon_REF.gc | 213 ++++++------------ test/decompiler/test_FormExpressionBuild.cpp | 4 +- test/offline/offline_test_main.cpp | 14 +- 5 files changed, 90 insertions(+), 155 deletions(-) diff --git a/decompiler/IR2/AtomicOpForm.cpp b/decompiler/IR2/AtomicOpForm.cpp index c5daae7703..75ee812fee 100644 --- a/decompiler/IR2/AtomicOpForm.cpp +++ b/decompiler/IR2/AtomicOpForm.cpp @@ -267,6 +267,13 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const { assert(false); } + if (m_value.is_var()) { + auto input_var_type = env.get_types_before_op(m_my_idx).get(m_value.var().reg()); + if (env.dts->ts.tc(TypeSpec("uinteger"), input_var_type.typespec())) { + cast_type.insert(cast_type.begin(), 'u'); + } + } + auto source = pool.alloc_single_element_form( nullptr, SimpleAtom::make_var(ro.var).as_expr(), m_my_idx); auto cast_source = pool.alloc_single_element_form( diff --git a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc index f7e2b7d250..37ceb6b757 100644 --- a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc @@ -148,14 +148,11 @@ }, "(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"} + "vars":{"v1-1":"content-type-sym"} }, "(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"} + "vars":{"v1-1":"content-type-sym"} }, "mem-copy!":{ diff --git a/test/decompiler/reference/gcommon_REF.gc b/test/decompiler/reference/gcommon_REF.gc index d229b95a81..7e4bd43a73 100644 --- a/test/decompiler/reference/gcommon_REF.gc +++ b/test/decompiler/reference/gcommon_REF.gc @@ -637,154 +637,121 @@ ;; definition for method 2 of type array ;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] (defmethod print array ((obj array)) - (local-vars - (a2-8 int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - ) + (local-vars (a2-8 int)) (format #t "#(") (if (type-type? (-> obj content-type) integer) (let ((content-type-sym (-> obj content-type symbol)) ) (cond ((= content-type-sym 'int32) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-0 (-> obj length)) + (format #t (if (zero? s5-0) "~D" " ~D" ) - (-> (the-as (array int32) obj) i) + (-> (the-as (array int32) obj) s5-0) ) - (+! i 1) ) ) ((= content-type-sym 'uint32) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-1 (-> obj length)) + (format #t (if (zero? s5-1) "~D" " ~D" ) - (-> (the-as (array uint32) obj) i) + (-> (the-as (array uint32) obj) s5-1) ) - (+! i 1) ) ) ((= content-type-sym 'int64) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-2 (-> obj length)) + (format #t (if (zero? s5-2) "~D" " ~D" ) - (-> (the-as (array int64) obj) i) + (-> (the-as (array int64) obj) s5-2) ) - (+! i 1) ) ) ((= content-type-sym 'uint64) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-3 (-> obj length)) + (format #t (if (zero? s5-3) "#x~X" " #x~X" ) - (-> (the-as (array uint64) obj) i) + (-> (the-as (array uint64) obj) s5-3) ) - (+! i 1) ) ) ((= content-type-sym 'int8) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-4 (-> obj length)) + (format #t (if (zero? s5-4) "~D" " ~D" ) - (-> (the-as (array int8) obj) i) + (-> (the-as (array int8) obj) s5-4) ) - (+! i 1) ) ) ((= content-type-sym 'uint8) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-5 (-> obj length)) + (format #t (if (zero? s5-5) "~D" " ~D" ) - (-> (the-as (array uint8) obj) i) + (-> (the-as (array uint8) obj) s5-5) ) - (+! i 1) ) ) ((= content-type-sym 'int16) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-6 (-> obj length)) + (format #t (if (zero? s5-6) "~D" " ~D" ) - (-> (the-as (array int16) obj) i) + (-> (the-as (array int16) obj) s5-6) ) - (+! i 1) ) ) ((= content-type-sym 'uint16) - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-7 (-> obj length)) + (format #t (if (zero? s5-7) "~D" " ~D" ) - (-> (the-as (array uint16) obj) i) + (-> (the-as (array uint16) obj) s5-7) ) - (+! i 1) ) ) (else (cond ((or (= content-type-sym 'uint128) (= content-type-sym 'int128)) - (set! i 0) - (while (< i (-> obj length)) + (dotimes (s5-8 (-> obj length)) (let ((t9-10 format) (a0-21 #t) - (a1-11 (if (zero? i) + (a1-11 (if (zero? s5-8) "#x~X" " #x~X" ) ) ) - (let ((v1-42 (+ (shl i 4) (the-as int (the-as (array uint128) obj)))) - ) + (let + ((v1-42 (+ (shl s5-8 4) (the-as int (the-as (array uint128) obj)))) + ) (TODO.LQ a2-8 v1-42 :offset 12) ) (t9-10 a0-21 a1-11 a2-8) ) - (+! i 1) ) ) (else - (set! i 0) - (while (< i (-> obj length)) - (format #t (if (zero? i) + (dotimes (s5-9 (-> obj length)) + (format #t (if (zero? s5-9) "~D" " ~D" ) - (-> (the-as (array int32) obj) i) + (-> (the-as (array int32) obj) s5-9) ) - (+! i 1) ) ) ) @@ -793,23 +760,19 @@ ) (cond ((= (-> obj content-type) float) - (set! i 0) - (while (< i (-> obj length)) - (if (zero? i) - (format #t "~f" (-> (the-as (array float) obj) i)) - (format #t " ~f" (-> (the-as (array float) obj) i)) + (dotimes (s5-10 (-> obj length)) + (if (zero? s5-10) + (format #t "~f" (-> (the-as (array float) obj) s5-10)) + (format #t " ~f" (-> (the-as (array float) obj) s5-10)) ) - (+! i 1) ) ) (else - (set! i 0) - (while (< i (-> obj length)) - (if (zero? i) - (format #t "~A" (-> (the-as (array basic) obj) i)) - (format #t " ~A" (-> (the-as (array basic) obj) i)) + (dotimes (s5-11 (-> obj length)) + (if (zero? s5-11) + (format #t "~A" (-> (the-as (array basic) obj) s5-11)) + (format #t " ~A" (-> (the-as (array basic) obj) s5-11)) ) - (+! i 1) ) ) ) @@ -821,21 +784,7 @@ ;; definition for method 3 of type array ;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] (defmethod inspect array ((obj array)) - (local-vars - (a3-10 int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - (i int) - ) + (local-vars (a3-10 int)) (format #t "[~8x] ~A~%" obj (-> obj type)) (format #t "~Tallocated-length: ~D~%" (-> obj allocated-length)) (format #t "~Tlength: ~D~%" (-> obj length)) @@ -846,85 +795,65 @@ ) (cond ((= content-type-sym 'int32) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> (the-as (array int32) obj) i)) - (+! i 1) + (dotimes (s5-0 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-0 (-> (the-as (array int32) obj) s5-0)) ) ) ((= content-type-sym 'uint32) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> (the-as (array uint32) obj) i)) - (+! i 1) + (dotimes (s5-1 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-1 (-> (the-as (array uint32) obj) s5-1)) ) ) ((= content-type-sym 'int64) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> (the-as (array int64) obj) i)) - (+! i 1) + (dotimes (s5-2 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-2 (-> (the-as (array int64) obj) s5-2)) ) ) ((= content-type-sym 'uint64) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] #x~X~%" i (-> (the-as (array uint64) obj) i)) - (+! i 1) + (dotimes (s5-3 (-> obj length)) + (format #t "~T [~D] #x~X~%" s5-3 (-> (the-as (array uint64) obj) s5-3)) ) ) ((= content-type-sym 'int8) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) - (+! i 1) + (dotimes (s5-4 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-4 (-> (the-as (array int8) obj) s5-4)) ) ) ((= content-type-sym 'uint8) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> (the-as (array int8) obj) i)) - (+! i 1) + (dotimes (s5-5 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-5 (-> (the-as (array int8) obj) s5-5)) ) ) ((= content-type-sym 'int16) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> (the-as (array int16) obj) i)) - (+! i 1) + (dotimes (s5-6 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-6 (-> (the-as (array int16) obj) s5-6)) ) ) ((= content-type-sym 'uint16) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> (the-as (array uint16) obj) i)) - (+! i 1) + (dotimes (s5-7 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-7 (-> (the-as (array uint16) obj) s5-7)) ) ) (else (cond ((or (= content-type-sym 'int128) (= content-type-sym 'uint128)) - (set! i 0) - (while (< i (-> obj length)) + (dotimes (s5-8 (-> obj length)) (let ((t9-14 format) (a0-25 #t) (a1-15 "~T [~D] #x~X~%") - (a2-13 i) + (a2-13 s5-8) ) - (let ((v1-42 (+ (shl i 4) (the-as int obj))) + (let ((v1-42 (+ (shl s5-8 4) (the-as int obj))) ) (TODO.LQ a3-10 v1-42 :offset 12) ) (t9-14 a0-25 a1-15 a2-13 a3-10) ) - (+! i 1) ) ) (else - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~D~%" i (-> obj i)) - (+! i 1) + (dotimes (s5-9 (-> obj length)) + (format #t "~T [~D] ~D~%" s5-9 (-> obj s5-9)) ) ) ) @@ -933,17 +862,13 @@ ) (cond ((= (-> obj content-type) float) - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~f~%" i (-> obj i)) - (+! i 1) + (dotimes (s5-10 (-> obj length)) + (format #t "~T [~D] ~f~%" s5-10 (-> obj s5-10)) ) ) (else - (set! i 0) - (while (< i (-> obj length)) - (format #t "~T [~D] ~A~%" i (-> obj i)) - (+! i 1) + (dotimes (s5-11 (-> obj length)) + (format #t "~T [~D] ~A~%" s5-11 (-> obj s5-11)) ) ) ) @@ -980,7 +905,7 @@ (let ((result dst) ) (dotimes (i size) - (set! (-> (the-as (pointer int8) dst)) (-> (the-as (pointer uint8) src))) + (set! (-> (the-as (pointer uint8) dst)) (-> (the-as (pointer uint8) src))) (&+! dst 1) (&+! src 1) ) @@ -1051,7 +976,7 @@ ) (dotimes (i size) (set! - (-> (the-as (pointer int8) dst)) + (-> (the-as (pointer uint8) dst)) (logior (-> (the-as (pointer uint8) dst)) (-> (the-as (pointer uint8) src)) diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index ca1c8f9698..d3df983f04 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -1858,7 +1858,7 @@ TEST_F(FormRegressionTest, ExprMemCopy) { " ((v0-0 arg0))\n" " (dotimes\n" " (v1-0 arg2)\n" - " (set! (-> (the-as (pointer int8) arg0)) (-> (the-as (pointer uint8) arg1)))\n" + " (set! (-> (the-as (pointer uint8) arg0)) (-> (the-as (pointer uint8) arg1)))\n" " (&+! arg0 1)\n" " (&+! arg1 1)\n" " )\n" @@ -1940,7 +1940,7 @@ TEST_F(FormRegressionTest, ExprMemOr) { " (dotimes\n" " (v1-0 arg2)\n" " (set!\n" - " (-> (the-as (pointer int8) arg0))\n" + " (-> (the-as (pointer uint8) arg0))\n" " (logior\n" " (-> (the-as (pointer uint8) arg0))\n" " (-> (the-as (pointer uint8) arg1))\n" diff --git a/test/offline/offline_test_main.cpp b/test/offline/offline_test_main.cpp index db2033fdc9..2c6d1f2a0f 100644 --- a/test/offline/offline_test_main.cpp +++ b/test/offline/offline_test_main.cpp @@ -39,16 +39,22 @@ const std::unordered_set expected_skip_in_decompiler = { }; const std::unordered_set skip_in_compiling = { + ////////////////////// + // GCOMMON + ////////////////////// + // these functions are not implemented by the compiler in OpenGOAL, but are in GOAL. "abs", "ash", "min", "max", "lognor", // weird PS2 specific debug registers: "breakpoint-range-set!", // these require 128-bit integers. We want these eventually, but disabling for now to focus // on more important issues. - "(method 3 vec4s)", "(method 2 vec4s)", "qmem-copy<-!", "qmem-copy->!", - // these should pass eventually - "(method 2 array)", "(method 3 array)", "valid?", "mem-copy!", "mem-or!", "print", "printl", - "inspect"}; + "(method 3 vec4s)", "(method 2 vec4s)", "qmem-copy<-!", "qmem-copy->!", "(method 2 array)", + "(method 3 array)", + // does weird stuff with the type system. + "print", "printl", "inspect", + // inline assembly + "valid?"}; // The decompiler does not attempt to insert forward definitions, as this would be part of an // unimplemented full-program type analysis pass. For now, we manually specify all functions