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 cfor 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.