From b20d9ad3030729c57da73ec2c321795907d11b7a Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 30 Jun 2018 22:46:32 -0700 Subject: 4298 - framework for translating SubX programs --- subx/010core.cc | 6 +++--- subx/021translate.cc | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/subx/010core.cc b/subx/010core.cc index 90359162..b21511d7 100644 --- a/subx/010core.cc +++ b/subx/010core.cc @@ -99,7 +99,7 @@ End_of_program = 0; // helper for tests: load a program into memory from a textual representation // of its bytes, and run it void run(const string& text_bytes) { - load_program(text_bytes); + load_program(text_bytes, 1); // tests always assume a starting address of 1 EIP = 1; // preserve null pointer while (EIP < End_of_program) run_one_instruction(); @@ -151,9 +151,9 @@ void run_one_instruction() { } } -void load_program(const string& text_bytes) { +void load_program(const string& text_bytes, uint32_t addr) { istringstream in(text_bytes); - load_program(in, 1); + load_program(in, addr); } void load_program(istream& in, uint32_t addr) { in >> std::noskipws; diff --git a/subx/021translate.cc b/subx/021translate.cc index 94553ae9..f262bcd6 100644 --- a/subx/021translate.cc +++ b/subx/021translate.cc @@ -1,18 +1,45 @@ +//: Beginnings of a nicer way to build SubX programs. +//: We're going to question every notion, including "Assembly language" and +//: "compiler". +//: Motto: Abstract nothing, check everything. +//: +//: Workflow: read 'source' file as a single string. Run a series of +//: transforms on it, each converting to a new string. The final string should +//: be just machine code and comments, suitable to pass to load_program(). + +:(before "End Types") +typedef void (*transform_fn)(const string& input, string& output); +:(before "End Globals") +vector Transform; + :(before "End Includes") const int START = 0x08048000; :(before "End Main") if (is_equal(argv[1], "translate")) { assert(argc > 3); - ifstream in(argv[2]); - Mem.resize(1024); - load_program(in, 1); // since we're not going to run it right now, we can load it anywhere - dump_elf(argv[3]); + string program; + slurp(argv[2], program); + perform_all_transforms(program); + dump_elf(program, argv[3]); } :(code) +void perform_all_transforms(string& program) { + string& in = program; + string out; + for (int t = 0; t < SIZE(Transform); ++t, in.swap(out), out.clear()) + (*Transform.at(t))(in, out); +} + // write out the current Memory contents from address 1 to End_of_program to a // bare-bones ELF file with a single section/segment and a hard-coded origin address. -void dump_elf(const char* filename) { +void dump_elf(const string& program, const char* filename) { + Mem.resize(1024); + // load program into memory, filtering out comments + load_program(program, 1); // Not where 'program' should be loaded for running. + // But we're not going to run it right now, so we + // can load it anywhere. + // dump contents of memory into ELF binary ofstream out(filename, ios::binary); dump_elf_header(out); for (size_t i = 1; i < End_of_program; ++i) { @@ -93,5 +120,17 @@ void dump_elf_header(ostream& out) { #undef O } +void slurp(const char* filename, string& out) { + ifstream fin(filename); + fin >> std::noskipws; + ostringstream fout; + char c = '\0'; + while(has_data(fin)) { + fin >> c; + fout << c; + } + fout.str().swap(out); +} + :(before "End Includes") using std::ios; -- cgit 1.4.1-2-gfad0