From 287bf565bd9ed245d26bcfe5cb9877fffcf35b49 Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Wed, 5 May 2021 15:16:57 +0200 Subject: [PATCH] [FEAT] Implemented 'if' support [BUG] Variables inside blocks couldn't shadow those outside [FEAT] Decompiler shows address of each opcode --- decompiled.txt | 30 ++++++---- decompiler.cpp | 18 +++++- parser.cpp | 150 ++++++++++++++++++------------------------------- scope.cpp | 15 +++-- scope.h | 2 +- test.vb | 7 ++- 6 files changed, 108 insertions(+), 114 deletions(-) diff --git a/decompiled.txt b/decompiled.txt index 633d1b7..a0f069d 100644 --- a/decompiled.txt +++ b/decompiled.txt @@ -1,10 +1,20 @@ -NOP -NOP -PUSH 4 -LD 72 -LD 60 -MUL -SUB -ST 144 -STL 4 -STL 0 +0000: NOP +0001: NOP +0002: PUSH 4 +0007: LD 72 +0012: LD 60 +0017: MUL +0018: SUB +0019: ST 144 +0024: RET +0025: STL 4 +0030: STL 0 +0035: LDL 8 +0040: PUSH 0 +0045: GT +0046: JNT 66 +0051: PUSH 1 +0056: STL 12 +0061: JMP 76 +0066: PUSH 2 +0071: STL 16 diff --git a/decompiler.cpp b/decompiler.cpp index 848532b..016edf9 100644 --- a/decompiler.cpp +++ b/decompiler.cpp @@ -4,10 +4,22 @@ #include #include "parser.h" -#define SIMPLE(X) f << X << std::endl; pos++; break +#define SIMPLE(X) f << get_address(pos) << ": " << X << std::endl; pos++; break // [RZC 05/05/2021] To solve alignment problems on ARM architectures we have to first copy the 4 bytes to an aligned byte array, then cast it to float -#define FVAR(X) memcpy(data, &code[pos+1], 4); f << X << " " << *((float*)data) << std::endl; pos += 5; break -#define IVAR(X) memcpy(data, &code[pos+1], 4); f << X << " " << *((uint32_t*)data) << std::endl; pos += 5; break +#define FVAR(X) memcpy(data, &code[pos+1], 4); f << get_address(pos) << ": " << X << " " << *((float*)data) << std::endl; pos += 5; break +#define IVAR(X) memcpy(data, &code[pos+1], 4); f << get_address(pos) << ": " << X << " " << *((uint32_t*)data) << std::endl; pos += 5; break + +static std::string get_address(const int pos) { + std::string label = "0000"; + int value = pos; + int i = 3; + while (value > 0) { + label[i] = 48 + (value % 10); + value = value / 10; + i--; + } + return label; +} void decompiler_save(const uint8_t *code, const int size) { uint8_t data[4]; diff --git a/parser.cpp b/parser.cpp index 3f5aa3a..39d1c7d 100644 --- a/parser.cpp +++ b/parser.cpp @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include "decompiler.h" #define MAX_CODE_SIZE 65536 @@ -19,36 +21,12 @@ #define MAX_CONSTANTS 256 #define MAX_STRUCT_MEMBERS 10 -/* -struct t_variable { - char name[MAX_IDENTIFIER_LENGTH]; - int type; - int length; - int address; -}; - -struct t_struct { - char name[MAX_IDENTIFIER_LENGTH]; - int num_members; - t_variable members[MAX_STRUCT_MEMBERS]; -}; - -struct t_scope { - -}; -*/ - struct t_label { - char name[MAX_IDENTIFIER_LENGTH]; - word address; + std::string name; + uint32_t address; }; -/*struct t_variable { - char name[MAX_IDENTIFIER_LENGTH]; - int index = 0; - int size = 1; - t_variable* next{ nullptr }; -}; +/* struct t_external_function { char name[MAX_IDENTIFIER_LENGTH]; @@ -60,25 +38,21 @@ struct t_string { word references[256]; int num_references = 1; }; - -struct t_constant { - char name[MAX_IDENTIFIER_LENGTH]; - byte value; -};*/ +*/ static byte* code; // [MAX_CODE_SIZE]; static uint32_t codepos = 0; static uint32_t lines[32768]; static uint32_t current_line; -//static t_label known_labels[MAX_LABELS]; +static std::vector known_labels; //static int num_known_labels = 0; -static t_label unknown_labels[MAX_LABELS]; -static int num_unknown_labels = 0; +static std::vector unknown_labels; +//static int num_unknown_labels = 0; static int num_anonymous_labels = 0; -static char* breaklabel = nullptr; -static char* contlabel = nullptr; +static std::string breaklabel = ""; +static std::string contlabel = ""; /* static t_variable* variables = nullptr; @@ -102,15 +76,16 @@ static bool global_closed = false; /* GENERIC FUNCTIONS */ /****************************************************************************************/ -static void int_to_string(int value, char* label) { - for (int i = 0; i < 7; i++) label[i] = '0'; - label[7] = 0; +static const std::string int_to_string(int value) { + std::string label = "0000000"; + //for (int i = 0; i < 7; i++) label[i] = '0'; int i = 6; while (value > 0) { label[i] = 48 + (value % 10); value = value / 10; i--; } + return label; } /****************************************************************************************/ @@ -162,56 +137,44 @@ static const uint32_t get_current_address() { return codepos; } +#define EXPECT(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return; } +#define EXPECT2(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return -1; } +#define HALT(Y) { parser_finished = true; error_raise(Y); return; } +#define HALT2(Y) { parser_finished = true; error_raise(Y); return -1; } + /****************************************************************************************/ /* LABEL MANAGEMENT */ /****************************************************************************************/ -/* -static const word get_label_address(const char* string) { - for (int i = 0; i < num_known_labels; i++) { if (strcmp(known_labels[i].name, string) == 0) return known_labels[i].address; } - //unknown_labels[num_unknown_labels].name = (char*)malloc(strlen(string) + 1); - strcpy(unknown_labels[num_unknown_labels].name, string); - unknown_labels[num_unknown_labels].address = get_current_address(); - num_unknown_labels++; + +static const uint32_t get_label_address(const std::string name) { + for (auto label : known_labels) if (label.name == name) return label.address; + unknown_labels.push_back({name, get_current_address()}); return 0; } -static void register_label_address(const char* string) { +static void register_label_address(const std::string name) { // If the label already exists, vomit an error - for (int i = 0; i < num_known_labels; i++) { - if (strcmp(known_labels[i].name, string) == 0) { - parser_finished = true; - error_raise("Duplicate label"); - return; - } - } + for (auto label : known_labels) if (label.name == name) HALT("Duplicate label"); + // register new label - //known_labels[num_known_labels].name = (char*)malloc(strlen(string) + 1); - strcpy(known_labels[num_known_labels].name, string); - known_labels[num_known_labels++].address = get_current_address(); + known_labels.push_back({name, get_current_address()}); + // patch and remove any references awaiting for this label - int i = 0; - while (i < num_unknown_labels) { - if (strcmp(unknown_labels[i].name, string) == 0) { - patch(unknown_labels[i].address, get_current_address()); - if (i < num_unknown_labels - 1) { - //free(unknown_labels[i].name); - unknown_labels[i].address = unknown_labels[num_unknown_labels - 1].address; - strcpy(unknown_labels[i].name, unknown_labels[num_unknown_labels - 1].name); - //unknown_labels[i].name = unknown_labels[num_unknown_labels - 1].name; - } - num_unknown_labels--; - } - else { - i++; + auto i = std::begin(unknown_labels); + while (i != std::end(unknown_labels)) { + if ((*i).name == name) { + patch_dw((*i).address, get_current_address()); + i = unknown_labels.erase(i); + } else { + ++i; } } - //num_known_labels++; } -static void generate_anonymous_labelname(char* dest) { - int_to_string(num_anonymous_labels++, dest); +static const std::string generate_anonymous_labelname() { + return int_to_string(num_anonymous_labels++); } -*/ + @@ -234,11 +197,6 @@ static void parse_getchar(); static void parse_getcolor(); */ -#define EXPECT(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return; } -#define EXPECT2(X, Y) if (tkn_get_token() != X) { parser_finished = true; error_raise(Y); return -1; } -#define HALT(Y) { parser_finished = true; error_raise(Y); return; } -#define HALT2(Y) { parser_finished = true; error_raise(Y); return -1; } - /* static void parse_concat_atom() { if (tkn_get_token() == TOKEN_STRING) { @@ -418,8 +376,8 @@ static void parse_expression() { } } -static bool identifier_exists(const std::string identifier) { - if (scope_variable_exists(identifier)) return true; +static bool identifier_exists(const std::string identifier, const bool can_shadow=false) { + if (scope_variable_exists(identifier, can_shadow)) return true; if (types_exist(identifier) != -1) return true; if (function_exists(identifier)) return true; return false; @@ -429,7 +387,7 @@ static void parse_const() { EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); char const_name[40]; strcpy(const_name, tkn_get_string()); - if (identifier_exists(const_name)) HALT("Identifier already exists"); + if (identifier_exists(const_name, true)) HALT("Identifier already exists"); tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'"); tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier"); char type_name[40]; @@ -448,7 +406,7 @@ static void parse_var() { int var_length = 1; EXPECT(TOKEN_IDENTIFIER, "Expected identifier"); const std::string var_name = tkn_get_string(); - if (identifier_exists(var_name)) HALT("Identifier already exists"); + if (identifier_exists(var_name, true)) HALT("Identifier already exists"); tkn_next(); EXPECT(TOKEN_AS, "Expected 'as'"); tkn_next(); if (tkn_get_token() == TOKEN_ARRAY) { @@ -646,28 +604,30 @@ static void parse_dec() { } }*/ -/* + static void parse_if() { - char* previous_breaklabel = breaklabel; + const std::string previous_breaklabel = breaklabel; parse_expression(); EXPECT(TOKEN_THEN, "Expected 'THEN'"); tkn_next(); emmit(OP_JNT); - char elselabel[8]; - generate_anonymous_labelname(elselabel); - char endlabel[8]; - generate_anonymous_labelname(endlabel); + const std::string elselabel = generate_anonymous_labelname(); + const std::string endlabel = generate_anonymous_labelname(); breaklabel = endlabel; bool else_visited = false; - emmit_w(get_label_address(elselabel)); + emmit_dw(get_label_address(elselabel)); + scope_open_block(); parse_statements(); + scope_close_block(); if (tkn_get_token() == TOKEN_ELSE) { else_visited = true; emmit(OP_JMP); - emmit_w(get_label_address(endlabel)); + emmit_dw(get_label_address(endlabel)); register_label_address(elselabel); tkn_next(); + scope_open_block(); parse_statements(); + scope_close_block(); } if (tkn_get_token() == TOKEN_END) { if (!else_visited) register_label_address(elselabel); @@ -679,7 +639,7 @@ static void parse_if() { parser_finished = true; if (!else_visited) error_raise("Expected 'ELSE', 'END' or a statement"); else error_raise("Expected 'END' or a statement"); } - +/* static void parse_for() { char* previous_breaklabel = breaklabel; char* previous_contlabel = contlabel; @@ -804,9 +764,9 @@ static void parse_statements() { tkn_next(); parse_const(); break; case TOKEN_VAR: tkn_next(); parse_var(); break; -/* case TOKEN_IF: tkn_next(); parse_if(); break; +/* case TOKEN_FOR: tkn_next(); parse_for(); break; case TOKEN_BREAK: diff --git a/scope.cpp b/scope.cpp index c422734..236e1ec 100644 --- a/scope.cpp +++ b/scope.cpp @@ -69,11 +69,18 @@ const int scope_declare_variable(const std::string name, const uint32_t type, co return address; } -const bool scope_variable_exists(const std::string name) { +const bool scope_variable_exists(const std::string name, const bool can_shadow) { t_scope& scope = (are_we_inside_local ? local : global); - for (t_variable v : scope.variables) if (v.name == name) { - current_var = &v; - return true; + if (are_we_inside_local && can_shadow) { + for (int i = blocks.top(); i < scope.variables.size(); i++ ) if (scope.variables[i].name == name) { + current_var = &scope.variables[i]; + return true; + } + } else { + for (t_variable v : scope.variables) if (v.name == name) { + current_var = &v; + return true; + } } return false; } diff --git a/scope.h b/scope.h index 9679447..c5cf464 100644 --- a/scope.h +++ b/scope.h @@ -11,7 +11,7 @@ void scope_close_block(); const int scope_declare_variable(const std::string name, const uint32_t type, const uint32_t length); -const bool scope_variable_exists(const std::string name); +const bool scope_variable_exists(const std::string name, const bool can_shadow = false); const uint32_t scope_get_variable_address(); const int scope_get_variable_size(); const int scope_get_variable_type(); diff --git a/test.vb b/test.vb index 0d42149..72f7e2d 100644 --- a/test.vb +++ b/test.vb @@ -14,6 +14,11 @@ var peiv as array of 2 triangle const perico as number = 4-peiv[1].a.x * peiv[0].c.y[2] function tarari(a as number, b as number) as number - var x as number + var local1 as number + if local1 > 0 then + var local1 as number = 1 + else + var local3 as number = 2 + end end