2021-01-25 22:08:58 -05:00
|
|
|
#include "GenericElementMatcher.h"
|
|
|
|
|
|
|
|
namespace decompiler {
|
|
|
|
Matcher Matcher::any_reg(int match_id) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::ANY_REG;
|
|
|
|
m.m_reg_out_id = match_id;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
Matcher Matcher::any_label(int match_id) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::ANY_LABEL;
|
|
|
|
m.m_label_out_id = match_id;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2022-05-19 21:30:14 -04:00
|
|
|
Matcher Matcher::reg(Register reg) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::REG;
|
|
|
|
m.m_reg = reg;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
Matcher Matcher::op(const GenericOpMatcher& op, const std::vector<Matcher>& args) {
|
2021-01-25 22:08:58 -05:00
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::GENERIC_OP;
|
2021-01-27 13:47:54 -05:00
|
|
|
m.m_gen_op_matcher = std::make_shared<GenericOpMatcher>(op);
|
|
|
|
m.m_sub_matchers = args;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2022-06-09 21:18:08 -04:00
|
|
|
Matcher Matcher::func(const Matcher& matcher, const std::vector<Matcher>& args) {
|
|
|
|
return Matcher::op(GenericOpMatcher::func(matcher), args);
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::func(const std::string& name, const std::vector<Matcher>& args) {
|
|
|
|
return Matcher::op(GenericOpMatcher::func(Matcher::constant_token(name)), args);
|
|
|
|
}
|
|
|
|
|
2021-08-22 20:12:47 -04:00
|
|
|
Matcher Matcher::op_fixed(FixedOperatorKind op, const std::vector<Matcher>& args) {
|
|
|
|
return Matcher::op(GenericOpMatcher::fixed(op), args);
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
Matcher Matcher::op_with_rest(const GenericOpMatcher& op, const std::vector<Matcher>& args) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::GENERIC_OP_WITH_REST;
|
|
|
|
m.m_gen_op_matcher = std::make_shared<GenericOpMatcher>(op);
|
2021-01-25 22:08:58 -05:00
|
|
|
m.m_sub_matchers = args;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2022-06-09 21:18:08 -04:00
|
|
|
Matcher Matcher::func_with_rest(const Matcher& matcher, const std::vector<Matcher>& args) {
|
|
|
|
return Matcher::op_with_rest(GenericOpMatcher::func(matcher), args);
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::func_with_rest(const std::string& name, const std::vector<Matcher>& args) {
|
|
|
|
return Matcher::op_with_rest(GenericOpMatcher::func(Matcher::constant_token(name)), args);
|
2021-01-25 22:08:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::match_or(const std::vector<Matcher>& args) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::OR;
|
|
|
|
m.m_sub_matchers = args;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::cast(const std::string& type, Matcher value) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::CAST;
|
|
|
|
m.m_str = type;
|
|
|
|
m.m_sub_matchers = {value};
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2022-11-12 17:56:07 -05:00
|
|
|
Matcher Matcher::cast_to_any(int type_out, Matcher value) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::CAST_TO_ANY;
|
|
|
|
m.m_string_out_id = type_out;
|
|
|
|
m.m_sub_matchers = {value};
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
Matcher Matcher::any(int match_id) {
|
2021-01-25 22:08:58 -05:00
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::ANY;
|
2021-02-01 20:41:37 -05:00
|
|
|
m.m_form_match = match_id;
|
2021-01-25 22:08:58 -05:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::integer(std::optional<int> value) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::INT;
|
|
|
|
m.m_int_match = value;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-22 09:36:30 -05:00
|
|
|
Matcher Matcher::any_integer(int match_id) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::ANY_INT;
|
|
|
|
m.m_int_out_id = match_id;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2022-06-09 21:18:08 -04:00
|
|
|
Matcher Matcher::single(std::optional<float> value) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::FLOAT;
|
|
|
|
m.m_float_match = value;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
Matcher Matcher::any_quoted_symbol(int match_id) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::ANY_QUOTED_SYMBOL;
|
|
|
|
m.m_string_out_id = match_id;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::any_symbol(int match_id) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::ANY_SYMBOL;
|
|
|
|
m.m_string_out_id = match_id;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2023-03-11 10:45:16 -05:00
|
|
|
Matcher Matcher::quoted_symbol(const std::string& name) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::QUOTED_SYMBOL;
|
|
|
|
m.m_str = name;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
Matcher Matcher::symbol(const std::string& name) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::SYMBOL;
|
|
|
|
m.m_str = name;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-11 09:49:15 -05:00
|
|
|
Matcher Matcher::if_with_else(const Matcher& condition,
|
|
|
|
const Matcher& true_case,
|
|
|
|
const Matcher& false_case) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::IF_WITH_ELSE;
|
|
|
|
m.m_sub_matchers = {condition, true_case, false_case};
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
Matcher Matcher::if_no_else(const Matcher& condition, const Matcher& true_case) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::IF_NO_ELSE;
|
|
|
|
m.m_sub_matchers = {condition, true_case};
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::or_expression(const std::vector<Matcher>& elts) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::SC_OR;
|
|
|
|
m.m_sub_matchers = elts;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
Matcher Matcher::deref(const Matcher& root,
|
|
|
|
bool is_addr_of,
|
|
|
|
const std::vector<DerefTokenMatcher>& tokens) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::DEREF_OP;
|
|
|
|
m.m_sub_matchers = {root};
|
|
|
|
m.m_deref_is_addr_of = is_addr_of;
|
|
|
|
m.m_token_matchers = tokens;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
Matcher Matcher::set(const Matcher& dst, const Matcher& src) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::SET;
|
|
|
|
m.m_sub_matchers = {dst, src};
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-07-03 16:18:41 -04:00
|
|
|
Matcher Matcher::set_var(const Matcher& src, int dst_match_id) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::SET_VAR;
|
|
|
|
m.m_sub_matchers = {src};
|
|
|
|
m.m_reg_out_id = dst_match_id;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-03-05 21:46:39 -05:00
|
|
|
Matcher Matcher::while_loop(const Matcher& condition, const Matcher& body) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::WHILE_LOOP;
|
|
|
|
m.m_sub_matchers = {condition, body};
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-05-06 00:42:49 -04:00
|
|
|
Matcher Matcher::any_constant_token(int match_id) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::ANY_CONSTANT_TOKEN;
|
|
|
|
m.m_string_out_id = match_id;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-12-01 19:41:49 -05:00
|
|
|
Matcher Matcher::constant_token(const std::string& name) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::CONSTANT_TOKEN;
|
|
|
|
m.m_str = name;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-07-03 16:18:41 -04:00
|
|
|
Matcher Matcher::begin(const std::vector<Matcher>& elts) {
|
|
|
|
Matcher m;
|
|
|
|
m.m_kind = Kind::BEGIN;
|
|
|
|
m.m_sub_matchers = elts;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out) const {
|
2021-01-25 22:08:58 -05:00
|
|
|
switch (m_kind) {
|
2021-02-01 20:41:37 -05:00
|
|
|
case Kind::ANY:
|
|
|
|
if (m_form_match != -1) {
|
|
|
|
maps_out->forms[m_form_match] = input;
|
|
|
|
}
|
|
|
|
return true;
|
2022-05-19 21:30:14 -04:00
|
|
|
case Kind::ANY_REG:
|
|
|
|
case Kind::REG: {
|
2021-01-25 22:08:58 -05:00
|
|
|
bool got = false;
|
2021-02-28 12:38:29 -05:00
|
|
|
RegisterAccess result;
|
2021-01-25 22:08:58 -05:00
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
2021-01-25 22:08:58 -05:00
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_var()) {
|
|
|
|
got = true;
|
|
|
|
result = as_simple_atom->atom().var();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
2021-01-25 22:08:58 -05:00
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
|
|
|
auto atom = as_expr->expr().get_arg(0);
|
|
|
|
if (atom.is_var()) {
|
|
|
|
got = true;
|
|
|
|
result = atom.var();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (got) {
|
2022-05-19 21:30:14 -04:00
|
|
|
if (m_kind == Kind::REG) {
|
|
|
|
return result.reg() == *m_reg;
|
|
|
|
} else if (m_reg_out_id != -1) {
|
2021-01-25 22:08:58 -05:00
|
|
|
maps_out->regs.resize(std::max(size_t(m_reg_out_id + 1), maps_out->regs.size()));
|
|
|
|
maps_out->regs.at(m_reg_out_id) = result;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::ANY_LABEL: {
|
|
|
|
bool got = false;
|
|
|
|
int result;
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
2021-02-09 20:59:14 -05:00
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_label()) {
|
|
|
|
got = true;
|
|
|
|
result = as_simple_atom->atom().label();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
2021-02-09 20:59:14 -05:00
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
|
|
|
auto atom = as_expr->expr().get_arg(0);
|
|
|
|
if (atom.is_label()) {
|
|
|
|
got = true;
|
|
|
|
result = atom.label();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (got) {
|
|
|
|
if (m_label_out_id != -1) {
|
|
|
|
maps_out->label[m_label_out_id] = result;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2022-06-09 21:18:08 -04:00
|
|
|
case Kind::GENERIC_OP:
|
2021-01-27 13:47:54 -05:00
|
|
|
case Kind::GENERIC_OP_WITH_REST: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_generic = dynamic_cast<GenericElement*>(input->try_as_single_active_element());
|
2021-01-27 13:47:54 -05:00
|
|
|
if (as_generic) {
|
|
|
|
if (!m_gen_op_matcher->do_match(as_generic->op(), maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-06-09 21:18:08 -04:00
|
|
|
if ((m_kind == Kind::GENERIC_OP && as_generic->elts().size() != m_sub_matchers.size()) ||
|
|
|
|
(m_kind == Kind::GENERIC_OP_WITH_REST &&
|
|
|
|
as_generic->elts().size() < m_sub_matchers.size())) {
|
2021-01-27 13:47:54 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < m_sub_matchers.size(); i++) {
|
|
|
|
if (!m_sub_matchers.at(i).do_match(as_generic->elts().at(i), maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2021-01-25 22:08:58 -05:00
|
|
|
case Kind::OR: {
|
|
|
|
for (auto& matcher : m_sub_matchers) {
|
|
|
|
if (matcher.do_match(input, maps_out)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2021-05-06 00:42:49 -04:00
|
|
|
case Kind::ANY_CONSTANT_TOKEN: {
|
|
|
|
auto as_ct = input->try_as_element<ConstantTokenElement>();
|
|
|
|
if (as_ct) {
|
|
|
|
if (m_string_out_id != -1) {
|
|
|
|
maps_out->strings[m_string_out_id] = as_ct->value();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2021-12-01 19:41:49 -05:00
|
|
|
case Kind::CONSTANT_TOKEN: {
|
|
|
|
auto as_ct = input->try_as_element<ConstantTokenElement>();
|
|
|
|
if (as_ct) {
|
|
|
|
return as_ct->value() == m_str;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2021-01-25 22:08:58 -05:00
|
|
|
case Kind::CAST: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_cast = dynamic_cast<CastElement*>(input->try_as_single_active_element());
|
2021-01-25 22:08:58 -05:00
|
|
|
if (as_cast) {
|
|
|
|
if (as_cast->type().print() == m_str) {
|
|
|
|
return m_sub_matchers.at(0).do_match(as_cast->source(), maps_out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2022-11-12 17:56:07 -05:00
|
|
|
case Kind::CAST_TO_ANY: {
|
|
|
|
auto as_cast = dynamic_cast<CastElement*>(input->try_as_single_active_element());
|
|
|
|
if (as_cast) {
|
|
|
|
maps_out->strings[m_string_out_id] = as_cast->type().print();
|
|
|
|
return m_sub_matchers.at(0).do_match(as_cast->source(), maps_out);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2021-01-25 22:08:58 -05:00
|
|
|
case Kind::INT: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
2021-01-25 22:08:58 -05:00
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_int()) {
|
|
|
|
if (!m_int_match.has_value()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return as_simple_atom->atom().get_int() == *m_int_match;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
2021-01-25 22:08:58 -05:00
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
2022-06-09 21:18:08 -04:00
|
|
|
const auto& atom = as_expr->expr().get_arg(0);
|
2021-01-25 22:08:58 -05:00
|
|
|
if (atom.is_int()) {
|
|
|
|
if (!m_int_match.has_value()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return atom.get_int() == *m_int_match;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2022-06-09 21:18:08 -04:00
|
|
|
case Kind::FLOAT: {
|
|
|
|
auto as_const_float =
|
|
|
|
dynamic_cast<ConstantFloatElement*>(input->try_as_single_active_element());
|
|
|
|
if (as_const_float) {
|
|
|
|
if (!m_float_match.has_value()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return as_const_float->value() == *m_float_match;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2021-02-22 09:36:30 -05:00
|
|
|
case Kind::ANY_INT: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
2021-02-22 09:36:30 -05:00
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_int()) {
|
|
|
|
if (m_int_out_id != -1) {
|
|
|
|
maps_out->ints[m_int_out_id] = as_simple_atom->atom().get_int();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
2021-02-22 09:36:30 -05:00
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
2022-06-09 21:18:08 -04:00
|
|
|
const auto& atom = as_expr->expr().get_arg(0);
|
2021-02-22 09:36:30 -05:00
|
|
|
if (atom.is_int()) {
|
|
|
|
if (m_int_out_id != -1) {
|
|
|
|
maps_out->ints[m_int_out_id] = atom.get_int();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
} break;
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
case Kind::ANY_QUOTED_SYMBOL: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
2021-01-27 13:47:54 -05:00
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_sym_ptr()) {
|
|
|
|
if (m_string_out_id != -1) {
|
|
|
|
maps_out->strings[m_string_out_id] = as_simple_atom->atom().get_str();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
2021-01-27 13:47:54 -05:00
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
2022-06-09 21:18:08 -04:00
|
|
|
const auto& atom = as_expr->expr().get_arg(0);
|
2021-01-27 13:47:54 -05:00
|
|
|
if (atom.is_sym_ptr()) {
|
|
|
|
if (m_string_out_id != -1) {
|
|
|
|
maps_out->strings[m_string_out_id] = atom.get_str();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Kind::ANY_SYMBOL: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
2021-01-27 13:47:54 -05:00
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_sym_val()) {
|
|
|
|
if (m_string_out_id != -1) {
|
|
|
|
maps_out->strings[m_string_out_id] = as_simple_atom->atom().get_str();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
2021-01-27 13:47:54 -05:00
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
2022-06-09 21:18:08 -04:00
|
|
|
const auto& atom = as_expr->expr().get_arg(0);
|
2021-01-27 13:47:54 -05:00
|
|
|
if (atom.is_sym_val()) {
|
|
|
|
if (m_string_out_id != -1) {
|
|
|
|
maps_out->strings[m_string_out_id] = atom.get_str();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-03-11 10:45:16 -05:00
|
|
|
case Kind::QUOTED_SYMBOL: {
|
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_sym_ptr()) {
|
|
|
|
return as_simple_atom->atom().get_str() == m_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
|
|
|
const auto& atom = as_expr->expr().get_arg(0);
|
|
|
|
if (atom.is_sym_ptr()) {
|
|
|
|
return atom.get_str() == m_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::SYMBOL: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_simple_atom = dynamic_cast<SimpleAtomElement*>(input->try_as_single_active_element());
|
2021-02-09 20:59:14 -05:00
|
|
|
if (as_simple_atom) {
|
|
|
|
if (as_simple_atom->atom().is_sym_val()) {
|
|
|
|
return as_simple_atom->atom().get_str() == m_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_expr = dynamic_cast<SimpleExpressionElement*>(input->try_as_single_active_element());
|
2021-02-09 20:59:14 -05:00
|
|
|
if (as_expr && as_expr->expr().is_identity()) {
|
2022-06-09 21:18:08 -04:00
|
|
|
const auto& atom = as_expr->expr().get_arg(0);
|
2021-02-09 20:59:14 -05:00
|
|
|
if (atom.is_sym_val()) {
|
|
|
|
return atom.get_str() == m_str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
case Kind::DEREF_OP: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_deref = dynamic_cast<DerefElement*>(input->try_as_single_active_element());
|
2021-01-27 13:47:54 -05:00
|
|
|
if (as_deref) {
|
|
|
|
if (as_deref->is_addr_of() != m_deref_is_addr_of) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!m_sub_matchers.at(0).do_match(as_deref->base(), maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (as_deref->tokens().size() != m_token_matchers.size()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < as_deref->tokens().size(); i++) {
|
|
|
|
if (!m_token_matchers.at(i).do_match(as_deref->tokens().at(i), maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2021-01-25 22:08:58 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:59:14 -05:00
|
|
|
case Kind::SET: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_set = dynamic_cast<SetFormFormElement*>(input->try_as_single_active_element());
|
2021-02-09 20:59:14 -05:00
|
|
|
if (!as_set) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!m_sub_matchers.at(0).do_match(as_set->dst(), maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(1).do_match(as_set->src(), maps_out)) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2021-02-11 09:49:15 -05:00
|
|
|
case Kind::IF_WITH_ELSE: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_cond = dynamic_cast<CondWithElseElement*>(input->try_as_single_active_element());
|
2021-02-11 09:49:15 -05:00
|
|
|
if (!as_cond) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (as_cond->entries.size() != 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(0).do_match(as_cond->entries.front().condition, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(1).do_match(as_cond->entries.front().body, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(2).do_match(as_cond->else_ir, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} break;
|
|
|
|
|
2021-05-12 19:46:17 -04:00
|
|
|
case Kind::IF_NO_ELSE: {
|
|
|
|
auto as_cond = dynamic_cast<CondNoElseElement*>(input->try_as_single_active_element());
|
|
|
|
if (!as_cond) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (as_cond->entries.size() != 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(0).do_match(as_cond->entries.front().condition, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(1).do_match(as_cond->entries.front().body, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case Kind::SC_OR: {
|
|
|
|
auto as_sc = dynamic_cast<ShortCircuitElement*>(input->try_as_single_active_element());
|
|
|
|
if (!as_sc || as_sc->kind != ShortCircuitElement::OR) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (as_sc->entries.size() != m_sub_matchers.size()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < m_sub_matchers.size(); i++) {
|
|
|
|
if (!m_sub_matchers.at(i).do_match(as_sc->entries.at(i).condition, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} break;
|
|
|
|
|
2021-03-05 21:46:39 -05:00
|
|
|
case Kind::WHILE_LOOP: {
|
2021-05-12 19:46:17 -04:00
|
|
|
auto as_while = dynamic_cast<WhileElement*>(input->try_as_single_active_element());
|
2021-03-05 21:46:39 -05:00
|
|
|
if (!as_while) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(0).do_match(as_while->condition, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(1).do_match(as_while->body, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} break;
|
|
|
|
|
2021-07-03 16:18:41 -04:00
|
|
|
case Kind::BEGIN: {
|
|
|
|
if ((int)m_sub_matchers.size() != input->size()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < input->size(); i++) {
|
|
|
|
Form fake;
|
|
|
|
fake.elts().push_back(input->elts().at(i));
|
|
|
|
if (!m_sub_matchers.at(i).do_match(&fake, maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Kind::SET_VAR: {
|
|
|
|
auto as_set = dynamic_cast<SetVarElement*>(input->try_as_single_active_element());
|
|
|
|
if (!as_set) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_sub_matchers.at(0).do_match(as_set->src(), maps_out)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_reg_out_id != -1) {
|
|
|
|
maps_out->regs.resize(std::max((int)maps_out->regs.size(), m_reg_out_id + 1));
|
|
|
|
maps_out->regs.at(m_reg_out_id) = as_set->dst();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-01-25 22:08:58 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-02-09 20:59:14 -05:00
|
|
|
return false;
|
2021-01-25 22:08:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Matcher Matcher::any_reg_cast_to_int_or_uint(int match_id) {
|
|
|
|
return match_or(
|
|
|
|
{any_reg(match_id), cast("uint", any_reg(match_id)), cast("int", any_reg(match_id))});
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
MatchResult match(const Matcher& spec, Form* input) {
|
2021-01-25 22:08:58 -05:00
|
|
|
MatchResult result;
|
|
|
|
result.matched = spec.do_match(input, &result.maps);
|
|
|
|
return result;
|
|
|
|
}
|
2021-01-27 13:47:54 -05:00
|
|
|
|
2022-05-19 21:30:14 -04:00
|
|
|
MatchResult match(const Matcher& spec, FormElement* input) {
|
|
|
|
Form hack;
|
|
|
|
hack.elts().push_back(input);
|
|
|
|
MatchResult result;
|
|
|
|
result.matched = spec.do_match(&hack, &result.maps);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
DerefTokenMatcher DerefTokenMatcher::string(const std::string& str) {
|
|
|
|
DerefTokenMatcher result;
|
|
|
|
result.m_kind = Kind::STRING;
|
|
|
|
result.m_str = str;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-05-31 18:14:18 -04:00
|
|
|
DerefTokenMatcher DerefTokenMatcher::integer(int value) {
|
|
|
|
DerefTokenMatcher result;
|
|
|
|
result.m_kind = Kind::CONSTANT_INTEGER;
|
|
|
|
result.m_int = value;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-01-27 13:47:54 -05:00
|
|
|
DerefTokenMatcher DerefTokenMatcher::any_string(int match_id) {
|
|
|
|
DerefTokenMatcher result;
|
|
|
|
result.m_kind = Kind::ANY_STRING;
|
|
|
|
result.m_str_out_id = match_id;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-12-01 19:41:49 -05:00
|
|
|
DerefTokenMatcher DerefTokenMatcher::any_integer(int match_id) {
|
|
|
|
DerefTokenMatcher result;
|
|
|
|
result.m_kind = Kind::ANY_INTEGER;
|
|
|
|
result.m_str_out_id = match_id;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-02-12 12:26:19 -05:00
|
|
|
DerefTokenMatcher DerefTokenMatcher::any_expr(int match_id) {
|
|
|
|
DerefTokenMatcher result;
|
|
|
|
result.m_kind = Kind::ANY_EXPR;
|
|
|
|
result.m_str_out_id = match_id;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
DerefTokenMatcher DerefTokenMatcher::any_expr_or_int(int match_id) {
|
|
|
|
DerefTokenMatcher result;
|
|
|
|
result.m_kind = Kind::ANY_EXPR_OR_INT;
|
|
|
|
result.m_str_out_id = match_id;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DerefTokenMatcher::do_match(DerefToken& input, MatchResult::Maps* maps_out) const {
|
2021-01-27 13:47:54 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::STRING:
|
|
|
|
return input.kind() == DerefToken::Kind::FIELD_NAME && input.field_name() == m_str;
|
|
|
|
case Kind::ANY_STRING:
|
|
|
|
if (input.kind() == DerefToken::Kind::FIELD_NAME) {
|
|
|
|
if (m_str_out_id != -1) {
|
|
|
|
maps_out->strings[m_str_out_id] = input.field_name();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2021-05-31 18:14:18 -04:00
|
|
|
case Kind::CONSTANT_INTEGER:
|
|
|
|
return input.kind() == DerefToken::Kind::INTEGER_CONSTANT && input.is_int(m_int);
|
2022-02-12 12:26:19 -05:00
|
|
|
case Kind::ANY_EXPR:
|
|
|
|
case Kind::ANY_EXPR_OR_INT:
|
|
|
|
if (input.is_expr()) {
|
|
|
|
if (m_str_out_id != -1) {
|
|
|
|
maps_out->forms[m_str_out_id] = input.expr();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// NOTE intentional fallthrough
|
|
|
|
if (m_kind != Kind::ANY_EXPR_OR_INT) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-12-01 19:41:49 -05:00
|
|
|
case Kind::ANY_INTEGER:
|
|
|
|
if (input.kind() == DerefToken::Kind::INTEGER_CONSTANT) {
|
|
|
|
if (m_str_out_id != -1) {
|
|
|
|
maps_out->ints[m_str_out_id] = input.int_constant();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2021-01-27 13:47:54 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return false;
|
2021-01-27 13:47:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericOpMatcher GenericOpMatcher::fixed(FixedOperatorKind kind) {
|
|
|
|
GenericOpMatcher m;
|
|
|
|
m.m_kind = Kind::FIXED;
|
|
|
|
m.m_fixed_kind = kind;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
GenericOpMatcher GenericOpMatcher::func(const Matcher& func_matcher) {
|
|
|
|
GenericOpMatcher m;
|
|
|
|
m.m_kind = Kind::FUNC;
|
|
|
|
m.m_func_matcher = func_matcher;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-11 09:49:15 -05:00
|
|
|
GenericOpMatcher GenericOpMatcher::condition(IR2_Condition::Kind condition) {
|
|
|
|
GenericOpMatcher m;
|
|
|
|
m.m_kind = Kind::CONDITION;
|
|
|
|
m.m_condition_kind = condition;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-06-05 16:58:32 -04:00
|
|
|
GenericOpMatcher GenericOpMatcher::or_match(const std::vector<GenericOpMatcher>& matchers) {
|
|
|
|
GenericOpMatcher m;
|
|
|
|
m.m_kind = Kind::OR;
|
|
|
|
m.m_sub_matchers = matchers;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
bool GenericOpMatcher::do_match(GenericOperator& input, MatchResult::Maps* maps_out) const {
|
2021-01-27 13:47:54 -05:00
|
|
|
switch (m_kind) {
|
|
|
|
case Kind::FIXED:
|
|
|
|
if (input.kind() == GenericOperator::Kind::FIXED_OPERATOR) {
|
|
|
|
return input.fixed_kind() == m_fixed_kind;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
case Kind::FUNC:
|
|
|
|
if (input.kind() == GenericOperator::Kind::FUNCTION_EXPR) {
|
|
|
|
return m_func_matcher.do_match(input.func(), maps_out);
|
|
|
|
}
|
|
|
|
return false;
|
2021-02-11 09:49:15 -05:00
|
|
|
case Kind::CONDITION:
|
|
|
|
if (input.kind() == GenericOperator::Kind::CONDITION_OPERATOR) {
|
|
|
|
return input.condition_kind() == m_condition_kind;
|
|
|
|
}
|
|
|
|
return false;
|
2021-06-05 16:58:32 -04:00
|
|
|
case Kind::OR:
|
|
|
|
for (auto& m : m_sub_matchers) {
|
|
|
|
if (m.do_match(input, maps_out)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2021-01-27 13:47:54 -05:00
|
|
|
default:
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2021-03-07 12:01:59 -05:00
|
|
|
return false;
|
2021-01-27 13:47:54 -05:00
|
|
|
}
|
|
|
|
}
|
2021-02-11 09:49:15 -05:00
|
|
|
|
2021-12-01 19:41:49 -05:00
|
|
|
} // namespace decompiler
|