diff --git a/decompiler/IR2/AtomicOp.cpp b/decompiler/IR2/AtomicOp.cpp index fe09ed918b..9929768819 100644 --- a/decompiler/IR2/AtomicOp.cpp +++ b/decompiler/IR2/AtomicOp.cpp @@ -353,6 +353,10 @@ goos::Object SimpleExpression::to_form(const std::vector& label } } +std::string SimpleExpression::to_string(const Env& env) const { + return to_form(env.file->labels, env).print(); +} + bool SimpleExpression::operator==(const SimpleExpression& other) const { if (m_kind != other.m_kind) { return false; diff --git a/decompiler/IR2/AtomicOp.h b/decompiler/IR2/AtomicOp.h index 069b46a2b1..a55c4c25ac 100644 --- a/decompiler/IR2/AtomicOp.h +++ b/decompiler/IR2/AtomicOp.h @@ -233,6 +233,7 @@ class SimpleExpression { SimpleExpression(Kind kind, const SimpleAtom& arg0); SimpleExpression(Kind kind, const SimpleAtom& arg0, const SimpleAtom& arg1); goos::Object to_form(const std::vector& labels, const Env& env) const; + std::string to_string(const Env& env) const; bool operator==(const SimpleExpression& other) const; bool is_identity() const { return m_kind == Kind::IDENTITY; } bool is_var() const { return is_identity() && get_arg(0).is_var(); } diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index eb67c2501a..0de4952b56 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -359,13 +359,13 @@ TP_Type SimpleExpression::get_type_int2(const TypeState& input, if (m_kind == Kind::ADD && arg0_type.typespec().base_type() == "pointer" && tc(dts, TypeSpec("integer"), arg1_type)) { // plain pointer plus integer = plain pointer - return TP_Type::make_from_ts(TypeSpec("pointer")); + return TP_Type::make_from_ts(arg0_type.typespec()); } if (m_kind == Kind::ADD && arg1_type.typespec().base_type() == "pointer" && tc(dts, TypeSpec("integer"), arg0_type)) { // plain pointer plus integer = plain pointer - return TP_Type::make_from_ts(TypeSpec("pointer")); + return TP_Type::make_from_ts(arg1_type.typespec()); } if (tc(dts, TypeSpec("structure"), arg1_type) && !m_args[0].is_int() && diff --git a/decompiler/IR2/Form.cpp b/decompiler/IR2/Form.cpp index c8984db910..a0f4dd4679 100644 --- a/decompiler/IR2/Form.cpp +++ b/decompiler/IR2/Form.cpp @@ -1,10 +1,11 @@ #include "Form.h" +#include #include #include "decompiler/ObjectFile/LinkedObjectFile.h" #include "common/goos/PrettyPrinter.h" #include "common/type_system/TypeSystem.h" -#include +#include "decompiler/util/DecompilerTypeSystem.h" namespace decompiler { @@ -289,13 +290,23 @@ SetVarElement::SetVarElement(const RegisterAccess& var, : m_dst(var), m_src(value), m_is_sequence_point(is_sequence_point), - m_src_type(src_type), + m_src_type(std::move(src_type)), m_var_info(info) { value->parent_element = this; } goos::Object SetVarElement::to_form_internal(const Env& env) const { assert(active()); + auto reg_kind = m_dst.reg().get_kind(); + if ((reg_kind == Reg::FPR || reg_kind == Reg::GPR) && env.has_type_analysis()) { + auto expected_type = env.get_variable_type(m_dst, true); + if (!env.dts->ts.tc(expected_type, m_src_type)) { + return pretty_print::build_list( + "set!", m_dst.to_form(env), + pretty_print::build_list("the-as", expected_type.print(), m_src->to_form(env))); + } + } + return pretty_print::build_list("set!", m_dst.to_form(env), m_src->to_form(env)); } diff --git a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc index 5d2e8d3727..ddd202bdf5 100644 --- a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc @@ -20,6 +20,8 @@ ["L86", "_lambda_", true] ], + "gstring": [["L170", "float", true]], + "math": [ ["L41", "float", true], ["L34", "float", true], diff --git a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc index 0015910aad..b79aabc598 100644 --- a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc @@ -98,8 +98,15 @@ [17, "s5", "pointer"] ], + // GSTRING "name=": [ [24, "a1", "symbol"], [39, "a0", "symbol"] + ], + + "string-cat-to-last-char": [ + [3, "s5", "(pointer uint8)"], + [4, "s5", "string"] ] + } diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc index 1764e8e50a..e4cb65f2b4 100644 --- a/goal_src/goal-lib.gc +++ b/goal_src/goal-lib.gc @@ -343,6 +343,11 @@ ) +(defmacro empty () + "The decompiler may use (empty) as the body of a loop with nothing in it." + `(none) + ) + ;;;;;;;;;;;;;;;;;;; ;; Math Macros ;;;;;;;;;;;;;;;;;;; diff --git a/test/decompiler/reference/all_forward_declarations.gc b/test/decompiler/reference/all_forward_declarations.gc index 0eea3bd498..ce63d165dc 100644 --- a/test/decompiler/reference/all_forward_declarations.gc +++ b/test/decompiler/reference/all_forward_declarations.gc @@ -1,6 +1,8 @@ ;; GCOMMON (define-extern name= (function basic basic symbol)) (define-extern fact (function int int)) +(define-extern max (function int int int)) +(define-extern min (function int int int)) ;; KERNEL (declare-type process basic) diff --git a/test/decompiler/reference/gstring_REF.gc b/test/decompiler/reference/gstring_REF.gc new file mode 100644 index 0000000000..11579e8db5 --- /dev/null +++ b/test/decompiler/reference/gstring_REF.gc @@ -0,0 +1,740 @@ +;;-*-Lisp-*- +(in-package goal) + +;; definition for method 4 of type string +(defmethod length string ((obj string)) + (let ((v1-0 (-> obj data))) + (while (nonzero? (-> v1-0 0)) + (nop!) + (nop!) + (nop!) + (set! v1-0 (&-> v1-0 1)) + ) + (&- v1-0 (the-as uint (-> obj data))) + ) + ) + +;; definition for method 5 of type string +(defmethod asize-of string ((obj string)) + (+ (+ (-> obj allocated-length) 1) (the-as int (-> string size))) + ) + +;; definition for function copy-string<-string +(defun copy-string<-string ((arg0 string) (arg1 string)) + (let ((v1-0 (-> arg0 data))) + (let ((a1-1 (-> arg1 data))) + (while (nonzero? (-> a1-1 0)) + (set! (-> v1-0 0) (-> a1-1 0)) + (set! v1-0 (&-> v1-0 1)) + (set! a1-1 (&-> a1-1 1)) + ) + ) + (set! (-> v1-0 0) (the-as uint 0)) + ) + arg0 + ) + +;; definition for method 0 of type string +(defmethod + new + string + ((allocation symbol) (type-to-make type) (arg0 int) (arg1 string)) + (if arg1 (let* ((s2-1 (max ((method-of-type string length) arg1) arg0)) + (a0-4 + (object-new + allocation + type-to-make + (+ (+ s2-1 1) (the-as int (-> type-to-make size))) + ) + ) + ) + (set! (-> a0-4 allocated-length) s2-1) + (copy-string<-string a0-4 arg1) + ) + (let + ((v0-2 + (object-new + allocation + type-to-make + (+ (+ arg0 1) (the-as int (-> type-to-make size))) + ) + ) + ) + (set! (-> v0-2 allocated-length) arg0) + v0-2 + ) + ) + ) + +;; definition for function string= +(defun string= ((str-a string) (str-b string)) + (let ((a-ptr (-> str-a data)) + (b-ptr (-> str-b data)) + ) + (if (or (zero? str-a) (zero? str-b)) + (return #f) + ) + (while (and (nonzero? (-> a-ptr 0)) (nonzero? (-> b-ptr 0))) + (if (!= (-> a-ptr 0) (-> b-ptr 0)) + (return #f) + ) + (set! a-ptr (&-> a-ptr 1)) + (set! b-ptr (&-> b-ptr 1)) + ) + (and (zero? (-> a-ptr 0)) (zero? (-> b-ptr 0))) + ) + ) + +;; definition for function string-charp= +(defun string-charp= ((str string) (charp (pointer uint8))) + (let ((str-ptr (-> str data))) + (while (and (nonzero? (-> str-ptr 0)) (nonzero? (-> charp 0))) + (if (!= (-> str-ptr 0) (-> charp 0)) + (return #f) + ) + (set! str-ptr (&-> str-ptr 1)) + (set! charp (&-> charp 1)) + ) + (and (zero? (-> str-ptr 0)) (zero? (-> charp 0))) + ) + ) + +;; definition for function name= +(defun name= ((arg0 basic) (arg1 basic)) + (cond + ((= arg0 arg1) + #t + ) + ((and (= (-> arg0 type) string) (= (-> arg1 type) string)) + (string= (the-as string arg0) (the-as string arg1)) + ) + ((and (= (-> arg0 type) string) (= (-> arg1 type) symbol)) + (string= + (the-as string arg0) + (the-as string (-> (the-as (pointer uint32) (+ #xff38 (the-as int arg1))))) + ) + ) + ((and (= (-> arg1 type) string) (= (-> arg0 type) symbol)) + (string= + (the-as string arg1) + (the-as string (-> (the-as (pointer uint32) (+ #xff38 (the-as int arg0))))) + ) + ) + ) + ) + +;; definition for function copyn-string<-charp +(defun copyn-string<-charp ((str string) (charp (pointer uint8)) (len int)) + (let ((str-ptr (-> str data))) + (dotimes (i len) + (set! (-> str-ptr 0) (-> charp 0)) + (set! str-ptr (&-> str-ptr 1)) + (set! charp (&-> charp 1)) + ) + (set! (-> str-ptr 0) (the-as uint 0)) + ) + str + ) + +;; definition for function string<-charp +(defun string<-charp ((str string) (charp (pointer uint8))) + (let ((str-ptr (-> str data))) + (while (nonzero? (-> charp 0)) + (set! (-> str-ptr 0) (-> charp 0)) + (set! str-ptr (&-> str-ptr 1)) + (set! charp (&-> charp 1)) + ) + (set! (-> str-ptr 0) (the-as uint 0)) + ) + str + ) + +;; definition for function charp<-string +(defun charp<-string ((charp (pointer uint8)) (str string)) + (let ((str-ptr (-> str data))) + (while (nonzero? (-> str-ptr 0)) + (set! (-> charp 0) (-> str-ptr 0)) + (set! charp (&-> charp 1)) + (set! str-ptr (&-> str-ptr 1)) + ) + ) + (set! (-> charp 0) (the-as uint 0)) + 0 + ) + +;; definition for function copy-charp<-charp +(defun copy-charp<-charp ((dst (pointer uint8)) (src (pointer uint8))) + (while (nonzero? (-> src 0)) + (set! (-> dst 0) (-> src 0)) + (set! dst (&-> dst 1)) + (set! src (&-> src 1)) + ) + (set! (-> dst 0) (the-as uint 0)) + dst + ) + +;; definition for function cat-string<-string +(defun cat-string<-string ((a string) (b string)) + (let ((a-ptr (-> a data))) + (let ((b-ptr (-> b data))) + (while (nonzero? (-> a-ptr 0)) + (nop!) + (nop!) + (nop!) + (set! a-ptr (&-> a-ptr 1)) + ) + (while (nonzero? (-> b-ptr 0)) + (set! (-> a-ptr 0) (-> b-ptr 0)) + (set! a-ptr (&-> a-ptr 1)) + (set! b-ptr (&-> b-ptr 1)) + ) + ) + (set! (-> a-ptr 0) (the-as uint 0)) + ) + a + ) + +;; definition for function catn-string<-charp +(defun catn-string<-charp ((a string) (b (pointer uint8)) (len int)) + (let ((a-ptr (-> a data))) + (while (nonzero? (-> a-ptr 0)) + (nop!) + (nop!) + (nop!) + (set! a-ptr (&-> a-ptr 1)) + ) + (dotimes (i len) + (set! (-> a-ptr 0) (-> b 0)) + (set! a-ptr (&-> a-ptr 1)) + (set! b (&-> b 1)) + ) + (set! (-> a-ptr 0) (the-as uint 0)) + ) + a + ) + +;; definition for function cat-string<-string_to_charp +(defun + cat-string<-string_to_charp + ((a string) (b string) (end-ptr (pointer uint8))) + (let ((b-ptr (-> b data)) + (a-ptr (-> a data)) + ) + (while (nonzero? (-> a-ptr 0)) + (nop!) + (nop!) + (nop!) + (set! a-ptr (&-> a-ptr 1)) + ) + (while + (and (>= (the-as int end-ptr) (the-as int b-ptr)) (nonzero? (-> b-ptr 0))) + (set! (-> a-ptr 0) (-> b-ptr 0)) + (set! a-ptr (&-> a-ptr 1)) + (set! b-ptr (&-> b-ptr 1)) + ) + (set! (-> a-ptr 0) (the-as uint 0)) + a-ptr + ) + ) + +;; definition for function append-character-to-string +(defun append-character-to-string ((str string) (char uint8)) + (let ((str-ptr (-> str data))) + (while (nonzero? (-> str-ptr 0)) + (nop!) + (nop!) + (nop!) + (set! str-ptr (&-> str-ptr 1)) + ) + (set! (-> str-ptr 0) (the-as uint char)) + (set! (-> str-ptr 1) (the-as uint 0)) + ) + (let ((v1-1 0)) + ) + 0 + ) + +;; definition for function charp-basename +(defun charp-basename ((charp (pointer uint8))) + (let ((ptr charp)) + (while (nonzero? (-> ptr 0)) + (set! ptr (&-> ptr 1)) + ) + (while (< (the-as int charp) (the-as int ptr)) + (set! ptr (&-> ptr -1)) + (if (or (= (-> ptr 0) 47) (= (-> ptr 0) 92)) + (return (&-> ptr 1)) + ) + ) + ) + charp + ) + +;; definition for function clear +(defun clear ((arg0 string)) + (set! (-> arg0 data 0) (the-as uint 0)) + arg0 + ) + +;; definition for function string a data i) (-> b data i)) + (return #t) + ) + ((< (-> b data i) (-> a data i)) + (return #f) + ) + ) + ) + ) + #f + ) + +;; definition for function string>? +(defun string>? ((a string) (b string)) + (let + ((len + (min ((method-of-type string length) a) ((method-of-type string length) b)) + ) + ) + (dotimes (i len) + (cond + ((< (-> a data i) (-> b data i)) + (return #f) + ) + ((< (-> b data i) (-> a data i)) + (return #t) + ) + ) + ) + ) + #f + ) + +;; definition for function string<=? +(defun string<=? ((a string) (b string)) + (let + ((len + (min ((method-of-type string length) a) ((method-of-type string length) b)) + ) + ) + (dotimes (i len) + (cond + ((< (-> a data i) (-> b data i)) + (return #t) + ) + ((< (-> b data i) (-> a data i)) + (return #f) + ) + ) + ) + ) + #t + ) + +;; definition for function string>=? +(defun string>=? ((a string) (b string)) + (let + ((len + (min ((method-of-type string length) a) ((method-of-type string length) b)) + ) + ) + (dotimes (i len) + (cond + ((< (-> a data i) (-> b data i)) + (return #f) + ) + ((< (-> b data i) (-> a data i)) + (return #t) + ) + ) + ) + ) + #t + ) + +;; definition for symbol *string-tmp-str*, type string +(define *string-tmp-str* (new 'global 'string 128 (the-as string #f))) + +;; definition for function string-skip-to-char +(defun string-skip-to-char ((arg0 (pointer uint8)) (arg1 uint)) + (while (and (nonzero? (-> arg0 0)) (!= (-> arg0 0) arg1)) + (set! arg0 (&-> arg0 1)) + ) + arg0 + ) + +;; definition for function string-cat-to-last-char +(defun + string-cat-to-last-char + ((base-str string) (append-str string) (char uint)) + (let ((end-of-append (&-> (the-as (pointer uint8) append-str) 3))) + (let ((location-of-char (string-skip-to-char (-> append-str data) char))) + (when (= (-> location-of-char 0) char) + (until (begin + (set! end-of-append location-of-char) + (set! + location-of-char + (string-skip-to-char (&-> location-of-char 1) char) + ) + (!= (-> location-of-char 0) char) + ) + (empty) + ) + ) + ) + (cat-string<-string_to_charp base-str append-str end-of-append) + ) + ) + +;; definition for function string-skip-whitespace +(defun string-skip-whitespace ((arg0 (pointer uint8))) + (while + (and + (nonzero? (-> arg0 0)) + (or + (= (-> arg0 0) 32) + (= (-> arg0 0) 9) + (= (-> arg0 0) 13) + (= (-> arg0 0) 10) + ) + ) + (set! arg0 (&-> arg0 1)) + ) + arg0 + ) + +;; definition for function string-suck-up! +(defun string-suck-up! ((str string) (location (pointer uint8))) + (when (!= location (-> str data)) + (let ((str-ptr (-> str data))) + (while (nonzero? (-> location 0)) + (set! (-> str-ptr 0) (-> location 0)) + (set! str-ptr (&-> str-ptr 1)) + (set! location (&-> location 1)) + ) + (set! (-> str-ptr 0) (the-as uint 0)) + ) + (let ((v1-3 0)) + ) + ) + #f + ) + +;; definition for function string-strip-leading-whitespace! +(defun string-strip-leading-whitespace! ((arg0 string)) + (let ((a1-0 (string-skip-whitespace (-> arg0 data)))) + (string-suck-up! arg0 a1-0) + ) + #f + ) + +;; definition for function string-strip-trailing-whitespace! +(defun string-strip-trailing-whitespace! ((str string)) + (when (nonzero? ((method-of-type string length) str)) + (let ((ptr (&+ (-> str data) (+ ((method-of-type string length) str) -1)))) + (while + (and + (>= (the-as int ptr) (the-as int (-> str data))) + (or + (= (-> ptr 0) 32) + (= (-> ptr 0) 9) + (= (-> ptr 0) 13) + (= (-> ptr 0) 10) + ) + ) + (set! ptr (&-> ptr -1)) + ) + (set! (-> ptr 1) (the-as uint 0)) + ) + (let ((v1-7 0)) + ) + ) + #f + ) + +;; definition for function string-strip-whitespace! +(defun string-strip-whitespace! ((arg0 string)) + (string-strip-trailing-whitespace! arg0) + (string-strip-leading-whitespace! arg0) + #f + ) + +;; definition for function string-get-arg!! +(defun string-get-arg!! ((a-str string) (arg string)) + (let ((arg-word-start (string-skip-whitespace (-> arg data)))) + (cond + ((= (-> arg-word-start 0) 34) + (return (begin + (let ((arg-end (&-> arg-word-start 1))) + (let ((arg-start arg-end)) + (while + (and + (nonzero? (-> arg-end 0)) + (nonzero? (+ (-> arg-end 0) -34)) + ) + (set! arg-end (&-> arg-end 1)) + ) + (copyn-string<-charp + a-str + arg-start + (&- arg-end (the-as uint arg-start)) + ) + ) + (when (= (-> arg-end 0) 34) + (set! arg-end (&-> arg-end 1)) + (let ((v1-6 arg-end)) + ) + ) + (let ((a1-3 (string-skip-whitespace arg-end))) + (string-suck-up! arg a1-3) + ) + ) + #t + ) + ) + ) + ((nonzero? (-> arg-word-start 0)) + (return (begin + (let ((v1-11 arg-word-start)) + (while + (and + (nonzero? (-> arg-word-start 0)) + (nonzero? (+ (-> arg-word-start 0) -32)) + (nonzero? (+ (-> arg-word-start 0) -9)) + (nonzero? (+ (-> arg-word-start 0) -13)) + (nonzero? (+ (-> arg-word-start 0) -10)) + ) + (set! arg-word-start (&-> arg-word-start 1)) + ) + (copyn-string<-charp + a-str + v1-11 + (&- arg-word-start (the-as uint v1-11)) + ) + ) + (let ((a1-9 (string-skip-whitespace arg-word-start))) + (string-suck-up! arg a1-9) + ) + #t + ) + ) + ) + ) + ) + #f + ) + +;; definition for function string->int +(defun string->int ((str string)) + (let ((str-ptr (-> str data)) + (result 0) + (v1-0 #f) + ) + (cond + ((= (-> str-ptr 0) 35) + (let ((next-char-1 (&-> str-ptr 1))) + (cond + ((or (= (-> next-char-1 0) 120) (= (-> next-char-1 0) 88)) + (let ((next-char-2 (&-> next-char-1 1))) + (when (= (-> next-char-2 1) 45) + (set! v1-0 #t) + (set! next-char-2 (&-> next-char-2 1)) + (let ((a1-8 next-char-2)) + ) + ) + (while + (or + (and + (>= (-> next-char-2 0) (the-as uint 48)) + (>= (the-as uint 57) (-> next-char-2 0)) + ) + (and + (>= (-> next-char-2 0) (the-as uint 65)) + (>= (the-as uint 70) (-> next-char-2 0)) + ) + (and + (>= (-> next-char-2 0) (the-as uint 97)) + (>= (the-as uint 102) (-> next-char-2 0)) + ) + ) + (cond + ((and + (>= (-> next-char-2 0) (the-as uint 65)) + (>= (the-as uint 70) (-> next-char-2 0)) + ) + (set! + result + (the-as + int + (+ (+ (-> next-char-2 0) -55) (the-as uint (shl result 4))) + ) + ) + (let ((a1-14 (the-as uint result))) + ) + ) + (else + (cond + ((and + (>= (-> next-char-2 0) (the-as uint 97)) + (>= (the-as uint 102) (-> next-char-2 0)) + ) + (set! + result + (the-as + int + (+ (+ (-> next-char-2 0) -87) (the-as uint (shl result 4))) + ) + ) + (let ((a1-20 (the-as uint result))) + ) + ) + (else + (set! + result + (the-as + int + (+ (+ (-> next-char-2 0) -48) (the-as uint (shl result 4))) + ) + ) + (let ((a1-23 (the-as uint result))) + ) + ) + ) + ) + ) + (set! next-char-2 (&-> next-char-2 1)) + ) + ) + ) + ((or (= (-> next-char-1 0) 98) (= (-> next-char-1 0) 66)) + (let ((a0-4 (&-> next-char-1 1))) + (while + (and + (>= (-> a0-4 0) (the-as uint 48)) + (>= (the-as uint 49) (-> a0-4 0)) + ) + (set! + result + (the-as int (+ (+ (-> a0-4 0) -48) (the-as uint (shl result 1)))) + ) + (set! a0-4 (&-> a0-4 1)) + ) + ) + ) + ) + ) + ) + (else + (when (= (-> str-ptr 1) 45) + (set! v1-0 #t) + (set! str-ptr (&-> str-ptr 1)) + (let ((a1-47 str-ptr)) + ) + ) + (while + (and + (>= (-> str-ptr 0) (the-as uint 48)) + (>= (the-as uint 57) (-> str-ptr 0)) + ) + (set! + result + (the-as int (+ (+ (-> str-ptr 0) -48) (the-as uint (* 10 result)))) + ) + (set! str-ptr (&-> str-ptr 1)) + ) + ) + ) + (cond + (v1-0 + (- result) + ) + (else + (empty) + result + ) + ) + ) + ) + +;; definition for function string->float +(defun string->float ((arg0 string)) + (format 0 "string->float left as an excersize for the reader~%") + 0.0 + ) + +;; definition for function string-get-int32!! +(defun string-get-int32!! ((arg0 (pointer int32)) (arg1 string)) + (cond + ((string-get-arg!! *string-tmp-str* arg1) + (set! (-> arg0 0) (string->int *string-tmp-str*)) + #t + ) + (else + #f + ) + ) + ) + +;; definition for function string-get-float!! +(defun string-get-float!! ((arg0 (pointer float)) (arg1 string)) + (cond + ((string-get-arg!! *string-tmp-str* arg1) + (set! (-> arg0 0) (string->float *string-tmp-str*)) + #t + ) + (else + #f + ) + ) + ) + +;; definition for function string-get-flag!! +(defun + string-get-flag!! + ((result (pointer symbol)) + (in string) + (first-flag string) + (second-flag string) + ) + (if (string-get-arg!! *string-tmp-str* in) + (cond + ((or + (string= *string-tmp-str* first-flag) + (string= *string-tmp-str* second-flag) + ) + (set! (-> result 0) (string= *string-tmp-str* first-flag)) + #t + ) + (else + #f + ) + ) + #f + ) + ) + +;; definition for symbol *debug-draw-pauseable*, type symbol +(define *debug-draw-pauseable* #f) + +;; definition for symbol *stdcon0*, type string +(define *stdcon0* (new 'global 'string #x4000 (the-as string #f))) + +;; definition for symbol *stdcon1*, type string +(define *stdcon1* (new 'global 'string #x4000 (the-as string #f))) + +;; definition for symbol *stdcon*, type string +(define *stdcon* *stdcon0*) + +;; definition for symbol *temp-string*, type string +(define *temp-string* (new 'global 'string 256 (the-as string #f))) + +;; failed to figure out what this is: +(none) diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index 78a0da4fb5..47c54d7167 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -2625,4 +2625,114 @@ TEST_F(FormRegressionTest, QMemCpy) { " v0-0\n" " )"; test_with_expr(func, type, expected); +} + +TEST_F(FormRegressionTest, StripStripTrailingWhitespace) { + std::string func = + "sll r0, r0, 0\n" + "L52:\n" + " daddiu sp, sp, -48\n" + " sd ra, 0(sp)\n" + " sq s5, 16(sp)\n" + " sq gp, 32(sp)\n" + + " or gp, a0, r0\n" + " or a0, gp, r0\n" + " lw v1, string(s7)\n" + " lwu t9, 32(v1)\n" + " jalr ra, t9\n" + " sll v0, ra, 0\n" + + " or v1, v0, r0\n" + " beq v1, r0, L56\n" + " or v1, s7, r0\n" + + " daddiu s5, gp, 4\n" + " or a0, gp, r0\n" + " lw v1, string(s7)\n" + " lwu t9, 32(v1)\n" + " jalr ra, t9\n" + " sll v0, ra, 0\n" + + " or v1, v0, r0\n" + " daddiu v1, v1, -1\n" + " daddu v1, s5, v1\n" + " beq r0, r0, L54\n" + " sll r0, r0, 0\n" + "L53:\n" + " daddiu v1, v1, -1\n" + "L54:\n" + " daddiu a0, gp, 4\n" + " slt a0, v1, a0\n" + " daddiu a1, s7, 8\n" + " movn a1, s7, a0\n" + " beql s7, a1, L55\n" + " or a0, a1, r0\n" + + " lbu a0, 0(v1)\n" + " daddiu a0, a0, -32\n" + " daddiu a1, s7, 8\n" + " movn a1, s7, a0\n" + " bnel s7, a1, L55\n" + " or a0, a1, r0\n" + + " lbu a0, 0(v1)\n" + " daddiu a0, a0, -9\n" + " daddiu a1, s7, 8\n" + " movn a1, s7, a0\n" + " bnel s7, a1, L55\n" + " or a0, a1, r0\n" + + " lbu a0, 0(v1)\n" + " daddiu a0, a0, -13\n" + " daddiu a1, s7, 8\n" + " movn a1, s7, a0\n" + " bnel s7, a1, L55\n" + " or a0, a1, r0\n" + + " lbu a0, 0(v1)\n" + " daddiu a1, a0, -10\n" + " daddiu a0, s7, 8\n" + " movn a0, s7, a1\n" + "L55:\n" + " bne s7, a0, L53\n" + " sll r0, r0, 0\n" + + " or a0, s7, r0\n" + " sb r0, 1(v1)\n" + " or v1, r0, r0\n" + "L56:\n" + " or v0, s7, r0\n" + " ld ra, 0(sp)\n" + " lq gp, 32(sp)\n" + " lq s5, 16(sp)\n" + " jr ra\n" + " daddiu sp, sp, 48\n"; + + std::string type = "(function string symbol)"; + std::string expected = + "(begin\n" + " (when (nonzero? ((method-of-type string length) arg0))\n" + " (let\n" + " ((v1-6 (&+ (-> arg0 data) (+ ((method-of-type string length) arg0) -1))))\n" + " (while\n" + " (and\n" + " (>= (the-as int v1-6) (the-as int (-> arg0 data)))\n" + " (or\n" + " (= (-> v1-6 0) 32)\n" + " (= (-> v1-6 0) 9)\n" + " (= (-> v1-6 0) 13)\n" + " (= (-> v1-6 0) 10)\n" + " )\n" + " )\n" + " (set! v1-6 (&-> v1-6 -1))\n" + " )\n" + " (set! (-> v1-6 1) (the-as uint 0))\n" + " )\n" + " (let ((v1-7 0))\n" + " )\n" + " )\n" + " #f\n" + " )"; + test_with_expr(func, type, expected); } \ No newline at end of file diff --git a/test/decompiler/test_FormExpressionBuildLong.cpp b/test/decompiler/test_FormExpressionBuildLong.cpp index 50b6b08844..8cd8215747 100644 --- a/test/decompiler/test_FormExpressionBuildLong.cpp +++ b/test/decompiler/test_FormExpressionBuildLong.cpp @@ -2350,21 +2350,21 @@ TEST_F(FormRegressionTest, ExprStringToInt) { std::string type = "(function string int)"; std::string expected = "(defun test-function ((arg0 string))\n" - " (let\n" - " ((a0-1 (-> arg0 data)) (v0-0 0) (v1-0 #f))\n" + " (let ((a0-1 (-> arg0 data))\n" + " (v0-0 0)\n" + " (v1-0 #f)\n" + " )\n" " (cond\n" " ((= (-> a0-1 0) 35)\n" - " (let\n" - " ((a0-2 (&-> a0-1 1)))\n" + " (let ((a0-2 (&-> a0-1 1)))\n" " (cond\n" " ((or (= (-> a0-2 0) 120) (= (-> a0-2 0) 88))\n" - " (let\n" - " ((a0-3 (&-> a0-2 1)))\n" - " (when\n" - " (= (-> a0-3 1) 45)\n" + " (let ((a0-3 (&-> a0-2 1)))\n" + " (when (= (-> a0-3 1) 45)\n" " (set! v1-0 #t)\n" " (set! a0-3 (&-> a0-3 1))\n" - " (let ((a1-8 a0-3)))\n" + " (let ((a1-8 a0-3))\n" + " )\n" " )\n" " (while\n" " (or\n" @@ -2386,8 +2386,12 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " (>= (-> a0-3 0) (the-as uint 65))\n" " (>= (the-as uint 70) (-> a0-3 0))\n" " )\n" - " (set! v0-0 (+ (+ (-> a0-3 0) -55) (the-as uint (shl v0-0 4))))\n" - " (let ((a1-14 (the-as uint v0-0))))\n" + " (set!\n" + " v0-0\n" + " (the-as int (+ (+ (-> a0-3 0) -55) (the-as uint (shl v0-0 4))))\n" + " )\n" + " (let ((a1-14 (the-as uint v0-0)))\n" + " )\n" " )\n" " (else\n" " (cond\n" @@ -2395,12 +2399,20 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " (>= (-> a0-3 0) (the-as uint 97))\n" " (>= (the-as uint 102) (-> a0-3 0))\n" " )\n" - " (set! v0-0 (+ (+ (-> a0-3 0) -87) (the-as uint (shl v0-0 4))))\n" - " (let ((a1-20 (the-as uint v0-0))))\n" + " (set!\n" + " v0-0\n" + " (the-as int (+ (+ (-> a0-3 0) -87) (the-as uint (shl v0-0 4))))\n" + " )\n" + " (let ((a1-20 (the-as uint v0-0)))\n" + " )\n" " )\n" " (else\n" - " (set! v0-0 (+ (+ (-> a0-3 0) -48) (the-as uint (shl v0-0 4))))\n" - " (let ((a1-23 (the-as uint v0-0))))\n" + " (set!\n" + " v0-0\n" + " (the-as int (+ (+ (-> a0-3 0) -48) (the-as uint (shl v0-0 4))))\n" + " )\n" + " (let ((a1-23 (the-as uint v0-0)))\n" + " )\n" " )\n" " )\n" " )\n" @@ -2410,14 +2422,16 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " )\n" " )\n" " ((or (= (-> a0-2 0) 98) (= (-> a0-2 0) 66))\n" - " (let\n" - " ((a0-4 (&-> a0-2 1)))\n" + " (let ((a0-4 (&-> a0-2 1)))\n" " (while\n" " (and\n" " (>= (-> a0-4 0) (the-as uint 48))\n" " (>= (the-as uint 49) (-> a0-4 0))\n" " )\n" - " (set! v0-0 (+ (+ (-> a0-4 0) -48) (the-as uint (shl v0-0 1))))\n" + " (set!\n" + " v0-0\n" + " (the-as int (+ (+ (-> a0-4 0) -48) (the-as uint (shl v0-0 1))))\n" + " )\n" " (set! a0-4 (&-> a0-4 1))\n" " )\n" " )\n" @@ -2426,20 +2440,28 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " )\n" " )\n" " (else\n" - " (when\n" - " (= (-> a0-1 1) 45)\n" + " (when (= (-> a0-1 1) 45)\n" " (set! v1-0 #t)\n" " (set! a0-1 (&-> a0-1 1))\n" - " (let ((a1-47 a0-1)))\n" + " (let ((a1-47 a0-1))\n" + " )\n" " )\n" " (while\n" " (and (>= (-> a0-1 0) (the-as uint 48)) (>= (the-as uint 57) (-> a0-1 0)))\n" - " (set! v0-0 (+ (+ (-> a0-1 0) -48) (the-as uint (* 10 v0-0))))\n" + " (set! v0-0 (the-as int (+ (+ (-> a0-1 0) -48) (the-as uint (* 10 v0-0)))))\n" " (set! a0-1 (&-> a0-1 1))\n" " )\n" " )\n" " )\n" - " (cond (v1-0 (- v0-0)) (else (empty) v0-0))\n" + " (cond\n" + " (v1-0\n" + " (- v0-0)\n" + " )\n" + " (else\n" + " (empty)\n" + " v0-0\n" + " )\n" + " )\n" " )\n" " )"; test_final_function(func, type, expected); diff --git a/test/offline/offline_test_main.cpp b/test/offline/offline_test_main.cpp index 794460e395..71c80dd837 100644 --- a/test/offline/offline_test_main.cpp +++ b/test/offline/offline_test_main.cpp @@ -9,13 +9,13 @@ namespace { // the object files to test -const std::unordered_set g_object_files_to_decompile = {"gcommon", "gstring-h", - "gkernel-h", "gkernel"}; +const std::unordered_set g_object_files_to_decompile = { + "gcommon", "gstring-h", "gkernel-h", "gkernel", "gstring"}; // the object files to check against a reference in test/decompiler/reference const std::vector g_object_files_to_check_against_reference = { "gcommon", // NOTE: this file needs work, but adding it for now just to test the framework. - "gstring-h", "gkernel-h", "gkernel"}; + "gstring-h", "gkernel-h", "gkernel", "gstring"}; // the functions we expect the decompiler to skip const std::unordered_set expected_skip_in_decompiler = {