mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-05 22:38:44 +00:00
bytecode compiler impirsts and external functions call support, byyterun imports and external functions calls parsing, initial impl of module manager
This commit is contained in:
parent
2cd7afe0c5
commit
0a26953318
11 changed files with 409 additions and 205 deletions
14
byterun/dune
14
byterun/dune
|
|
@ -5,8 +5,20 @@
|
|||
(:main src/cli.c src/interpreter.c)
|
||||
(:parser src/parser.c)
|
||||
(:utils src/types.c)
|
||||
(:runtime ../runtime/runtime.a)
|
||||
(:module_manager module_manager.o))
|
||||
(mode
|
||||
(promote (until-clean)))
|
||||
(action
|
||||
(run gcc -Iinclude/ %{main} %{parser} %{utils} %{runtime} %{module_manager} -lstdc++ -o %{target})))
|
||||
|
||||
(rule
|
||||
(target module_manager.o)
|
||||
(deps
|
||||
(:include (source_tree include))
|
||||
(:src src/module_manager.cpp)
|
||||
(:runtime ../runtime/runtime.a))
|
||||
(mode
|
||||
(promote (until-clean)))
|
||||
(action
|
||||
(run gcc -Iinclude/ %{main} %{parser} %{utils} %{runtime} -o %{target})))
|
||||
(run g++ -Iinclude/ -c %{src} -o %{target})))
|
||||
|
|
|
|||
19
byterun/include/module_manager.h
Normal file
19
byterun/include/module_manager.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
struct ModSearchResult {
|
||||
ssize_t symbol_offset; // < 0 => not found
|
||||
uint32_t mod_id;
|
||||
bytefile *mod_file;
|
||||
};
|
||||
|
||||
void mod_add_search_path(const char *path);
|
||||
|
||||
bytefile *mod_get(uint32_t id);
|
||||
|
||||
int32_t mod_load(const char *name); // < 0 => not found
|
||||
|
||||
struct ModSearchResult mod_search_pub_symbol(const char *name);
|
||||
|
|
@ -19,8 +19,8 @@
|
|||
DEF(CMD_BINOP_AND, &&) \
|
||||
DEF(CMD_BINOP_OR, ||)
|
||||
|
||||
const char *read_cmd(char *ip);
|
||||
const char *read_cmd(const char *ip);
|
||||
|
||||
bytefile *read_file(char *fname);
|
||||
bytefile *read_file(const char *fname);
|
||||
|
||||
// void dump_file(FILE *f, bytefile *bf);
|
||||
void dump_file(FILE *f, bytefile *bf);
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ enum CMD_CTRLS {
|
|||
CMD_CTRL_ARRAY,
|
||||
CMD_CTRL_FAIL,
|
||||
CMD_CTRL_LINE,
|
||||
CMD_CTRL_CALLF,
|
||||
};
|
||||
|
||||
enum CMD_PATTS {
|
||||
|
|
|
|||
|
|
@ -10,13 +10,15 @@
|
|||
/* The unpacked representation of bytecode file */
|
||||
typedef struct {
|
||||
char *string_ptr; /* A pointer to the beginning of the string table */
|
||||
int *imports_ptr; /* A pointer to the beginning of imports table */
|
||||
int *public_ptr; /* A pointer to the beginning of publics table */
|
||||
char *code_ptr; /* A pointer to the bytecode itself */
|
||||
int *global_ptr; /* A pointer to the global area */
|
||||
int code_size; /* The size (in bytes) of code */
|
||||
uint stringtab_size; /* The size (in bytes) of the string table */
|
||||
uint global_area_size; /* The size (in words) of global area */
|
||||
uint public_symbols_number; /* The number of public symbols */
|
||||
uint imports_number; /* The number of imports */
|
||||
uint public_symbols_number; /* The number of public symbols */
|
||||
char buffer[0];
|
||||
} bytefile;
|
||||
|
||||
|
|
@ -29,15 +31,23 @@ static inline void exec_failure(const char *cmd, int line, aint offset,
|
|||
/* Gets a string from a string table by an index */
|
||||
static inline const char *get_string(const bytefile *f, size_t pos) {
|
||||
if (pos >= f->stringtab_size) {
|
||||
failure("strinpg pos is out of range: %zu >= %i\n", pos, f->stringtab_size);
|
||||
failure("string pos is out of range: %zu >= %i\n", pos, f->stringtab_size);
|
||||
}
|
||||
return &f->string_ptr[pos];
|
||||
}
|
||||
|
||||
/* Gets import */
|
||||
static inline const char *get_import(const bytefile *f, size_t i) {
|
||||
if (i >= f->imports_number) {
|
||||
failure("import pos is out of range: %zu >= %i\n", i, f->imports_number);
|
||||
}
|
||||
return get_string(f, f->imports_ptr[i]);
|
||||
}
|
||||
|
||||
/* Gets a name for a public symbol */
|
||||
static inline const char *get_public_name(const bytefile *f, size_t i) {
|
||||
if (i >= f->public_symbols_number) {
|
||||
failure("public number is out of range: %zu >= %i\n", i * 2,
|
||||
failure("public number is out of range: %zu >= %i\n", i,
|
||||
f->public_symbols_number);
|
||||
}
|
||||
return get_string(f, f->public_ptr[i * 2]);
|
||||
|
|
@ -45,8 +55,8 @@ static inline const char *get_public_name(const bytefile *f, size_t i) {
|
|||
|
||||
/* Gets an offset for a publie symbol */
|
||||
static inline size_t get_public_offset(const bytefile *f, size_t i) {
|
||||
if (i + 1 >= f->public_symbols_number) {
|
||||
failure("public number is out of range: %zu >= %i\n", i * 2 + 1,
|
||||
if (i >= f->public_symbols_number) {
|
||||
failure("public number is out of range: %zu >= %i\n", i,
|
||||
f->public_symbols_number);
|
||||
}
|
||||
return f->public_ptr[i * 2 + 1];
|
||||
|
|
|
|||
|
|
@ -4,15 +4,18 @@
|
|||
#include "../../runtime/runtime.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
failure("no file name provided");
|
||||
if (argc < 3) {
|
||||
failure("two arguments should be provided: execution option (-i/-p) and file name\n");
|
||||
}
|
||||
|
||||
bytefile *f = read_file(argv[1]);
|
||||
// #ifdef DEBUG_VERSION
|
||||
// dump_file (stdout, f);
|
||||
// #endif
|
||||
run(f, argc - 1, argv + 1);
|
||||
bytefile *f = read_file(argv[2]);
|
||||
if (strcmp(argv[1], "-i") == 0) {
|
||||
run(f, argc - 1, argv + 1);
|
||||
} else if (strcmp(argv[1], "-p") == 0) {
|
||||
dump_file (stdout, f);
|
||||
} else {
|
||||
failure("undefined execution mode. Execution mode should be -i (interpret) or -p (print)\n");
|
||||
}
|
||||
|
||||
free(f->global_ptr);
|
||||
free(f);
|
||||
|
|
|
|||
|
|
@ -369,6 +369,23 @@ void run(bytefile *bf, int argc, char **argv) {
|
|||
// maybe some metainfo should be collected
|
||||
break;
|
||||
|
||||
case CMD_CTRL_CALLF: { // CALLF %s %d // call external function
|
||||
const char* call_func = ip_read_string(&s.ip);
|
||||
ip_read_int(&s.ip); // args count
|
||||
|
||||
// TODO: jump to other module, save ret module
|
||||
|
||||
// call_happened = true;
|
||||
// s.is_closure_call = false;
|
||||
// s.call_ip = s.ip;
|
||||
|
||||
// if (call_p >= bf->code_size) {
|
||||
// s_failure(&s, "jump out of file");
|
||||
// }
|
||||
// s.ip = bf->code_ptr + call_p;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
s_failure(&s, "invalid opcode"); // %d-%d\n", h, l);
|
||||
}
|
||||
|
|
|
|||
100
byterun/src/module_manager.cpp
Normal file
100
byterun/src/module_manager.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
extern "C" {
|
||||
#include "module_manager.h"
|
||||
#include "parser.h"
|
||||
#include "utils.h"
|
||||
}
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct ModSymbolPos {
|
||||
uint32_t mod_id;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
struct ModuleManager {
|
||||
std::unordered_map<std::string, uint32_t> loaded_modules;
|
||||
std::unordered_map<std::string, ModSymbolPos> public_symbols_mods;
|
||||
std::vector<bytefile *> modules;
|
||||
std::vector<std::filesystem::path> search_paths;
|
||||
};
|
||||
|
||||
static ModuleManager manager;
|
||||
|
||||
uint32_t path_mod_load(const char *name, std::filesystem::path &&path) {
|
||||
bytefile *module = read_file(path.c_str());
|
||||
uint32_t id = manager.modules.size();
|
||||
manager.modules.push_back(module);
|
||||
for (size_t i = 0; i < module->public_symbols_number; ++i) {
|
||||
if (!manager.public_symbols_mods
|
||||
.insert({
|
||||
get_public_name(module, i),
|
||||
{.mod_id = id, .offset = get_public_offset(module, i)},
|
||||
})
|
||||
.second) {
|
||||
failure("public symbol loaded more then once\n");
|
||||
}
|
||||
}
|
||||
manager.loaded_modules.insert({name, id});
|
||||
return id;
|
||||
}
|
||||
extern "C" {
|
||||
|
||||
void mod_add_search_path(const char *path) {
|
||||
manager.search_paths.emplace_back(path);
|
||||
}
|
||||
|
||||
bytefile *mod_get(uint32_t id) {
|
||||
if (id > manager.modules.size()) {
|
||||
failure("module id is out of range\n");
|
||||
}
|
||||
return manager.modules[id];
|
||||
}
|
||||
|
||||
int32_t find_mod_loaded(const char *name) {
|
||||
auto it = manager.loaded_modules.find(name);
|
||||
|
||||
// module already loaded
|
||||
if (it != manager.loaded_modules.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t mod_load(const char *name) {
|
||||
auto it = manager.loaded_modules.find(name);
|
||||
|
||||
// module already loaded
|
||||
if (it != manager.loaded_modules.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(name)) {
|
||||
return path_mod_load(name, name);
|
||||
}
|
||||
for (const auto &dir_path : manager.search_paths) {
|
||||
auto path = dir_path / name;
|
||||
if (std::filesystem::exists(path)) {
|
||||
return path_mod_load(name, std::move(path));
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ModSearchResult mod_search_pub_symbol(const char *name) {
|
||||
auto it = manager.public_symbols_mods.find(name);
|
||||
if (it == manager.public_symbols_mods.end()) {
|
||||
return {.symbol_offset = -1, .mod_id = 0, .mod_file = nullptr};
|
||||
}
|
||||
|
||||
return {
|
||||
.symbol_offset = (int32_t)it->second.offset,
|
||||
.mod_id = it->second.mod_id,
|
||||
.mod_file = mod_get(it->second.mod_id),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ void *__start_custom_data;
|
|||
void *__stop_custom_data;
|
||||
|
||||
/* Reads a binary bytecode file by name and unpacks it */
|
||||
bytefile* read_file (char *fname) {
|
||||
bytefile* read_file (const char *fname) {
|
||||
FILE *f = fopen (fname, "rb");
|
||||
bytefile *file;
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ bytefile* read_file (char *fname) {
|
|||
}
|
||||
|
||||
long size = ftell (f);
|
||||
long additional_size = sizeof(void*) * 4 + sizeof(int);
|
||||
long additional_size = sizeof(void*) * 5 + sizeof(int);
|
||||
file = (bytefile*) malloc (size + additional_size); // file itself + additional data
|
||||
|
||||
char* file_begin = (char*)file + additional_size;
|
||||
|
|
@ -45,11 +45,13 @@ bytefile* read_file (char *fname) {
|
|||
|
||||
fclose (f);
|
||||
|
||||
long imports_size = file->imports_number * sizeof(int);
|
||||
long public_symbols_size = file->public_symbols_number * 2 * sizeof(int);
|
||||
if (file->buffer + public_symbols_size >= file_end) {
|
||||
long strings_buffer_offset = public_symbols_size + imports_size;
|
||||
if (file->buffer + strings_buffer_offset >= file_end) {
|
||||
failure ("public symbols are out of the file size\n");
|
||||
}
|
||||
file->string_ptr = &file->buffer[public_symbols_size];
|
||||
file->string_ptr = &file->buffer[strings_buffer_offset];
|
||||
if (file->string_ptr + file->stringtab_size > file_end) {
|
||||
failure ("strings table is out of the file size\n");
|
||||
}
|
||||
|
|
@ -60,16 +62,17 @@ bytefile* read_file (char *fname) {
|
|||
failure ("file zones sizes should be >= 0\n");
|
||||
}
|
||||
|
||||
file->public_ptr = (int*) file->buffer;
|
||||
file->imports_ptr = (int*) file->buffer;
|
||||
file->public_ptr = (int*) (file->buffer + imports_size);
|
||||
file->code_ptr = &file->string_ptr [file->stringtab_size];
|
||||
file->global_ptr = (int*) calloc (file->global_area_size, sizeof (int));
|
||||
|
||||
file->code_size = size - public_symbols_size - file->stringtab_size;
|
||||
file->code_size = size - strings_buffer_offset - file->stringtab_size;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
const char *read_cmd(char *ip) {
|
||||
const char *read_cmd(const char *ip) {
|
||||
uint8_t x = (*ip++), h = (x & 0xF0) >> 4, l = x & 0x0F;
|
||||
|
||||
switch (h) {
|
||||
|
|
@ -138,6 +141,8 @@ const char *read_cmd(char *ip) {
|
|||
return "FAIL";
|
||||
case CMD_CTRL_LINE:
|
||||
return "LINE";
|
||||
case CMD_CTRL_CALLF:
|
||||
return "CALL";
|
||||
default:
|
||||
return "_UNDEF_CMD5_";
|
||||
}
|
||||
|
|
@ -164,225 +169,236 @@ const char *read_cmd(char *ip) {
|
|||
}
|
||||
}
|
||||
|
||||
// /* Disassembles the bytecode pool */
|
||||
// void disassemble (FILE *f, bytefile *bf) {
|
||||
/* Disassembles the bytecode pool */
|
||||
void disassemble (FILE *f, bytefile *bf) {
|
||||
|
||||
// # define INT (ip += sizeof (int), *(int*)(ip - sizeof (int)))
|
||||
// # define BYTE *ip++
|
||||
// # define STRING get_string (bf, INT)
|
||||
// # define FAIL failure ("ERROR: invalid opcode %d-%d\n", h, l)
|
||||
# define INT (ip += sizeof (int), *(int*)(ip - sizeof (int)))
|
||||
# define BYTE *ip++
|
||||
# define STRING get_string (bf, INT)
|
||||
# define FAIL failure ("ERROR: invalid opcode %d-%d\n", h, l)
|
||||
|
||||
// char *ip = bf->code_ptr;
|
||||
// char *ops [] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"};
|
||||
// char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"};
|
||||
// char *lds [] = {"LD", "LDA", "ST"};
|
||||
// do {
|
||||
// uint8_t x = BYTE,
|
||||
// h = (x & 0xF0) >> 4,
|
||||
// l = x & 0x0F;
|
||||
char *ip = bf->code_ptr;
|
||||
char *ops [] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"};
|
||||
char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"};
|
||||
char *lds [] = {"LD", "LDA", "ST"};
|
||||
do {
|
||||
uint8_t x = BYTE,
|
||||
h = (x & 0xF0) >> 4,
|
||||
l = x & 0x0F;
|
||||
|
||||
// fprintf (f, "0x%.8x:\t", ip-bf->code_ptr-1);
|
||||
fprintf (f, "0x%.8x:\t", ip-bf->code_ptr-1);
|
||||
|
||||
// switch (h) {
|
||||
// case 15:
|
||||
// goto stop;
|
||||
switch (h) {
|
||||
case 15:
|
||||
goto stop;
|
||||
|
||||
// /* BINOP */
|
||||
// case 0:
|
||||
// fprintf (f, "BINOP\t%s", ops[l-1]);
|
||||
// break;
|
||||
/* BINOP */
|
||||
case 0:
|
||||
fprintf (f, "BINOP\t%s", ops[l-1]);
|
||||
break;
|
||||
|
||||
// case 1:
|
||||
// switch (l) {
|
||||
// case 0:
|
||||
// fprintf (f, "CONST\t%d", INT);
|
||||
// break;
|
||||
case 1:
|
||||
switch (l) {
|
||||
case 0:
|
||||
fprintf (f, "CONST\t%d", INT);
|
||||
break;
|
||||
|
||||
// case 1:
|
||||
// fprintf (f, "STRING\t%s", STRING);
|
||||
// break;
|
||||
case 1:
|
||||
fprintf (f, "STRING\t%s", STRING);
|
||||
break;
|
||||
|
||||
// case 2:
|
||||
// fprintf (f, "SEXP\t%s ", STRING);
|
||||
// fprintf (f, "%d", INT);
|
||||
// break;
|
||||
case 2:
|
||||
fprintf (f, "SEXP\t%s ", STRING);
|
||||
fprintf (f, "%d", INT);
|
||||
break;
|
||||
|
||||
// case 3:
|
||||
// fprintf (f, "STI");
|
||||
// break;
|
||||
case 3:
|
||||
fprintf (f, "STI");
|
||||
break;
|
||||
|
||||
// case 4:
|
||||
// fprintf (f, "STA");
|
||||
// break;
|
||||
case 4:
|
||||
fprintf (f, "STA");
|
||||
break;
|
||||
|
||||
// case 5:
|
||||
// fprintf (f, "JMP\t0x%.8x", INT);
|
||||
// break;
|
||||
case 5:
|
||||
fprintf (f, "JMP\t0x%.8x", INT);
|
||||
break;
|
||||
|
||||
// case 6:
|
||||
// fprintf (f, "END");
|
||||
// break;
|
||||
case 6:
|
||||
fprintf (f, "END");
|
||||
break;
|
||||
|
||||
// case 7:
|
||||
// fprintf (f, "RET");
|
||||
// break;
|
||||
case 7:
|
||||
fprintf (f, "RET");
|
||||
break;
|
||||
|
||||
// case 8:
|
||||
// fprintf (f, "DROP");
|
||||
// break;
|
||||
case 8:
|
||||
fprintf (f, "DROP");
|
||||
break;
|
||||
|
||||
// case 9:
|
||||
// fprintf (f, "DUP");
|
||||
// break;
|
||||
case 9:
|
||||
fprintf (f, "DUP");
|
||||
break;
|
||||
|
||||
// case 10:
|
||||
// fprintf (f, "SWAP");
|
||||
// break;
|
||||
case 10:
|
||||
fprintf (f, "SWAP");
|
||||
break;
|
||||
|
||||
// case 11:
|
||||
// fprintf (f, "ELEM");
|
||||
// break;
|
||||
case 11:
|
||||
fprintf (f, "ELEM");
|
||||
break;
|
||||
|
||||
// default:
|
||||
// FAIL;
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
// case 2:
|
||||
// case 3:
|
||||
// case 4:
|
||||
// fprintf (f, "%s\t", lds[h-2]);
|
||||
// switch (l) {
|
||||
// case 0: fprintf (f, "G(%d)", INT); break;
|
||||
// case 1: fprintf (f, "L(%d)", INT); break;
|
||||
// case 2: fprintf (f, "A(%d)", INT); break;
|
||||
// case 3: fprintf (f, "C(%d)", INT); break;
|
||||
// default: FAIL;
|
||||
// }
|
||||
// break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
fprintf (f, "%s\t", lds[h-2]);
|
||||
switch (l) {
|
||||
case 0: fprintf (f, "G(%d)", INT); break;
|
||||
case 1: fprintf (f, "L(%d)", INT); break;
|
||||
case 2: fprintf (f, "A(%d)", INT); break;
|
||||
case 3: fprintf (f, "C(%d)", INT); break;
|
||||
default: FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
// case 5:
|
||||
// switch (l) {
|
||||
// case 0:
|
||||
// fprintf (f, "CJMPz\t0x%.8x", INT);
|
||||
// break;
|
||||
case 5:
|
||||
switch (l) {
|
||||
case 0:
|
||||
fprintf (f, "CJMPz\t0x%.8x", INT);
|
||||
break;
|
||||
|
||||
// case 1:
|
||||
// fprintf (f, "CJMPnz\t0x%.8x", INT);
|
||||
// break;
|
||||
case 1:
|
||||
fprintf (f, "CJMPnz\t0x%.8x", INT);
|
||||
break;
|
||||
|
||||
// case 2:
|
||||
// fprintf (f, "BEGIN\t%d ", INT);
|
||||
// fprintf (f, "%d", INT);
|
||||
// break;
|
||||
case 2:
|
||||
fprintf (f, "BEGIN\t%d ", INT);
|
||||
fprintf (f, "%d", INT);
|
||||
break;
|
||||
|
||||
// case 3:
|
||||
// fprintf (f, "CBEGIN\t%d ", INT);
|
||||
// fprintf (f, "%d", INT);
|
||||
// break;
|
||||
case 3:
|
||||
fprintf (f, "CBEGIN\t%d ", INT);
|
||||
fprintf (f, "%d", INT);
|
||||
break;
|
||||
|
||||
// case 4:
|
||||
// fprintf (f, "CLOSURE\t0x%.8x", INT);
|
||||
// {int n = INT;
|
||||
// for (int i = 0; i<n; i++) {
|
||||
// switch (BYTE) {
|
||||
// case 0: fprintf (f, "G(%d)", INT); break;
|
||||
// case 1: fprintf (f, "L(%d)", INT); break;
|
||||
// case 2: fprintf (f, "A(%d)", INT); break;
|
||||
// case 3: fprintf (f, "C(%d)", INT); break;
|
||||
// default: FAIL;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// break;
|
||||
case 4:
|
||||
fprintf (f, "CLOSURE\t0x%.8x", INT);
|
||||
{int n = INT;
|
||||
for (int i = 0; i<n; i++) {
|
||||
switch (BYTE) {
|
||||
case 0: fprintf (f, "G(%d)", INT); break;
|
||||
case 1: fprintf (f, "L(%d)", INT); break;
|
||||
case 2: fprintf (f, "A(%d)", INT); break;
|
||||
case 3: fprintf (f, "C(%d)", INT); break;
|
||||
default: FAIL;
|
||||
}
|
||||
}
|
||||
};
|
||||
break;
|
||||
|
||||
// case 5:
|
||||
// fprintf (f, "CALLC\t%d", INT);
|
||||
// break;
|
||||
case 5:
|
||||
fprintf (f, "CALLC\t%d", INT);
|
||||
break;
|
||||
|
||||
// case 6:
|
||||
// fprintf (f, "CALL\t0x%.8x ", INT);
|
||||
// fprintf (f, "%d", INT);
|
||||
// break;
|
||||
case 6:
|
||||
fprintf (f, "CALL\t0x%.8x ", INT);
|
||||
fprintf (f, "%d", INT);
|
||||
break;
|
||||
|
||||
// case 7:
|
||||
// fprintf (f, "TAG\t%s ", STRING);
|
||||
// fprintf (f, "%d", INT);
|
||||
// break;
|
||||
case 7:
|
||||
fprintf (f, "TAG\t%s ", STRING);
|
||||
fprintf (f, "%d", INT);
|
||||
break;
|
||||
|
||||
// case 8:
|
||||
// fprintf (f, "ARRAY\t%d", INT);
|
||||
// break;
|
||||
case 8:
|
||||
fprintf (f, "ARRAY\t%d", INT);
|
||||
break;
|
||||
|
||||
// case 9:
|
||||
// fprintf (f, "FAIL\t%d", INT);
|
||||
// fprintf (f, "%d", INT);
|
||||
// break;
|
||||
case 9:
|
||||
fprintf (f, "FAIL\t%d", INT);
|
||||
fprintf (f, "%d", INT);
|
||||
break;
|
||||
|
||||
// case 10:
|
||||
// fprintf (f, "LINE\t%d", INT);
|
||||
// break;
|
||||
case 10:
|
||||
fprintf (f, "LINE\t%d", INT);
|
||||
break;
|
||||
|
||||
// default:
|
||||
// FAIL;
|
||||
// }
|
||||
// break;
|
||||
case 11:
|
||||
fprintf (f, "CALLF\t%s ", STRING);
|
||||
fprintf (f, "%d", INT);
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
// case 6:
|
||||
// fprintf (f, "PATT\t%s", pats[l]);
|
||||
// break;
|
||||
case 6:
|
||||
fprintf (f, "PATT\t%s", pats[l]);
|
||||
break;
|
||||
|
||||
// case 7: {
|
||||
// switch (l) {
|
||||
// case 0:
|
||||
// fprintf (f, "CALL\tLread");
|
||||
// break;
|
||||
case 7: {
|
||||
switch (l) {
|
||||
case 0:
|
||||
fprintf (f, "CALL\tLread");
|
||||
break;
|
||||
|
||||
// case 1:
|
||||
// fprintf (f, "CALL\tLwrite");
|
||||
// break;
|
||||
case 1:
|
||||
fprintf (f, "CALL\tLwrite");
|
||||
break;
|
||||
|
||||
// case 2:
|
||||
// fprintf (f, "CALL\tLlength");
|
||||
// break;
|
||||
case 2:
|
||||
fprintf (f, "CALL\tLlength");
|
||||
break;
|
||||
|
||||
// case 3:
|
||||
// fprintf (f, "CALL\tLstring");
|
||||
// break;
|
||||
case 3:
|
||||
fprintf (f, "CALL\tLstring");
|
||||
break;
|
||||
|
||||
// case 4:
|
||||
// fprintf (f, "CALL\tBarray\t%d", INT);
|
||||
// break;
|
||||
case 4:
|
||||
fprintf (f, "CALL\tBarray\t%d", INT);
|
||||
break;
|
||||
|
||||
// default:
|
||||
// FAIL;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
FAIL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// default:
|
||||
// FAIL;
|
||||
// }
|
||||
default:
|
||||
FAIL;
|
||||
}
|
||||
|
||||
// fprintf (f, "\n");
|
||||
// }
|
||||
// while (1);
|
||||
// stop: fprintf (f, "<end>\n");
|
||||
// }
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
while (1);
|
||||
stop: fprintf (f, "<end>\n");
|
||||
}
|
||||
|
||||
// /* Dumps the contents of the file */
|
||||
// void dump_file (FILE *f, bytefile *bf) {
|
||||
// size_t i;
|
||||
/* Dumps the contents of the file */
|
||||
void dump_file (FILE *f, bytefile *bf) {
|
||||
size_t i;
|
||||
|
||||
// fprintf (f, "String table size : %d\n", bf->stringtab_size);
|
||||
// fprintf (f, "Global area size : %d\n", bf->global_area_size);
|
||||
// fprintf (f, "Number of public symbols: %d\n", bf->public_symbols_number);
|
||||
// fprintf (f, "Public symbols :\n");
|
||||
fprintf (f, "String table size : %d\n", bf->stringtab_size);
|
||||
fprintf (f, "Global area size : %d\n", bf->global_area_size);
|
||||
fprintf (f, "Number of imports : %d\n", bf->imports_number);
|
||||
fprintf (f, "Number of public symbols: %d\n", bf->public_symbols_number);
|
||||
fprintf (f, "Imports :\n");
|
||||
|
||||
// for (i=0; i < bf->public_symbols_number; i++)
|
||||
// fprintf (f, " 0x%.8x: %s\n", get_public_offset (bf, i), get_public_name (bf, i));
|
||||
for (i=0; i < bf->imports_number; i++)
|
||||
fprintf (f, " %s\n", get_import (bf, i));
|
||||
|
||||
// fprintf (f, "Code:\n");
|
||||
// disassemble (f, bf);
|
||||
// }
|
||||
fprintf (f, "Public symbols :\n");
|
||||
|
||||
for (i=0; i < bf->public_symbols_number; i++)
|
||||
fprintf (f, " 0x%.8x: %s\n", get_public_offset (bf, i), get_public_name (bf, i));
|
||||
|
||||
fprintf (f, "Code:\n");
|
||||
disassemble (f, bf);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,4 +28,4 @@ fun generate (n) {
|
|||
if n then n : generate (n-1) else {} fi
|
||||
}
|
||||
|
||||
bubbleSort (generate (1000))
|
||||
bubbleSort (generate (1000))
|
||||
|
|
|
|||
34
src/SM.ml
34
src/SM.ml
|
|
@ -172,15 +172,19 @@ module ByteCode = struct
|
|||
let code = Buffer.create 256 in
|
||||
let st = StringTab.create () in
|
||||
let lmap = Stdlib.ref M.empty in
|
||||
let externs = Stdlib.ref S.empty in
|
||||
let pubs = Stdlib.ref S.empty in
|
||||
let imports = Stdlib.ref S.empty in
|
||||
let globals = Stdlib.ref M.empty in
|
||||
let glob_count = Stdlib.ref 0 in
|
||||
let fixups = Stdlib.ref [] in
|
||||
let func_fixups = Stdlib.ref [] in
|
||||
let add_lab l = lmap := M.add l (Buffer.length code) !lmap in
|
||||
let add_extern l = externs := S.add l !externs in
|
||||
let add_public l = pubs := S.add l !pubs in
|
||||
let add_import l = imports := S.add l !imports in
|
||||
let add_fixup l = fixups := (Buffer.length code, l) :: !fixups in
|
||||
let add_func_fixup c l = func_fixups := (c, Buffer.length code, l) :: !func_fixups in
|
||||
let add_bytes = List.iter (fun x -> Buffer.add_char code @@ Char.chr x) in
|
||||
let add_ints =
|
||||
List.iter (fun x -> Buffer.add_int32_ne code @@ Int32.of_int x)
|
||||
|
|
@ -302,9 +306,10 @@ module ByteCode = struct
|
|||
add_ints [ n ]
|
||||
(* 0x56 l:32 n:32 *)
|
||||
| CALL (fn, n, _) ->
|
||||
add_bytes [ (5 * 16) + 6 ];
|
||||
add_fixup fn;
|
||||
add_ints [ 0; n ]
|
||||
(add_bytes [ (5 * 16) + 6 ];
|
||||
(* TODO: 1 -> sizeof byte ?? *)
|
||||
add_func_fixup (Buffer.length code - 1) fn;
|
||||
add_ints [ 0; n ])
|
||||
(* 0x57 s:32 n:32 *)
|
||||
| TAG (s, n) ->
|
||||
add_bytes [ (5 * 16) + 7 ];
|
||||
|
|
@ -324,9 +329,11 @@ module ByteCode = struct
|
|||
add_ints [ n ]
|
||||
(* 0x6p *)
|
||||
| PATT p -> add_bytes [ (6 * 16) + enum patt p ]
|
||||
| EXTERN _ -> ()
|
||||
| EXTERN s -> add_extern s
|
||||
(* TODO: put externs in string table (?), or check that all external funtions are externs *)
|
||||
| PUBLIC s -> add_public s
|
||||
| IMPORT s -> add_import s
|
||||
(* TODO: add imports table before publics *)
|
||||
| _ ->
|
||||
failwith
|
||||
(Printf.sprintf "Unexpected pattern: %s: %d" __FILE__ __LINE__)
|
||||
|
|
@ -334,6 +341,15 @@ module ByteCode = struct
|
|||
List.iter insn_code insns;
|
||||
add_bytes [ 255 ];
|
||||
let code = Buffer.to_bytes code in
|
||||
List.iter
|
||||
(fun (cmd_ofs, addr_ofs, l) ->
|
||||
Bytes.set_int32_ne code addr_ofs
|
||||
(Int32.of_int
|
||||
@@
|
||||
try M.find l !lmap
|
||||
with Not_found ->
|
||||
Bytes.set_int8 code cmd_ofs ((5 * 16) + 11); StringTab.add st l))
|
||||
!func_fixups;
|
||||
List.iter
|
||||
(fun (ofs, l) ->
|
||||
Bytes.set_int32_ne code ofs
|
||||
|
|
@ -343,6 +359,11 @@ module ByteCode = struct
|
|||
with Not_found ->
|
||||
failwith (Printf.sprintf "ERROR: undefined label '%s'" l)))
|
||||
!fixups;
|
||||
let imports = (* TODO: check *)
|
||||
List.map (fun l ->
|
||||
(Int32.of_int @@ StringTab.add st l))
|
||||
@@ S.elements !imports
|
||||
in
|
||||
let pubs =
|
||||
List.map (fun l ->
|
||||
( Int32.of_int @@ StringTab.add st l,
|
||||
|
|
@ -357,7 +378,12 @@ module ByteCode = struct
|
|||
let file = Buffer.create 1024 in
|
||||
Buffer.add_int32_ne file (Int32.of_int @@ Bytes.length st);
|
||||
Buffer.add_int32_ne file (Int32.of_int @@ !glob_count);
|
||||
Buffer.add_int32_ne file (Int32.of_int @@ List.length imports);
|
||||
Buffer.add_int32_ne file (Int32.of_int @@ List.length pubs);
|
||||
List.iter
|
||||
(fun (n) ->
|
||||
Buffer.add_int32_ne file n)
|
||||
imports;
|
||||
List.iter
|
||||
(fun (n, o) ->
|
||||
Buffer.add_int32_ne file n;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue