From 71e4f3812982dba2efb471283d310224e8db363e Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Wed, 3 Mar 2021 22:09:50 -0800 Subject: 7842 - new directory organization Baremetal is now the default build target and therefore has its sources at the top-level. Baremetal programs build using the phase-2 Mu toolchain that requires a Linux kernel. This phase-2 codebase which used to be at the top-level is now under the linux/ directory. Finally, the phase-2 toolchain, while self-hosting, has a way to bootstrap from a C implementation, which is now stored in linux/bootstrap. The bootstrap C implementation uses some literate programming tools that are now in linux/bootstrap/tools. So the whole thing has gotten inverted. Each directory should build one artifact and include the main sources (along with standard library). Tools used for building it are relegated to sub-directories, even though those tools are often useful in their own right, and have had lots of interesting programs written using them. A couple of things have gotten dropped in this process: - I had old ways to run on just a Linux kernel, or with a Soso kernel. No more. - I had some old tooling for running a single test at the cursor. I haven't used that lately. Maybe I'll bring it back one day. The reorg isn't done yet. Still to do: - redo documentation everywhere. All the README files, all other markdown, particularly vocabulary.md. - clean up how-to-run comments at the start of programs everywhere - rethink what to do with the html/ directory. Do we even want to keep supporting it? In spite of these shortcomings, all the scripts at the top-level, linux/ and linux/bootstrap are working. The names of the scripts also feel reasonable. This is a good milestone to take stock at. --- linux/bootstrap/040tests.cc | 95 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 linux/bootstrap/040tests.cc (limited to 'linux/bootstrap/040tests.cc') diff --git a/linux/bootstrap/040tests.cc b/linux/bootstrap/040tests.cc new file mode 100644 index 00000000..0586249b --- /dev/null +++ b/linux/bootstrap/040tests.cc @@ -0,0 +1,95 @@ +//: Automatically aggregate functions starting with 'test-' into a test suite +//: called 'run-tests'. Running this function will run all tests. +//: +//: This is actually SubX's first (trivial) compiler. We generate all the code +//: needed for the 'run-tests' function. +//: +//: By convention, temporary functions needed by tests will start with +//: '_test-'. + +//: We don't rely on any transforms running in previous layers, but this layer +//: knows about labels and will emit labels for previous layers to transform. +:(after "Begin Transforms") +Transform.push_back(create_test_function); + +:(code) +void test_run_test() { + Mem.push_back(vma(0xbd000000)); // manually allocate memory + Reg[ESP].u = 0xbd000100; + run( + "== code 0x1\n" // code segment + "main:\n" + " e8/call run-tests/disp32\n" // 5 bytes + " f4/halt\n" // 1 byte + "test-foo:\n" // offset 7 + " 01 d8\n" // just some unique instruction: add EBX to EAX + " c3/return\n" + ); + // check that code in test-foo ran (implicitly called by run-tests) + CHECK_TRACE_CONTENTS( + "run: 0x00000007 opcode: 01\n" + ); +} + +void create_test_function(program& p) { + if (p.segments.empty()) return; + segment& code = *find(p, "code"); + trace(3, "transform") << "-- create 'run-tests'" << end(); + vector new_insts; + for (int i = 0; i < SIZE(code.lines); ++i) { + line& inst = code.lines.at(i); + for (int j = 0; j < SIZE(inst.words); ++j) { + const word& curr = inst.words.at(j); + if (*curr.data.rbegin() != ':') continue; // not a label + if (!starts_with(curr.data, "test-")) continue; + string fn = drop_last(curr.data); + new_insts.push_back(call(fn)); + } + } + if (new_insts.empty()) return; // no tests found + code.lines.push_back(label("run-tests")); + code.lines.insert(code.lines.end(), new_insts.begin(), new_insts.end()); + code.lines.push_back(ret()); +} + +string to_string(const segment& s) { + ostringstream out; + for (int i = 0; i < SIZE(s.lines); ++i) { + const line& l = s.lines.at(i); + for (int j = 0; j < SIZE(l.words); ++j) { + if (j > 0) out << ' '; + out << to_string(l.words.at(j)); + } + out << '\n'; + } + return out.str(); +} + +line call(string s) { + line result; + result.words.push_back(call()); + result.words.push_back(disp32(s)); + return result; +} + +word call() { + word result; + result.data = "e8"; + result.metadata.push_back("call"); + return result; +} + +word disp32(string s) { + word result; + result.data = s; + result.metadata.push_back("disp32"); + return result; +} + +line ret() { + line result; + result.words.push_back(word()); + result.words.back().data = "c3"; + result.words.back().metadata.push_back("return"); + return result; +} -- cgit 1.4.1-2-gfad0