jak-project/decompiler/IR2/GenericElementMatcher.h
ManDude 24578b64b9
proper support for hardcoded "time" types (#1141)
* hardcode `time-frame`things

* Update cam-states_REF.gc

* Update level-info_REF.gc

* update refs 1

* update refs 2

* update refs 3

* update refs 4

* update refs 5

* update detection and casting

* Update FormExpressionAnalysis.cpp

* update refs 6

* update mood decomp

* update refs 7

* update refs 8

* remove temp entity birth code

* update time-frame casts

* fix compiler

* hardcode stuff and fix some types

* fix some bitfield detection being wrong

* bug fixes

* detect seconds on adds with immediate

* update refs 9

* fix casts and rand-vu-int-range bugs (update refs 10)

* update refs 11

* update 12

* update 13

* update 14

* Update game-info_REF.gc

* improve cpad macros detection

* remove unused code

* update refs

* clang

* update source code

* Update cam-states.gc

* `lavatube-energy` finish

* update refs

* fix actor bank stuff

* Update navigate.gc

* reduce entity default stack size

* Update transformq-h.gc

* oops forgot these

* fix code and tests

* fix mood sound stuff

* Update load-dgo.gc

* Update README.md
2022-02-12 12:26:19 -05:00

150 lines
4.6 KiB
C++

/*!
* @file GenericElementMatcher.h
*
* The Matcher is supposed to match up forms to templates, and extract the variables actually used.
*/
#pragma once
#include "Form.h"
namespace decompiler {
class DerefTokenMatcher;
class GenericOpMatcher;
struct MatchResult {
bool matched = false;
struct Maps {
std::vector<std::optional<RegisterAccess>> regs;
std::unordered_map<int, std::string> strings;
std::unordered_map<int, Form*> forms;
std::unordered_map<int, s64> label;
std::unordered_map<int, s64> ints;
} maps;
};
class Matcher {
public:
static Matcher any_reg(int match_id = -1);
static Matcher any_label(int match_id = -1);
static Matcher op(const GenericOpMatcher& op, const std::vector<Matcher>& args);
static Matcher op_fixed(FixedOperatorKind op, const std::vector<Matcher>& args);
static Matcher op_with_rest(const GenericOpMatcher& op, const std::vector<Matcher>& args);
static Matcher set(const Matcher& dst, const Matcher& src); // form-form
static Matcher set_var(const Matcher& src, int dst_match_id); // var-form
static Matcher fixed_op(FixedOperatorKind op, const std::vector<Matcher>& args);
static Matcher match_or(const std::vector<Matcher>& args);
static Matcher cast(const std::string& type, Matcher value);
static Matcher any(int match_id = -1);
static Matcher integer(std::optional<int> value);
static Matcher any_integer(int match_id = -1);
static Matcher any_reg_cast_to_int_or_uint(int match_id = -1);
static Matcher any_quoted_symbol(int match_id = -1);
static Matcher any_symbol(int match_id = -1);
static Matcher symbol(const std::string& name);
static Matcher deref(const Matcher& root,
bool is_addr_of,
const std::vector<DerefTokenMatcher>& tokens);
static Matcher if_with_else(const Matcher& condition,
const Matcher& true_case,
const Matcher& false_case);
static Matcher if_no_else(const Matcher& condition, const Matcher& true_case);
static Matcher while_loop(const Matcher& condition, const Matcher& body);
static Matcher any_constant_token(int match_id = -1);
static Matcher constant_token(const std::string& name);
static Matcher or_expression(const std::vector<Matcher>& elts);
static Matcher begin(const std::vector<Matcher>& elts);
enum class Kind {
ANY_REG, // matching any register
GENERIC_OP, // matching
GENERIC_OP_WITH_REST,
OR,
CAST,
ANY,
INT,
ANY_INT,
ANY_QUOTED_SYMBOL,
ANY_SYMBOL,
DEREF_OP,
SET,
SET_VAR,
ANY_LABEL,
SYMBOL,
IF_WITH_ELSE,
IF_NO_ELSE,
WHILE_LOOP,
ANY_CONSTANT_TOKEN,
CONSTANT_TOKEN,
SC_OR,
BEGIN,
INVALID
};
bool do_match(Form* input, MatchResult::Maps* maps_out) const;
private:
std::vector<Matcher> m_sub_matchers;
std::vector<DerefTokenMatcher> m_token_matchers;
std::shared_ptr<GenericOpMatcher> m_gen_op_matcher;
bool m_deref_is_addr_of = false;
Kind m_kind = Kind::INVALID;
int m_reg_out_id = -1;
int m_string_out_id = -1;
int m_form_match = -1;
int m_label_out_id = -1;
int m_int_out_id = -1;
std::optional<int> m_int_match;
std::string m_str;
};
MatchResult match(const Matcher& spec, Form* input);
class DerefTokenMatcher {
public:
static DerefTokenMatcher string(const std::string& str);
static DerefTokenMatcher integer(int value);
static DerefTokenMatcher any_string(int match_id = -1);
static DerefTokenMatcher any_integer(int match_id = -1);
static DerefTokenMatcher any_expr(int match_id = -1);
static DerefTokenMatcher any_expr_or_int(int match_id = -1);
enum class Kind {
STRING,
ANY_STRING,
CONSTANT_INTEGER,
ANY_INTEGER,
ANY_EXPR,
ANY_EXPR_OR_INT,
INVALID
};
bool do_match(DerefToken& input, MatchResult::Maps* maps_out) const;
private:
Kind m_kind = Kind::INVALID;
std::string m_str;
int m_int = -1;
int m_str_out_id = -1;
};
class GenericOpMatcher {
public:
static GenericOpMatcher fixed(FixedOperatorKind kind);
static GenericOpMatcher func(const Matcher& func_matcher);
static GenericOpMatcher condition(IR2_Condition::Kind condition);
static GenericOpMatcher or_match(const std::vector<GenericOpMatcher>& matchers);
enum class Kind { FIXED, FUNC, CONDITION, OR, INVALID };
bool do_match(GenericOperator& input, MatchResult::Maps* maps_out) const;
private:
Kind m_kind = Kind::INVALID;
FixedOperatorKind m_fixed_kind = FixedOperatorKind::INVALID;
IR2_Condition::Kind m_condition_kind = IR2_Condition::Kind::INVALID;
std::vector<GenericOpMatcher> m_sub_matchers;
Matcher m_func_matcher;
};
} // namespace decompiler