[decompiler] Workaround for GOAL fpr -> gpr spill bug and fix >16-bit signed FP loads (#587)

* fix up broken stuff for collectables

* exception for stack spill float in gpr bug
This commit is contained in:
water111 2021-06-13 13:55:55 -04:00 committed by GitHub
parent 43b89dd982
commit 13b5695b63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 230 additions and 138 deletions

View file

@ -131,9 +131,9 @@ TP_Type SimpleAtom::get_type(const TypeState& input,
if (hint_kv != env.label_types().end()) {
return TP_Type::make_from_ts(dts.parse_type_spec(hint_kv->second.type_name));
}
// throw std::runtime_error("IR_StaticAddress could not figure out the type: " + label.name);
lg::error("IR_StaticAddress does not know the type of {}", label.name);
return TP_Type::make_from_ts("object");
// todo: should we take out this warning?
lg::warn("IR_StaticAddress does not know the type of {}", label.name);
return TP_Type::make_label_addr();
}
case Kind::INVALID:
default:

View file

@ -13,6 +13,16 @@ void StackSpillMap::add_access(const StackSpillSlot& access) {
auto existing = m_slot_map.find(access.offset);
if (existing != m_slot_map.end()) {
if (access != existing->second) {
// the GOAL float -> GPR loads are just totally wrong.
if (existing->second.size == 16 && access.size == 4) {
existing->second.size = 4;
return;
}
if (existing->second.size == 4 && access.size == 16) {
return;
}
throw std::runtime_error(fmt::format("Inconsistent stack access:\n{}\n{}\n",
existing->second.print(), access.print()));
}

View file

@ -18223,14 +18223,6 @@
;; - Types
; (deftype fuel-cell (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; unrecognized get op: (set! v1 eco-collectable) parent was UNKNOWN
; )
;; - Symbols
@ -19426,17 +19418,6 @@
;; Containing DGOs - ['GAME', 'ENGINE']
;; Version - 3
;; - Types
; (deftype money (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
;; - Symbols
(define-extern task-control-reset function)
@ -19700,125 +19681,208 @@
;; - Types
; (deftype ecovalve (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; unrecognized get op: (set! v1 process-drawable) parent was UNKNOWN
; )
(deftype collectable (process-drawable)
((pickup-type int32 :offset-assert 176)
(pickup-amount float :offset-assert 180)
(notify-parent basic :offset-assert 184)
(old-base vector :inline :offset-assert 192)
(base vector :inline :offset-assert 208)
(extra-trans vector :inline :offset-assert 224)
(jump-pos vector :inline :offset-assert 240)
(flags uint32 :offset-assert 256)
(birth-time uint64 :offset-assert 264)
(collect-timeout uint64 :offset-assert 272)
(fadeout-timeout uint64 :offset-assert 280)
(bob-offset uint64 :offset-assert 288)
(bob-amount float :offset-assert 296)
(pickup-handle handle :offset-assert 304) ;; not sure it's a handle
(actor-pause basic :offset-assert 312)
)
(:methods
(dummy-20 () none 20)
(dummy-21 () none 21)
)
:heap-base #xd0
:method-count-assert 22
:size-assert #x13c
:flag-assert #x1600d0013c
; (deftype eco-blue (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
)
; (deftype eco-red (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
;; L729
(deftype eco-collectable (collectable)
((eco-effect basic :offset-assert 316)
(collect-effect basic :offset-assert 320)
(collect-effect2 basic :offset-assert 324)
(collect-effect-time uint64 :offset-assert 328)
(respawn-delay uint64 :offset-assert 336)
(sound-name basic :offset-assert 344)
(target uint64 :offset-assert 352)
(suck-time uint64 :offset-assert 360)
(suck-y-offset float :offset-assert 368)
(speed vector :inline :offset-assert 384)
(movie-pos-index int32 :offset-assert 400)
)
(:methods
(dummy-22 () none 22)
(dummy-23 () none 23)
(dummy-24 () none 24)
(dummy-25 () none 25)
(dummy-26 () none 26)
(dummy-27 () none 27)
(dummy-28 () none 28)
(dummy-29 () none 29)
(dummy-30 () none 30)
)
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype eco-yellow (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
;; L729
(deftype eco (eco-collectable)
()
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype health (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
(deftype eco-yellow (eco)
()
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype buzzer (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; unrecognized get op: (set! v1 eco-collectable) parent was UNKNOWN
; )
(deftype eco-red (eco)
()
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype eco-pill (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
(deftype eco-blue (eco)
()
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype eco-collectable (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; unrecognized get op: (set! v1 collectable) parent was UNKNOWN
; )
(deftype health (eco-collectable)
()
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype vent (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; unrecognized get op: (set! v1 process-drawable) parent was UNKNOWN
; )
(deftype eco-pill (eco-collectable)
()
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype eco (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
(deftype money (eco-collectable)
()
:heap-base #x130
:method-count-assert 31
:size-assert #x194
:flag-assert #x1f01300194
)
; (deftype collectable (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; unrecognized get op: (set! v1 process-drawable) parent was UNKNOWN
; )
;; L730
(deftype fuel-cell (eco-collectable)
((victory-anim basic :offset-assert 404)
(state-object basic :offset-assert 408))
:heap-base #x130
:method-count-assert 31
:size-assert #x19c
:flag-assert #x1f0130019c
)
; (deftype ventyellow (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
;; L732
(deftype buzzer (eco-collectable)
((victory-anim basic :offset-assert 404))
:heap-base #x130
:method-count-assert 31
:size-assert #x198
:flag-assert #x1f01300198
)
; (deftype ventred (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
;; L728
(deftype ecovalve (process-drawable)
((offset vector :inline :offset-assert 176)
(offset-target vector :inline :offset-assert 192)
(block-func basic :offset-assert 208))
:heap-base #x70
:method-count-assert 20
:size-assert #xd4
:flag-assert #x14007000d4
)
; (deftype ventblue (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
;; L731
(deftype vent (process-drawable)
((show-particles basic :offset-assert 176)
(collect-effect basic :offset-assert 180)
(collect-effect2 basic :offset-assert 184)
(collect-effect-time uint64 :offset-assert 192)
(blocker basic :offset-assert 200)
(block-func basic :offset-assert 204)
(pickup-handle handle :offset-assert 208)) ;; not sure handle
(:methods
(dummy-20 () none 20)
)
:heap-base #x70
:method-count-assert 21
:size-assert #xd8
:flag-assert #x15007000d8
)
; (deftype ecovent (UNKNOWN)
; ()
; :method-count-assert 0
; :size-assert #x0
; :flag-assert #x0
; ;; not enough basic ops
; )
(deftype ventyellow (vent)
()
:heap-base #x70
:method-count-assert 21
:size-assert #xd8
:flag-assert #x15007000d8
)
(deftype ventred (vent)
()
:heap-base #x70
:method-count-assert 21
:size-assert #xd8
:flag-assert #x15007000d8
)
(deftype ventblue (vent)
()
:heap-base #x70
:method-count-assert 21
:size-assert #xd8
:flag-assert #x15007000d8
)
(deftype ecovent (vent)
()
:heap-base #x70
:method-count-assert 21
:size-assert #xd8
:flag-assert #x15007000d8
)
;; - Symbols
@ -19841,17 +19905,17 @@
;; - Unknowns
;;(define-extern vent-wait-for-touch object) ;; unknown type
;;(define-extern vent-pickup object) ;; unknown type
;;(define-extern vent-blocked object) ;; unknown type
;;(define-extern *ecovalve-sg* object) ;; unknown type
;;(define-extern ecovalve-idle object) ;; unknown type
;;(define-extern *eco-pill-count* object) ;; unknown type
;;(define-extern *buzzer-sg* object) ;; unknown type
;;(define-extern fuel-cell-clone-anim object) ;; unknown type
;;(define-extern *fuel-cell-tune-pos* object) ;; unknown type
;;(define-extern *fuel-cell-sg* object) ;; unknown type
;;(define-extern *money-sg* object) ;; unknown type
(define-extern vent-wait-for-touch state) ;; unknown type
(define-extern vent-pickup state) ;; unknown type
(define-extern vent-blocked state) ;; unknown type
(define-extern *ecovalve-sg* skeleton-group) ;; unknown type
(define-extern ecovalve-idle state) ;; unknown type
(define-extern *eco-pill-count* int) ;; unknown type
(define-extern *buzzer-sg* skeleton-group) ;; unknown type
(define-extern fuel-cell-clone-anim state) ;; unknown type
(define-extern *fuel-cell-tune-pos* vector) ;; unknown type
(define-extern *fuel-cell-sg* skeleton-group) ;; unknown type
(define-extern *money-sg* skeleton-group) ;; unknown type
;; ----------------------

View file

@ -296,6 +296,10 @@ TP_Type DecompilerTypeSystem::tp_lca(const TP_Type& existing,
return TP_Type::make_from_ts(
ts.lowest_common_ancestor(existing.typespec(), add.typespec()));
case TP_Type::Kind::LABEL_ADDR:
*changed = false;
return existing;
case TP_Type::Kind::FALSE_AS_NULL:
case TP_Type::Kind::UNINITIALIZED:
case TP_Type::Kind::DYNAMIC_METHOD_ACCESS:

View file

@ -67,6 +67,8 @@ std::string TP_Type::print() const {
}
case Kind::PCPYUD_BITFIELD:
return fmt::format("<pcpyud {}>", m_ts.print());
case Kind::LABEL_ADDR:
return "<label-addr>";
case Kind::INVALID:
default:
assert(false);
@ -117,6 +119,8 @@ bool TP_Type::operator==(const TP_Type& other) const {
return m_int == other.m_int && m_ts == other.m_ts && m_pcpyud == other.m_pcpyud;
case Kind::PCPYUD_BITFIELD:
return m_pcpyud == other.m_pcpyud && m_ts == other.m_ts;
case Kind::LABEL_ADDR:
return true;
case Kind::INVALID:
default:
assert(false);
@ -173,6 +177,8 @@ TypeSpec TP_Type::typespec() const {
return TypeSpec("int"); // ideally this is never used.
case Kind::PCPYUD_BITFIELD:
return TypeSpec("int");
case Kind::LABEL_ADDR:
return TypeSpec("pointer"); // ?
case Kind::INVALID:
default:
assert(false);

View file

@ -34,6 +34,7 @@ class TP_Type {
NON_VIRTUAL_METHOD,
PCPYUD_BITFIELD,
LEFT_SHIFTED_BITFIELD, // (bitfield << some-constant)
LABEL_ADDR,
INVALID
} kind = Kind::UNINITIALIZED;
TP_Type() = default;
@ -61,6 +62,7 @@ class TP_Type {
case Kind::NON_VIRTUAL_METHOD:
case Kind::LEFT_SHIFTED_BITFIELD:
case Kind::PCPYUD_BITFIELD:
case Kind::LABEL_ADDR:
return false;
case Kind::UNINITIALIZED:
case Kind::OBJECT_NEW_METHOD:
@ -238,6 +240,12 @@ class TP_Type {
return result;
}
static TP_Type make_label_addr() {
TP_Type result;
result.kind = Kind::LABEL_ADDR;
return result;
}
const TypeSpec& get_objects_typespec() const {
assert(kind == Kind::TYPESPEC || kind == Kind::INTEGER_CONSTANT_PLUS_VAR);
return m_ts;