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

View File

@@ -4,10 +4,22 @@
#include <string.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
#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];

View File

@@ -8,7 +8,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <stack>
#include <vector>
#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<t_label> known_labels;
//static int num_known_labels = 0;
static t_label unknown_labels[MAX_LABELS];
static int num_unknown_labels = 0;
static std::vector<t_label> 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:

View File

@@ -69,12 +69,19 @@ 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);
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;
}

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

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