I finally decided to use the power of emacs to automate a task that I perform at least a dozen times per day: converting a snippet of C source code into LLVM IR assembly. The command to do this is simple:
clang -emit-llvm -c -o - file.c | opt -S
The only annoying part about using the command was finding a spare terminal and finding the input file on the file system (and then remembering where I put that terminal when I wanted to refer to it later). Enter emacs. It took a while to navigate the emacs documentation to figure out how to write what I wanted and learn the relevant terminology. The function I came up with pipes the current buffer (or region, if it is active) to clang and opt, puts the output in a new buffer, activates the llvm major mode, and switches to the new buffer.
(defun llvmize (&optional start end)
"Convert the current buffer or region (containing C code) to LLVM assembly via clang and opt"
(interactive)
(let ((start (if mark-active (region-beginning) (point-min)))
(end (if mark-active (region-end) (point-max)))
(default-major-mode 'llvm-mode)
(buf (generate-new-buffer "*llvm-asm*")))
(set-buffer-major-mode buf)
(shell-command-on-region start end "clang -emit-llvm -x c -c -o - - | opt -S -mem2reg -basicaa -gvn" buf)
(set-buffer buf)
(setq buffer-read-only t)
(switch-to-buffer-other-window buf)))
This has a few nice benefits over just throwing LLVM IR assembly dumps into random terminals:
- Nice syntax highlighting
- Standard emacs buffer management applies
- Cuts down on terminal proliferation (a serious problem)
I feel like this style of function is generally useful and I should probably make a few more to automate my life a bit. This function still needs a few improvements:
- I want to look at the file extension (if there is one) of the
active buffer so that I can use
-x c++
instead of always just using-x c
for clang. - I also want to find the best clang and opt binaries on the system;
debian installs opt as
opt-$version
, so this function doesn't work as-is. - I want to add some keymaps to the freshly-created buffer to easily quit and close the window when I am done with it.
Back to reading the emacs documentation.