libregexis024/src/libregexis024test/byte_code_disassembler.h

212 lines
8.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This file is used for testing purposes only. Do not copy this file to installation prefix. */
#ifndef LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H
#define LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H
#include "vibe_check.h"
#include <libregexis024vm/vm_opcodes.h>
#include <libregexis024vm/utils.h>
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
#include <inttypes.h>
#include <stdexcept>
using namespace regexis024;
struct landing_place_resolvance{
size_t name_id;
bool visited = false;
landing_place_resolvance() = default;
landing_place_resolvance(size_t nameId, bool visited) : name_id(nameId), visited(visited) {}
};
void print_disassembly(size_t prgSize, uint8_t* prg){
std::vector<std::string> names = {
"Александр", "Мария", "Иван", "Анна", "Дмитрий", "Екатерина", "Алексей",
"Ольга", "Михаил", "София", "Сергей", "Анастасия", "Артем", "Виктория",
"Андрей", "Елена", "Максим", "Алиса", "Павел", "Наталья", "Денис", "Юлия",
"Владимир", "Маргарита", "Никита", "Дарья", "Илья", "Алина", "Роман", "Евгения",
"Кирилл", "Елизавета", "Антон", "Татьяна", "Владислав", "Валерия", "Георгий",
"Ксения", "Арсений", "Милана", "Даниил", "Вероника", "Тимофей", "Арина",
"Николай", "Кристина", "Степан", "Алёна", "Игорь", "Алла", "Григорий", "Ева",
"Олег", "Яна", "Семен", "Марина", "Федор", "Светлана", "Василий", "Людмила"
};
uint64_t used_names = 0;
/* From program position -> to names[ind] & */
std::map<near_ptr_t, landing_place_resolvance> bookmarks;
near_ptr_t IP = 0;
auto check_inboundness = [&](int region){
if (!vmprog_check_inboundness(prgSize, IP, region)) {
fprintf(stderr, "This program can't be decomposed into commands in a trivial way");
std::terminate();
}
};
auto extract_b = [&]() -> uint8_t{
check_inboundness(1);
return vmprog_extract_b(&IP, prg);
};
auto extract_w = [&]() -> uint16_t {
check_inboundness(2);
return vmprog_extract_w(&IP, prg);
};
auto extract_dw = [&]() -> uint32_t {
check_inboundness(4);
return vmprog_extract_dw(&IP, prg);
};
auto extract_qw = [&]() -> uint64_t {
check_inboundness(8);
return vmprog_extract_qw(&IP, prg);
};
auto extract_instruction = [&]() -> uint8_t{
return extract_b();
};
auto extract_sslot_id = [&]() -> sslot_id_t{
return extract_dw();
};
auto extract_near_pointer = [&]() -> near_ptr_t{
return extract_qw();
};
auto extract_track_array_index = [&]() -> tai_t{
return extract_w();
};
bool second_phase = false;
auto fph_register_landing = [&](near_ptr_t pos){
if (!second_phase){
if (bookmarks.count(pos) == 0){
if (used_names == names.size())
names.push_back("Закладка_" + std::to_string(used_names));
bookmarks.insert({pos, {used_names, false}});
used_names++;
}
}
};
auto get_bookmark_in_2phase = [&](near_ptr_t pos) -> std::string {
if (bookmarks.count(pos) == 0) {
fprintf(stderr, "Bruh\n");
std::terminate();
}
return names[bookmarks[pos].name_id];
};
auto one_reading = [&](){
while (IP < prgSize) {
near_ptr_t start_pos = IP;
if (second_phase){
if (bookmarks.count(IP) != 0){
printf("%s:\n", get_bookmark_in_2phase(IP).c_str());
bookmarks[IP].visited = true;
}
}
uint8_t opcode = extract_instruction();
switch (opcode) {
#define secPrint(fmt, ...) if (second_phase) {printf("% 3lu) " fmt, start_pos, __VA_ARGS__);} } break;
#define secPrintNoArg(str) if (second_phase) {printf("% 3lu) " str, start_pos);} } break;
#define instCase(oper_code) case opcodes::oper_code: {
#define jcMess(cond, sz_uppercase, x_t, extract_method, printf_sign) \
instCase(JC ## cond ## _ ## sz_uppercase) \
x_t x = extract_method(); \
near_ptr_t dest = extract_near_pointer(); \
fph_register_landing(dest); \
secPrint("JC" #cond "_" #sz_uppercase " %" printf_sign " $%s\n", x, get_bookmark_in_2phase(dest).c_str())
#define jcCacaphony(cond) \
jcMess(cond, B, uint8_t, extract_b, PRIu8) \
jcMess(cond, W, uint16_t, extract_w, PRIu16) \
jcMess(cond, DW, uint32_t, extract_dw, PRIu32) \
jcMess(cond, QW, uint64_t, extract_qw, PRIu64)
#define simpleDimple(name) instCase(name) secPrintNoArg(#name "\n")
instCase(READ)
uint32_t ssid = extract_sslot_id();
secPrint("READ %u\n", ssid)
simpleDimple(READZ)
instCase(JUMP)
uint32_t dest = extract_near_pointer();
fph_register_landing(dest);
secPrint("JUMP $%s\n", get_bookmark_in_2phase(dest).c_str())
jcCacaphony(EQUAL)
jcCacaphony(LESS)
jcCacaphony(GRTR)
instCase(FORK)
uint32_t ssid = extract_sslot_id();
near_ptr_t dest = extract_near_pointer();
fph_register_landing(dest);
secPrint("FORK %u $%s\n", ssid, get_bookmark_in_2phase(dest).c_str())
simpleDimple(MATCH)
simpleDimple(DIE)
instCase(PARAM_READ_SS_NUMBER)
sslot_id_t ssid_max_plus_one = extract_sslot_id();
secPrint("PARAM_READ_SS_NUMBER %u\n", ssid_max_plus_one)
instCase(PARAM_FORK_SS_NUMBER)
sslot_id_t ssid_max_plus_one = extract_sslot_id();
secPrint("PARAM_FORK_SS_NUMBER %u\n", ssid_max_plus_one)
instCase(PARAM_SELARR_LEN)
tai_t tai_max_plus_one = extract_track_array_index();
secPrint("PARAM_SELARR_LEN %hu\n", tai_max_plus_one)
instCase(PARAM_COLSIFTFUNC_SET)
near_ptr_t entry = extract_near_pointer();
fph_register_landing(entry);
secPrint("PARAM_COLSIFTFUNC_SET $%s\n", get_bookmark_in_2phase(entry).c_str())
simpleDimple(PARAM_COLSIFTFUNC_WIPE)
instCase(MSG_MULTISTART_ALLOWED)
uint8_t is_allowed = extract_b();
secPrint("MSG_MULTISTART_ALLOWED %hhu\n", is_allowed)
instCase(MSG_FED_INPUT_EXTENDED)
uint8_t left = extract_b();
uint8_t right = extract_b();
sslot_id_t part = extract_sslot_id();
secPrint("MSG_FED_INPUT_EXTENDED %hhu %hhu %u\n", left, right, part)
instCase(DMOV_RABX_SELARR)
tai_t i = extract_track_array_index();
secPrint("DMOV_RABX_SELARR %hu\n", i)
instCase(DDIST_RABX_SELARR)
tai_t s = extract_track_array_index();
tai_t e = extract_track_array_index();
secPrint("DDIST_RABX_SELARR %hu %hu\n", s, e);
simpleDimple(SIFTPRIOR_MIN_RABX)
simpleDimple(SIFTPRIOR_MAX_RABX)
simpleDimple(SIFT_DONE)
instCase(MOV_COLARR_IMM)
tai_t tai = extract_track_array_index();
uint64_t imm = extract_qw();
secPrint("MOV_COLARR_IMM %hu %lu\n", tai, imm);
instCase(MOV_COLARR_BTPOS)
tai_t tai = extract_track_array_index();
secPrint("MOV_COLARR_BTPOS %hu\n", tai);
instCase(MOV_SELARR_IMM)
tai_t tai = extract_track_array_index();
uint64_t imm = extract_qw();
secPrint("MOV_SELARR_IMM %hu %lu\n", tai, imm);
instCase(MOV_SELARR_CHPOS)
tai_t tai = extract_track_array_index();
secPrint("MOV_SELARR_CHPOS %hu\n", tai);
simpleDimple(INIT)
simpleDimple(THROW)
default:
fprintf(stderr, "Bad opcode\n");
std::terminate();
#undef secPrint
#undef secPrintNoArg
#undef instCase
#undef jcMess
#undef jcCacaphony
#undef simpleDimple
}
}
};
one_reading();
second_phase = true;
IP = 0;
one_reading();
}
#endif //LIBREGEXIS024_BYTE_CODE_DISASSEMBLER_H