diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-08-10 14:26:41 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-08-10 14:26:41 -0400 |
| commit | df7a8508c8bf075808e10b757704c2f04937f6b9 (patch) | |
| tree | 3b065c8900e486b4a75bc240d0e2871c76d1df0a /docs | |
| parent | 3b1d88ab93ddda16f1806ca3a10faae5e72ec511 (diff) | |
Move docs
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/compilation.md | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/docs/compilation.md b/docs/compilation.md new file mode 100644 index 00000000..27161115 --- /dev/null +++ b/docs/compilation.md @@ -0,0 +1,164 @@ +# Compilation Pipeline + +For a simple single-file program, the compilation process has a dependency +graph that looks like this: +``` + +----------+ transpile +------------+ generate arg parser + | foo.tm.h | <----------- | foo.tm | ------------- + +----------+ +------------+ | + | | | transpile | + | | v | + | | +------------+ | + | | | foo.tm.c | +--------------------+ + | | +------------+ | main() entry point | + | | | +--------------------+ + | | compile v | + | | +------------+ | + | +----------------->| foo.tm.o | | + | +------------+ | + | | link | + | v | + | compile +------------+ compile | + +---------------------> | foo | <------------+ + +------------+ +``` + +For a more complicated example, imagine `foo.tm` imports `baz.tm` and both are +being compiled into a shared library, `libfoo.so`: + +``` + +---------------------------------------+ + | | + +----------+ transpile +------------+ | + +- | baz.tm.h | <----------- | baz.tm | -+-------------------------+ + | +----------+ +------------+ | | + | | | | | + | | | transpile | | + | | v | | + | | +------------+ | | + | | | baz.tm.c | | | + | | +------------+ | | + | | | | | + | | | compile | | + | | v | | + | | compile +------------+ | | + | +---------------------> | baz.tm.o | | | + | +------------+ | | + | | | | + | | link | compile | + | v v | + | compile +--------------------------------------+ | + | +---------------------> | libfoo.so | | + | | +--------------------------------------+ | + | | ^ | + | | | link | + | | | | + | +----------+ transpile +------------+ | | + | | foo.tm.h | <----------- | foo.tm | | | + | +----------+ +------------+ | | + | | | | | + | | | transpile | | + | | v | | + | | +------------+ | type info | + | | | foo.tm.c | <+-------------------------+ + | | +------------+ | + | | | | + | | | compile | + | | v | + | | compile +------------+ | + +----+---------------------> | foo.tm.o | -+ + | +------------+ + | compile ^ + +-------------------------+ +``` + +These dependency graphs are relatively complicated-looking, but here are some +rough takeaways: + + 1) Header files are a dependency for many parts of the process, so it's + good to transpile them as early as possible. + 2) Once all the header files are available, + compiled into their object files in parallel. This is by far the + slowest part of compilation (invoking the C compiler), so it benefits + the most from parallelization. + 3) After all object files are compiled, the last step is to link them + all together (fast and simple). + +To sastisfy these requirements as efficiently as possible, the approach taken +below is to first transpile all header files sequentially (this could be +parallelized, but is probably faster than the overhead of forking new +processes), then fork a new process for each dependency to transpile and +compile it to an object file. Then, wait for all child processes to finish and +link the resulting object files together. + +## Phase 1 (sequential transpilation): + +``` + +--------+ +--------+ + | foo.tm | | baz.tm | + +--------+ +--------+ + | | | + +--------------+ | + | | + v v + +----------+ +----------+ + | foo.tm.h | | baz.tm.h | + +----------+ +----------+ +``` + +## Phase 2 (parallel transpilation/compilation): + +``` + ################################ ################################ + # Process 1 # # Process 2 # + # +--------+ +----------+ # # +----------+ +--------+ # + # | foo.tm | | foo.tm.h | # # | baz.tm.h | | baz.tm | # + # +--------+ | baz.tm.h | # # +----------+ +--------+ # + # | +----+-----+ # # | | # + # v | # # | v # + # +----------+ | # # | +----------+ # + # | foo.tm.c | | # # | | baz.tm.c | # + # +----------+ | # # | +----------+ # + # | | # # | | # + # +------+------+ # # +--------+ # + # | # # | # + # v # # v # + # +----------+ # # +----------+ # + # | foo.tm.o | # # | baz.tm.o | # + # +----------+ # # +----------+ # + ################################ ################################ +``` + +## Phase 3 (linking a shared object file library): + +``` + +----------+ +----------+ + | foo.tm.o | | baz.tm.o | + +----------+ +----------+ + | | + +--------+--------+ + | + v + +-----------+ + | libfoo.so | + +-----------+ +``` + +## Phase 3 (linking an executable): + +``` + +----------+ +----------+ +--------+ +--------+ + | foo.tm.o | | baz.tm.o | | foo.tm | | baz.tm | + +----------+ +----------+ +--------+ +--------+ + | | | | + +--------+--------+ +----+-----+ + | link | Figure out command line args + v v + +-----+ compile +-------------------------+ + | foo |<-------------| main() function for exe | + +-----+ +----------+--------------+ + | foo.tm.h | + +----------+ + | baz.tm.h | + +----------+ +``` |
