[FEAT] Implemented 'if' support
[BUG] Variables inside blocks couldn't shadow those outside [FEAT] Decompiler shows address of each opcode
This commit is contained in:
@@ -1,10 +1,20 @@
|
|||||||
NOP
|
0000: NOP
|
||||||
NOP
|
0001: NOP
|
||||||
PUSH 4
|
0002: PUSH 4
|
||||||
LD 72
|
0007: LD 72
|
||||||
LD 60
|
0012: LD 60
|
||||||
MUL
|
0017: MUL
|
||||||
SUB
|
0018: SUB
|
||||||
ST 144
|
0019: ST 144
|
||||||
STL 4
|
0024: RET
|
||||||
STL 0
|
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
|
||||||
|
|||||||
@@ -4,10 +4,22 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "parser.h"
|
#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
|
// [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 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 << X << " " << *((uint32_t*)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) {
|
void decompiler_save(const uint8_t *code, const int size) {
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
|
|||||||
150
parser.cpp
150
parser.cpp
@@ -8,7 +8,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
#include "decompiler.h"
|
#include "decompiler.h"
|
||||||
|
|
||||||
#define MAX_CODE_SIZE 65536
|
#define MAX_CODE_SIZE 65536
|
||||||
@@ -19,36 +21,12 @@
|
|||||||
#define MAX_CONSTANTS 256
|
#define MAX_CONSTANTS 256
|
||||||
#define MAX_STRUCT_MEMBERS 10
|
#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 {
|
struct t_label {
|
||||||
char name[MAX_IDENTIFIER_LENGTH];
|
std::string name;
|
||||||
word address;
|
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 {
|
struct t_external_function {
|
||||||
char name[MAX_IDENTIFIER_LENGTH];
|
char name[MAX_IDENTIFIER_LENGTH];
|
||||||
@@ -60,25 +38,21 @@ struct t_string {
|
|||||||
word references[256];
|
word references[256];
|
||||||
int num_references = 1;
|
int num_references = 1;
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
struct t_constant {
|
|
||||||
char name[MAX_IDENTIFIER_LENGTH];
|
|
||||||
byte value;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
static byte* code; // [MAX_CODE_SIZE];
|
static byte* code; // [MAX_CODE_SIZE];
|
||||||
static uint32_t codepos = 0;
|
static uint32_t codepos = 0;
|
||||||
static uint32_t lines[32768];
|
static uint32_t lines[32768];
|
||||||
static uint32_t current_line;
|
static uint32_t current_line;
|
||||||
|
|
||||||
//static t_label known_labels[MAX_LABELS];
|
static std::vector<t_label> known_labels;
|
||||||
//static int num_known_labels = 0;
|
//static int num_known_labels = 0;
|
||||||
static t_label unknown_labels[MAX_LABELS];
|
static std::vector<t_label> unknown_labels;
|
||||||
static int num_unknown_labels = 0;
|
//static int num_unknown_labels = 0;
|
||||||
static int num_anonymous_labels = 0;
|
static int num_anonymous_labels = 0;
|
||||||
|
|
||||||
static char* breaklabel = nullptr;
|
static std::string breaklabel = "";
|
||||||
static char* contlabel = nullptr;
|
static std::string contlabel = "";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
static t_variable* variables = nullptr;
|
static t_variable* variables = nullptr;
|
||||||
@@ -102,15 +76,16 @@ static bool global_closed = false;
|
|||||||
/* GENERIC FUNCTIONS */
|
/* GENERIC FUNCTIONS */
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
|
|
||||||
static void int_to_string(int value, char* label) {
|
static const std::string int_to_string(int value) {
|
||||||
for (int i = 0; i < 7; i++) label[i] = '0';
|
std::string label = "0000000";
|
||||||
label[7] = 0;
|
//for (int i = 0; i < 7; i++) label[i] = '0';
|
||||||
int i = 6;
|
int i = 6;
|
||||||
while (value > 0) {
|
while (value > 0) {
|
||||||
label[i] = 48 + (value % 10);
|
label[i] = 48 + (value % 10);
|
||||||
value = value / 10;
|
value = value / 10;
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
@@ -162,56 +137,44 @@ static const uint32_t get_current_address() {
|
|||||||
return codepos;
|
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 */
|
/* LABEL MANAGEMENT */
|
||||||
/****************************************************************************************/
|
/****************************************************************************************/
|
||||||
/*
|
|
||||||
static const word get_label_address(const char* string) {
|
static const uint32_t get_label_address(const std::string name) {
|
||||||
for (int i = 0; i < num_known_labels; i++) { if (strcmp(known_labels[i].name, string) == 0) return known_labels[i].address; }
|
for (auto label : known_labels) if (label.name == name) return label.address;
|
||||||
//unknown_labels[num_unknown_labels].name = (char*)malloc(strlen(string) + 1);
|
unknown_labels.push_back({name, get_current_address()});
|
||||||
strcpy(unknown_labels[num_unknown_labels].name, string);
|
|
||||||
unknown_labels[num_unknown_labels].address = get_current_address();
|
|
||||||
num_unknown_labels++;
|
|
||||||
return 0;
|
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
|
// If the label already exists, vomit an error
|
||||||
for (int i = 0; i < num_known_labels; i++) {
|
for (auto label : known_labels) if (label.name == name) HALT("Duplicate label");
|
||||||
if (strcmp(known_labels[i].name, string) == 0) {
|
|
||||||
parser_finished = true;
|
|
||||||
error_raise("Duplicate label");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// register new label
|
// register new label
|
||||||
//known_labels[num_known_labels].name = (char*)malloc(strlen(string) + 1);
|
known_labels.push_back({name, get_current_address()});
|
||||||
strcpy(known_labels[num_known_labels].name, string);
|
|
||||||
known_labels[num_known_labels++].address = get_current_address();
|
|
||||||
// patch and remove any references awaiting for this label
|
// patch and remove any references awaiting for this label
|
||||||
int i = 0;
|
auto i = std::begin(unknown_labels);
|
||||||
while (i < num_unknown_labels) {
|
while (i != std::end(unknown_labels)) {
|
||||||
if (strcmp(unknown_labels[i].name, string) == 0) {
|
if ((*i).name == name) {
|
||||||
patch(unknown_labels[i].address, get_current_address());
|
patch_dw((*i).address, get_current_address());
|
||||||
if (i < num_unknown_labels - 1) {
|
i = unknown_labels.erase(i);
|
||||||
//free(unknown_labels[i].name);
|
} else {
|
||||||
unknown_labels[i].address = unknown_labels[num_unknown_labels - 1].address;
|
++i;
|
||||||
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++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//num_known_labels++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generate_anonymous_labelname(char* dest) {
|
static const std::string generate_anonymous_labelname() {
|
||||||
int_to_string(num_anonymous_labels++, dest);
|
return int_to_string(num_anonymous_labels++);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -234,11 +197,6 @@ static void parse_getchar();
|
|||||||
static void parse_getcolor();
|
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() {
|
static void parse_concat_atom() {
|
||||||
if (tkn_get_token() == TOKEN_STRING) {
|
if (tkn_get_token() == TOKEN_STRING) {
|
||||||
@@ -418,8 +376,8 @@ static void parse_expression() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool identifier_exists(const std::string identifier) {
|
static bool identifier_exists(const std::string identifier, const bool can_shadow=false) {
|
||||||
if (scope_variable_exists(identifier)) return true;
|
if (scope_variable_exists(identifier, can_shadow)) return true;
|
||||||
if (types_exist(identifier) != -1) return true;
|
if (types_exist(identifier) != -1) return true;
|
||||||
if (function_exists(identifier)) return true;
|
if (function_exists(identifier)) return true;
|
||||||
return false;
|
return false;
|
||||||
@@ -429,7 +387,7 @@ static void parse_const() {
|
|||||||
EXPECT(TOKEN_IDENTIFIER, "Expected identifier");
|
EXPECT(TOKEN_IDENTIFIER, "Expected identifier");
|
||||||
char const_name[40];
|
char const_name[40];
|
||||||
strcpy(const_name, tkn_get_string());
|
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_AS, "Expected 'as'");
|
||||||
tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier");
|
tkn_next(); EXPECT(TOKEN_IDENTIFIER, "Expected type identifier");
|
||||||
char type_name[40];
|
char type_name[40];
|
||||||
@@ -448,7 +406,7 @@ static void parse_var() {
|
|||||||
int var_length = 1;
|
int var_length = 1;
|
||||||
EXPECT(TOKEN_IDENTIFIER, "Expected identifier");
|
EXPECT(TOKEN_IDENTIFIER, "Expected identifier");
|
||||||
const std::string var_name = tkn_get_string();
|
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(); EXPECT(TOKEN_AS, "Expected 'as'");
|
||||||
tkn_next();
|
tkn_next();
|
||||||
if (tkn_get_token() == TOKEN_ARRAY) {
|
if (tkn_get_token() == TOKEN_ARRAY) {
|
||||||
@@ -646,28 +604,30 @@ static void parse_dec() {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*
|
|
||||||
static void parse_if() {
|
static void parse_if() {
|
||||||
char* previous_breaklabel = breaklabel;
|
const std::string previous_breaklabel = breaklabel;
|
||||||
parse_expression();
|
parse_expression();
|
||||||
EXPECT(TOKEN_THEN, "Expected 'THEN'");
|
EXPECT(TOKEN_THEN, "Expected 'THEN'");
|
||||||
tkn_next();
|
tkn_next();
|
||||||
emmit(OP_JNT);
|
emmit(OP_JNT);
|
||||||
char elselabel[8];
|
const std::string elselabel = generate_anonymous_labelname();
|
||||||
generate_anonymous_labelname(elselabel);
|
const std::string endlabel = generate_anonymous_labelname();
|
||||||
char endlabel[8];
|
|
||||||
generate_anonymous_labelname(endlabel);
|
|
||||||
breaklabel = endlabel;
|
breaklabel = endlabel;
|
||||||
bool else_visited = false;
|
bool else_visited = false;
|
||||||
emmit_w(get_label_address(elselabel));
|
emmit_dw(get_label_address(elselabel));
|
||||||
|
scope_open_block();
|
||||||
parse_statements();
|
parse_statements();
|
||||||
|
scope_close_block();
|
||||||
if (tkn_get_token() == TOKEN_ELSE) {
|
if (tkn_get_token() == TOKEN_ELSE) {
|
||||||
else_visited = true;
|
else_visited = true;
|
||||||
emmit(OP_JMP);
|
emmit(OP_JMP);
|
||||||
emmit_w(get_label_address(endlabel));
|
emmit_dw(get_label_address(endlabel));
|
||||||
register_label_address(elselabel);
|
register_label_address(elselabel);
|
||||||
tkn_next();
|
tkn_next();
|
||||||
|
scope_open_block();
|
||||||
parse_statements();
|
parse_statements();
|
||||||
|
scope_close_block();
|
||||||
}
|
}
|
||||||
if (tkn_get_token() == TOKEN_END) {
|
if (tkn_get_token() == TOKEN_END) {
|
||||||
if (!else_visited) register_label_address(elselabel);
|
if (!else_visited) register_label_address(elselabel);
|
||||||
@@ -679,7 +639,7 @@ static void parse_if() {
|
|||||||
parser_finished = true;
|
parser_finished = true;
|
||||||
if (!else_visited) error_raise("Expected 'ELSE', 'END' or a statement"); else error_raise("Expected 'END' or a statement");
|
if (!else_visited) error_raise("Expected 'ELSE', 'END' or a statement"); else error_raise("Expected 'END' or a statement");
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
static void parse_for() {
|
static void parse_for() {
|
||||||
char* previous_breaklabel = breaklabel;
|
char* previous_breaklabel = breaklabel;
|
||||||
char* previous_contlabel = contlabel;
|
char* previous_contlabel = contlabel;
|
||||||
@@ -804,9 +764,9 @@ static void parse_statements() {
|
|||||||
tkn_next(); parse_const(); break;
|
tkn_next(); parse_const(); break;
|
||||||
case TOKEN_VAR:
|
case TOKEN_VAR:
|
||||||
tkn_next(); parse_var(); break;
|
tkn_next(); parse_var(); break;
|
||||||
/*
|
|
||||||
case TOKEN_IF:
|
case TOKEN_IF:
|
||||||
tkn_next(); parse_if(); break;
|
tkn_next(); parse_if(); break;
|
||||||
|
/*
|
||||||
case TOKEN_FOR:
|
case TOKEN_FOR:
|
||||||
tkn_next(); parse_for(); break;
|
tkn_next(); parse_for(); break;
|
||||||
case TOKEN_BREAK:
|
case TOKEN_BREAK:
|
||||||
|
|||||||
@@ -69,12 +69,19 @@ const int scope_declare_variable(const std::string name, const uint32_t type, co
|
|||||||
return address;
|
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);
|
t_scope& scope = (are_we_inside_local ? local : global);
|
||||||
|
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) {
|
for (t_variable v : scope.variables) if (v.name == name) {
|
||||||
current_var = &v;
|
current_var = &v;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
scope.h
2
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 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 uint32_t scope_get_variable_address();
|
||||||
const int scope_get_variable_size();
|
const int scope_get_variable_size();
|
||||||
const int scope_get_variable_type();
|
const int scope_get_variable_type();
|
||||||
|
|||||||
7
test.vb
7
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]
|
const perico as number = 4-peiv[1].a.x * peiv[0].c.y[2]
|
||||||
|
|
||||||
function tarari(a as number, b as number) as number
|
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
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user