
A fork-rewrite of RMSbolt, itself a supercharged implementation of Godbolt, the Compiler Explorer but for Emacs, instead of a clunky browser.
Beardbolt shows assembly output for given source code file, making it easy to see what the compiler is doing.
It also highlights which source code corresponds to a given assembly, and vice versa.
cd /path/to/beardbolt/clone
make
(add-to-list 'load-path "/path/to/beardbolt/clone")
(require 'beardbolt)
M-x beardbolt-starter
beardbolt-starter: Lets you start a new experiment in one of the
supported languages. Automatically start beardbolt-mode.
beardbolt-mode: Starts a minor mode that automatically re-compiles
buffer code every few changes to the source code.
beardbolt-compile: Manually start a compilation. Bound to C-c C-c in beardbolt-mode.
Beardbolt's behaviour can be tweaked with some options that more or less correspond to the ones of Compiler Explorer. You may set them globally (they're normal Emacs customization variables), but they're probably more useful as file-local cookies, like you see in the animated gif above.
Beardbolt will pick them up immediately on each run.
beardbolt-command: Main compiler command to run. May be something like
"gcc -O3". Leave unset to have Beardbolt try to guess from some
nearby compilation_commands.json.
beardbolt-disassemble: Compile, assemble, then disassemble using
objdump and present that input instead of assembly code.
beardbolt-asm-format: Choose between intel and att formats.
beardbolt-preserve-directives: Keep every non-code, non-label asm
directive.
beardbolt-preserve-unused-labels: Keep unused asm labels.
beardbolt-preserve-library-functions: Keep functions with no code
related to current file.
beardbolt-demangle: Demangle any mangled symbols of resulting
assembly with c++filt.
beardbolt-execute: If non-nil, run the resulting program in the
compilation buffer. If a string, run with these arguments. If t,
runs without arguments.
beardbolt-ccj-extra-flags: A string of extra compilation flags to
append to the compilation command devined from
compile_commands.json.
beardbolt-shuffle-rainbow: Use less pretty rainbow colors, but
potentially more useful and contrasting ones.
First, a word on what "fast" means. The performance metric to optimize is responsiveness: the goal is not only to provide this a live view of the assembly output as quickly as possible, and also to intrude as little as possible in the user's editing.
Both Beardbolt and RMSbolt extensions work in a two-step fashion. Most of the speed gains of Beardbolt happen in step 2.
The file is saved somewhere and partially compiled by an external program
This happens asynchronously. It might takes several seconds and spin up your CPU, but it does not generally harm the UX inside Emacs.
Some Elisp processing takes place on the assembly output
This happens inside Emacs, and it's generally bad if it takes a long time, because Emacs is single-threaded and has no easily accessible asynchronous mechanisms for this type of work.
To run the benchmarks, have both RMSbolt and Beardbolt clones side-by-side, then:
$ cd /path/to/beardbolt/clone
$ EMACS=~/Source/Emacs/emacs/src/emacs make benchmark
/home/capitaomorte/Source/Emacs/emacs/src/emacs -Q -L . --batch -l beardbolt-benchmark starters/slow-to-process.cpp
RMSbolt timings for slow-to-process.cpp
samples: (1.329s 1.316s 1.338s 1.345s 1.341s)
average: 1.334s
Beardbolt timings for slow-to-process.cpp
samples: (0.324s 0.338s 0.334s 0.334s 0.342s)
average: 0.334s
/home/capitaomorte/Source/Emacs/emacs/src/emacs -Q -L . --batch -l beardbolt-benchmark starters/vector-emplace-back.cpp
RMSbolt timings for vector-emplace-back.cpp
samples: (0.234s 0.223s 0.223s 0.240s 0.224s)
average: 0.229s
Beardbolt timings for vector-emplace-back.cpp
samples: (0.086s 0.074s 0.073s 0.074s 0.089s)
average: 0.079s
/home/capitaomorte/Source/Emacs/emacs/src/emacs -Q -L . --batch -l beardbolt-benchmark starters/unordered-multimap-emplace.cpp
RMSbolt timings for unordered-multimap-emplace.cpp
samples: (0.534s 0.523s 0.524s 0.523s 0.529s)
average: 0.527s
Beardbolt timings for unordered-multimap-emplace.cpp
samples: (0.103s 0.123s 0.103s 0.102s 0.118s)
average: 0.110s
This ran beardbolt-compile and rmsbolt-compile 5 times on small
two cppreference.com examples
(1, 2) as well as a known "slow" file found in
RMSbolt's bug tracker.
To make the benchmark fair(er?) I patched rmsbolt.el to generate
slightly less debug with -g1 instead of -g, and thus benefit from
the same speedup that beardbolt.el.
The results were obtained on my Thinkpad T480 running Emacs 29 (without native compilation).
Emacs Lisp
53.7%
C++
43.6%
C
1.3%

A fork-rewrite of RMSbolt, itself a supercharged implementation of Godbolt, the Compiler Explorer but for Emacs, instead of a clunky browser.
Beardbolt shows assembly output for given source code file, making it easy to see what the compiler is doing.
It also highlights which source code corresponds to a given assembly, and vice versa.
cd /path/to/beardbolt/clone
make
(add-to-list 'load-path "/path/to/beardbolt/clone")
(require 'beardbolt)
M-x beardbolt-starter
beardbolt-starter: Lets you start a new experiment in one of the
supported languages. Automatically start beardbolt-mode.
beardbolt-mode: Starts a minor mode that automatically re-compiles
buffer code every few changes to the source code.
beardbolt-compile: Manually start a compilation. Bound to C-c C-c in beardbolt-mode.
Beardbolt's behaviour can be tweaked with some options that more or less correspond to the ones of Compiler Explorer. You may set them globally (they're normal Emacs customization variables), but they're probably more useful as file-local cookies, like you see in the animated gif above.
Beardbolt will pick them up immediately on each run.
beardbolt-command: Main compiler command to run. May be something like
"gcc -O3". Leave unset to have Beardbolt try to guess from some
nearby compilation_commands.json.
beardbolt-disassemble: Compile, assemble, then disassemble using
objdump and present that input instead of assembly code.
beardbolt-asm-format: Choose between intel and att formats.
beardbolt-preserve-directives: Keep every non-code, non-label asm
directive.
beardbolt-preserve-unused-labels: Keep unused asm labels.
beardbolt-preserve-library-functions: Keep functions with no code
related to current file.
beardbolt-demangle: Demangle any mangled symbols of resulting
assembly with c++filt.
beardbolt-execute: If non-nil, run the resulting program in the
compilation buffer. If a string, run with these arguments. If t,
runs without arguments.
beardbolt-ccj-extra-flags: A string of extra compilation flags to
append to the compilation command devined from
compile_commands.json.
beardbolt-shuffle-rainbow: Use less pretty rainbow colors, but
potentially more useful and contrasting ones.
First, a word on what "fast" means. The performance metric to optimize is responsiveness: the goal is not only to provide this a live view of the assembly output as quickly as possible, and also to intrude as little as possible in the user's editing.
Both Beardbolt and RMSbolt extensions work in a two-step fashion. Most of the speed gains of Beardbolt happen in step 2.
The file is saved somewhere and partially compiled by an external program
This happens asynchronously. It might takes several seconds and spin up your CPU, but it does not generally harm the UX inside Emacs.
Some Elisp processing takes place on the assembly output
This happens inside Emacs, and it's generally bad if it takes a long time, because Emacs is single-threaded and has no easily accessible asynchronous mechanisms for this type of work.
To run the benchmarks, have both RMSbolt and Beardbolt clones side-by-side, then:
$ cd /path/to/beardbolt/clone
$ EMACS=~/Source/Emacs/emacs/src/emacs make benchmark
/home/capitaomorte/Source/Emacs/emacs/src/emacs -Q -L . --batch -l beardbolt-benchmark starters/slow-to-process.cpp
RMSbolt timings for slow-to-process.cpp
samples: (1.329s 1.316s 1.338s 1.345s 1.341s)
average: 1.334s
Beardbolt timings for slow-to-process.cpp
samples: (0.324s 0.338s 0.334s 0.334s 0.342s)
average: 0.334s
/home/capitaomorte/Source/Emacs/emacs/src/emacs -Q -L . --batch -l beardbolt-benchmark starters/vector-emplace-back.cpp
RMSbolt timings for vector-emplace-back.cpp
samples: (0.234s 0.223s 0.223s 0.240s 0.224s)
average: 0.229s
Beardbolt timings for vector-emplace-back.cpp
samples: (0.086s 0.074s 0.073s 0.074s 0.089s)
average: 0.079s
/home/capitaomorte/Source/Emacs/emacs/src/emacs -Q -L . --batch -l beardbolt-benchmark starters/unordered-multimap-emplace.cpp
RMSbolt timings for unordered-multimap-emplace.cpp
samples: (0.534s 0.523s 0.524s 0.523s 0.529s)
average: 0.527s
Beardbolt timings for unordered-multimap-emplace.cpp
samples: (0.103s 0.123s 0.103s 0.102s 0.118s)
average: 0.110s
This ran beardbolt-compile and rmsbolt-compile 5 times on small
two cppreference.com examples
(1, 2) as well as a known "slow" file found in
RMSbolt's bug tracker.
To make the benchmark fair(er?) I patched rmsbolt.el to generate
slightly less debug with -g1 instead of -g, and thus benefit from
the same speedup that beardbolt.el.
The results were obtained on my Thinkpad T480 running Emacs 29 (without native compilation).
Emacs Lisp
53.7%
C++
43.6%
C
1.3%