diff --git a/web/index.html b/web/index.html index 1b77603..3ac93c3 100644 --- a/web/index.html +++ b/web/index.html @@ -328,17 +328,30 @@ $ ./_build/default/bin/main.exe run calc-me.flan "1 + 2 * (3 - 0.5) / 2"
$ flan
usage: flan (read|parse|check|emit|shim) <file.flan>...
+ flan emit <file.flan> [--x86] [--dev] [--debug] [--no-bounds-checks]
flan import-c <header.h> [package.flan...] [clang flags...]
flan generate-c <package-dir>
flan build <file.flan> [-o out] [--no-bounds-checks] [--dev] [--debug] [--sanitize] [--x86] [--target=wasm32-wasi|web]
flan run <file.flan> [args...]
- flan reload <program.flan> <forms.flan> [-o out.so]
- flan dev <program.flan> [-s socket]
+ flan reload <program.flan> <forms.flan> [-o out.so] [--x86]
+ flan dev <program.flan> [-s socket] [--x86]
read, parse, check, emit and
shim each stop the pipeline one stage further along and print what it
produced. run builds to a temporary file and execs it.
flan emit --x86 prints the hand-written backend's assembly where plain
+emit prints LLVM IR, and it is annotated: each run of bytes is
+headed by the Flan form that produced it and its source position, and each function by a
+map of its frame saying which displacement is which parameter, which is a named local,
+and below which offset everything is a reusable temporary. Reading a listing of this
+backend without that map is reading -0x20(%rbp) with no key. The comments
+cost nothing in the object — the assembler discards them — but they are
+emitted only by emit, never by a build, so the assembly a build hands to
+clang is the same text it always was. spike/x86/dump.sh puts all
+four lowerings of one function side by side, which is what C-c C-l shows in
+the editor.
The smallest program:
(defn main [] ()
@@ -1734,6 +1747,7 @@ something surprising.
C-c C-i inspect a value, navigating into its fields
C-c C-m what the macro call at point expands to, one step; C-u first for all the way
C-c C-a disassemble a function; C-u first for its LLVM IR
+C-c C-l every lowering of a function at once: IR, -O0, -O2, and the hand-written backend
C-c C-g debug under lldb, through dape — bound only once flan-dape.el is loaded, so flan-mode works without dape installed
C-c C-d what the running program currently defines
C-c C-v help on the name at point
@@ -1902,6 +1916,35 @@ name, with 38 programs skipped because they do not compile on either si
no main, or run forever. dune build @x86 runs it as part of the
build, so a refusal cannot sit unnoticed.
+It serves the editor now, which is what it was written for.
+flan dev --x86 and flan reload --x86 compile a redefinition
+through the hand-written backend, and the round trip is about half what LLVM's is —
+llc was nearly all of it, and an assembler is not:
+
+
+LLVM --x86
+code generation llc 42–48msas 8.0–8.4ms
+link ld 9.7–11.4msld 8.9–9.3ms
+C-c C-c, at the socket62–66ms 27–30ms
+C-x C-e60–61ms 24–25ms
+
+
+Both columns were measured on one machine, whose llc is slower than the
+one the 15–17ms above came from; the comparison is the point and not the absolute
+numbers. What the headline hides is where the time went: ld did not move and
+is now half the x86 build, and about 9ms of the round trip is the frontend checking the
+program again — a seventh of the LLVM loop but a third of this one. The next millisecond
+is in the linker rather than the code generator.
+
+It requires --two-process, and refuses the merged daemon by
+name. A merged host is linked -rdynamic, so it exports every Flan
+body it contains, and those interpose the prelude of the LLVM-built macro module the
+compiler loads into itself to expand macros. An LLVM caller lands in an x86 body
+and the process dies during the first expansion, before the program has started. The
+marker symbol that refuses a crossed redefinition module does not catch this, and was
+never meant to: a macro module deliberately carries none. Hidden visibility on a macro
+module's Flan bodies is the fix and is not built.
+
--debug is a third flag beside --dev and the optimisation
level. --dev asks whether you can redefine the program while it runs;
--debug asks whether you can stop it and read it. It emits DWARF, sets