diff --git a/src/SConscript b/src/SConscript
index 2903ec72c011e151e34df67417dc95c9a75a7900..9b89730d9b7015dad78e40f790a414cdab00fb44 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -70,7 +70,7 @@ backends = ['backends/%s.c' % s for s in
 
 # Add LLVM backend if enabled
 if GetOption("use_llvm"):
-    llvm_backend_files = ['llvm.c', 'llvm_charset.c']
+    llvm_backend_files = ['llvm.c', 'llvm_charset.c', 'llvm_suint.c']
     backends = backends + ['backends/llvm/%s' % s for s in llvm_backend_files]
 
 misc_hammer_parts = [
diff --git a/src/backends/llvm/llvm.c b/src/backends/llvm/llvm.c
index a2c15a102a532106e5497cb41c3a1ec4cc69bab1..185367a2e166920ada40a3e629ab72a38b747261 100644
--- a/src/backends/llvm/llvm.c
+++ b/src/backends/llvm/llvm.c
@@ -179,84 +179,6 @@ void h_llvm_free(HParser *parser) {
   llvm_parser->mod = NULL;
 }
 
-/*
- * Construct LLVM IR to allocate a token of type TT_SINT or TT_UINT
- *
- * Parameters:
- *  - mod [in]: an LLVMModuleRef
- *  - builder [in]: an LLVMBuilderRef, positioned appropriately
- *  - stream [in]: a value ref to an llvm_inputstreamptr, for the input stream
- *  - arena [in]: a value ref to an llvm_arenaptr to be used for the malloc
- *  - r [in]: a value ref to the value to be used to this token
- *  - mr_out [out]: the return value from make_result()
- *
- * TODO actually support TT_SINT, inputs other than 8 bit
- */
-
-void h_llvm_make_tt_suint(HLLVMParserCompileContext *ctxt,
-                          LLVMValueRef r, LLVMValueRef *mr_out) {
-  /* Set up call to h_arena_malloc() for a new HParsedToken */
-  LLVMValueRef tok_size = LLVMConstInt(LLVMInt32Type(), sizeof(HParsedToken), 0);
-  LLVMValueRef amalloc_args[] = { ctxt->arena, tok_size };
-  /* %h_arena_malloc = call void* @h_arena_malloc(%struct.HArena_.1* %1, i32 48) */
-  LLVMValueRef amalloc = LLVMBuildCall(ctxt->builder,
-      LLVMGetNamedFunction(ctxt->mod, "h_arena_malloc"),
-      amalloc_args, 2, "h_arena_malloc");
-  /* %tok = bitcast void* %h_arena_malloc to %struct.HParsedToken_.2* */
-  LLVMValueRef tok = LLVMBuildBitCast(ctxt->builder, amalloc, ctxt->llvm_parsedtokenptr, "tok");
-
-  /*
-   * tok->token_type = TT_UINT;
-   *
-   * %token_type = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 0
-   *
-   * TODO if we handle TT_SINT too, adjust here and the zero-ext below
-   */
-  LLVMValueRef toktype = LLVMBuildStructGEP(ctxt->builder, tok, 0, "token_type");
-  /* store i32 8, i32* %token_type */
-  LLVMBuildStore(ctxt->builder, LLVMConstInt(LLVMInt32Type(), 8, 0), toktype);
-
-  /*
-   * tok->uint = r;
-   *
-   * %token_data = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 1
-   */
-  LLVMValueRef tokdata = LLVMBuildStructGEP(ctxt->builder, tok, 1, "token_data");
-  /*
-   * TODO
-   *
-   * This is where we'll need to adjust to handle other types (sign vs. zero extend, omit extend if
-   * r is 64-bit already
-   */
-  LLVMBuildStore(ctxt->builder, LLVMBuildZExt(ctxt->builder, r, LLVMInt64Type(), "r"), tokdata);
-  /*
-   * Store the index from the stream into the token
-   */
-  /* %t_index = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 2 */
-  LLVMValueRef tokindex = LLVMBuildStructGEP(ctxt->builder, tok, 2, "t_index");
-  /* %s_index = getelementptr inbounds %struct.HInputStream_.0, %struct.HInputStream_.0* %0, i32 0, i32 2 */
-  LLVMValueRef streamindex = LLVMBuildStructGEP(ctxt->builder, ctxt->stream, 2, "s_index");
-  /* %4 = load i64, i64* %s_index */
-  /* store i64 %4, i64* %t_index */
-  LLVMBuildStore(ctxt->builder, LLVMBuildLoad(ctxt->builder, streamindex, ""), tokindex);
-  /* Store the bit length into the token */
-  LLVMValueRef tokbitlen = LLVMBuildStructGEP(ctxt->builder, tok, 3, "bit_length");
-  /* TODO handle multiple bit lengths */
-  LLVMBuildStore(ctxt->builder, LLVMConstInt(LLVMInt64Type(), 8, 0), tokbitlen);
-
-  /*
-   * Now call make_result()
-   *
-   * %make_result = call %struct.HParseResult_.3* @make_result(%struct.HArena_.1* %1, %struct.HParsedToken_.2* %3)
-   */
-  LLVMValueRef result_args[] = { ctxt->arena, tok };
-  LLVMValueRef mr = LLVMBuildCall(ctxt->builder,
-      LLVMGetNamedFunction(ctxt->mod, "make_result"),
-      result_args, 2, "make_result");
-
-  *mr_out = mr;
-}
-
 HParseResult *h_llvm_parse(HAllocator* mm__, const HParser* parser, HInputStream *input_stream) {
   const HLLVMParser *llvm_parser = parser->backend_data;
   HArena *arena = h_new_arena(mm__, 0);
diff --git a/src/backends/llvm/llvm_suint.c b/src/backends/llvm/llvm_suint.c
new file mode 100644
index 0000000000000000000000000000000000000000..0cce9a3e33b71821391fefd3e152c66b6a9c1635
--- /dev/null
+++ b/src/backends/llvm/llvm_suint.c
@@ -0,0 +1,90 @@
+#ifdef HAMMER_LLVM_BACKEND
+
+#include <llvm-c/Analysis.h>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#include <llvm-c/Core.h>
+#pragma GCC diagnostic pop
+#include <llvm-c/ExecutionEngine.h>
+#include "../../internal.h"
+#include "llvm.h"
+
+/*
+ * Construct LLVM IR to allocate a token of type TT_SINT or TT_UINT
+ *
+ * Parameters:
+ *  - mod [in]: an LLVMModuleRef
+ *  - builder [in]: an LLVMBuilderRef, positioned appropriately
+ *  - stream [in]: a value ref to an llvm_inputstreamptr, for the input stream
+ *  - arena [in]: a value ref to an llvm_arenaptr to be used for the malloc
+ *  - r [in]: a value ref to the value to be used to this token
+ *  - mr_out [out]: the return value from make_result()
+ *
+ * TODO actually support TT_SINT, inputs other than 8 bit
+ */
+
+void h_llvm_make_tt_suint(HLLVMParserCompileContext *ctxt,
+                          LLVMValueRef r, LLVMValueRef *mr_out) {
+  /* Set up call to h_arena_malloc() for a new HParsedToken */
+  LLVMValueRef tok_size = LLVMConstInt(LLVMInt32Type(), sizeof(HParsedToken), 0);
+  LLVMValueRef amalloc_args[] = { ctxt->arena, tok_size };
+  /* %h_arena_malloc = call void* @h_arena_malloc(%struct.HArena_.1* %1, i32 48) */
+  LLVMValueRef amalloc = LLVMBuildCall(ctxt->builder,
+      LLVMGetNamedFunction(ctxt->mod, "h_arena_malloc"),
+      amalloc_args, 2, "h_arena_malloc");
+  /* %tok = bitcast void* %h_arena_malloc to %struct.HParsedToken_.2* */
+  LLVMValueRef tok = LLVMBuildBitCast(ctxt->builder, amalloc, ctxt->llvm_parsedtokenptr, "tok");
+
+  /*
+   * tok->token_type = TT_UINT;
+   *
+   * %token_type = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 0
+   *
+   * TODO if we handle TT_SINT too, adjust here and the zero-ext below
+   */
+  LLVMValueRef toktype = LLVMBuildStructGEP(ctxt->builder, tok, 0, "token_type");
+  /* store i32 8, i32* %token_type */
+  LLVMBuildStore(ctxt->builder, LLVMConstInt(LLVMInt32Type(), 8, 0), toktype);
+
+  /*
+   * tok->uint = r;
+   *
+   * %token_data = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 1
+   */
+  LLVMValueRef tokdata = LLVMBuildStructGEP(ctxt->builder, tok, 1, "token_data");
+  /*
+   * TODO
+   *
+   * This is where we'll need to adjust to handle other types (sign vs. zero extend, omit extend if
+   * r is 64-bit already
+   */
+  LLVMBuildStore(ctxt->builder, LLVMBuildZExt(ctxt->builder, r, LLVMInt64Type(), "r"), tokdata);
+  /*
+   * Store the index from the stream into the token
+   */
+  /* %t_index = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 2 */
+  LLVMValueRef tokindex = LLVMBuildStructGEP(ctxt->builder, tok, 2, "t_index");
+  /* %s_index = getelementptr inbounds %struct.HInputStream_.0, %struct.HInputStream_.0* %0, i32 0, i32 2 */
+  LLVMValueRef streamindex = LLVMBuildStructGEP(ctxt->builder, ctxt->stream, 2, "s_index");
+  /* %4 = load i64, i64* %s_index */
+  /* store i64 %4, i64* %t_index */
+  LLVMBuildStore(ctxt->builder, LLVMBuildLoad(ctxt->builder, streamindex, ""), tokindex);
+  /* Store the bit length into the token */
+  LLVMValueRef tokbitlen = LLVMBuildStructGEP(ctxt->builder, tok, 3, "bit_length");
+  /* TODO handle multiple bit lengths */
+  LLVMBuildStore(ctxt->builder, LLVMConstInt(LLVMInt64Type(), 8, 0), tokbitlen);
+
+  /*
+   * Now call make_result()
+   *
+   * %make_result = call %struct.HParseResult_.3* @make_result(%struct.HArena_.1* %1, %struct.HParsedToken_.2* %3)
+   */
+  LLVMValueRef result_args[] = { ctxt->arena, tok };
+  LLVMValueRef mr = LLVMBuildCall(ctxt->builder,
+      LLVMGetNamedFunction(ctxt->mod, "make_result"),
+      result_args, 2, "make_result");
+
+  *mr_out = mr;
+}
+
+#endif /* defined(HAMMER_LLVM_BACKEND) */