[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:
2021-05-05 15:16:57 +02:00
parent 8b101e4d3c
commit 287bf565bd
6 changed files with 108 additions and 114 deletions

View File

@@ -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

View File

@@ -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];

View File

@@ -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:

View File

@@ -69,11 +69,18 @@ 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);
for (t_variable v : scope.variables) if (v.name == name) { if (are_we_inside_local && can_shadow) {
current_var = &v; for (int i = blocks.top(); i < scope.variables.size(); i++ ) if (scope.variables[i].name == name) {
return true; 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; return false;
} }

View File

@@ -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();

View File

@@ -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