diff --git a/src/backends/llvm/llvm.c b/src/backends/llvm/llvm.c
index 1e673b67f3954360ede0f8aae1fbd205fd97f1f1..356b279b2754772921ae9e449c6848d3b792a2b4 100644
--- a/src/backends/llvm/llvm.c
+++ b/src/backends/llvm/llvm.c
@@ -106,9 +106,30 @@ void h_llvm_declare_common(HLLVMParserCompileContext *ctxt) {
 }
 
 int h_llvm_compile(HAllocator* mm__, HParser* parser, const void* params) {
+  /* Globals for the LLVM build process */
   HLLVMParserCompileContext *ctxt;
-  // Boilerplate to set up a translation unit, aka a module.
-  const char* name = params ? (const char*)params : "parse";
+  /* Return result from the top-level parser */
+  LLVMValueRef res;
+  /* Execution engine, eventually */
+  LLVMExecutionEngineRef engine = NULL;
+  /* LLVM error message, if any */
+  char *error = NULL;
+  /* LLVM IR dump, if any */
+  char *dump = NULL;
+  /* Finished LLVM parser, eventually */
+  HLLVMParser *llvm_parser = NULL;
+  /* LLVM parse function return type */
+  LLVMTypeRef ret_type;
+  /* Preamble and postamble blocks */
+  LLVMBasicBlockRef preamble, postamble;
+  char *preamble_name = NULL, *postamble_name = NULL;
+  int preamble_name_len = 0, postamble_name_len = 0;
+  /* Boilerplate to set up a translation unit, aka a module. */
+  const char *name = params ? (const char*)params : "parse";
+  /* Types of parameters to use in the function declaration */
+  LLVMTypeRef parser_param_types[2];
+  /* Return value */
+  int rv;
 
   /* Build a parser compilation context */
   ctxt = h_new(HLLVMParserCompileContext, 1);
@@ -117,18 +138,27 @@ int h_llvm_compile(HAllocator* mm__, HParser* parser, const void* params) {
   ctxt->mod = LLVMModuleCreateWithName(name);
   h_llvm_declare_common(ctxt);
 
-  // Boilerplate to set up the parser function to add to the module. It takes an HInputStream* and
-  // returns an HParseResult.
-  LLVMTypeRef param_types[] = {
-    ctxt->llvm_inputstreamptr,
-    ctxt->llvm_arenaptr
-  };
-  LLVMTypeRef ret_type = LLVMFunctionType(ctxt->llvm_parseresultptr, param_types, 2, 0);
+  /*
+   * Boilerplate to set up the parser function to add to the module. It
+   * takes an HInputStream* and returns an HParseResult.
+   */
+  parser_param_types[0] = ctxt->llvm_inputstreamptr;
+  parser_param_types[1] = ctxt->llvm_arenaptr;
+  ret_type = LLVMFunctionType(ctxt->llvm_parseresultptr,
+      parser_param_types, 2, 0);
   ctxt->func = LLVMAddFunction(ctxt->mod, name, ret_type);
 
-  // Parse function is now declared; time to define it
+  /* Parse function is now declared; time to define it */
   ctxt->builder = LLVMCreateBuilder();
-  LLVMBasicBlockRef preamble = LLVMAppendBasicBlock(ctxt->func, "preamble");
+  /*
+   * In case we need to build more for internal parsers, we use the address
+   * of the HParser for forming names.
+   */
+  preamble_name_len = snprintf(NULL, 0, "preamble_%p", (void *)parser);
+  preamble_name = h_new(char, preamble_name_len + 1);
+  snprintf(preamble_name, preamble_name_len + 1, "preamble_%p",
+           (void *)parser);
+  preamble = LLVMAppendBasicBlock(ctxt->func, preamble_name);
   LLVMPositionBuilderAtEnd(ctxt->builder, preamble);
 
   /*
@@ -144,38 +174,72 @@ int h_llvm_compile(HAllocator* mm__, HParser* parser, const void* params) {
       ctxt->llvm_inputstreamptr, "stream");
   ctxt->arena = LLVMGetLastParam(ctxt->func);
 
-  // Translate the contents of the children of `parser` into their LLVM instruction equivalents
-  if (parser->vtable->llvm(ctxt, parser->env)) {
-    // But first, verification
-    char *error = NULL;
+  /*
+   * Translate the contents of the children of `parser` into their LLVM
+   * instruction equivalents
+   */
+  if (parser->vtable->llvm(ctxt, parser->env, &res)) {
+    /* Okay, we got it - set up a postamble basic block */
+    postamble_name_len = snprintf(NULL, 0, "postamble_%p", (void *)parser);
+    postamble_name = h_new(char, postamble_name_len + 1);
+    snprintf(postamble_name, postamble_name_len + 1, "postamble_%p",
+             (void *)parser);
+    postamble = LLVMAppendBasicBlock(ctxt->func, postamble_name);
+    /* Branch from last basic block in the parser to the postamble */
+    LLVMBuildBr(ctxt->builder, postamble);
+    LLVMPositionBuilderAtEnd(ctxt->builder, postamble);
+    /* ...and return the result, since this is the top level */
+    LLVMBuildRet(ctxt->builder, res);
+    /* Finished building the Big Damn Function, now we compile the module */
+
+    /* First, verification */
     LLVMVerifyModule(ctxt->mod, LLVMAbortProcessAction, &error);
     LLVMDisposeMessage(error);
     error = NULL;
-    // OK, link that sonofabitch
+    /* OK, link that sonofabitch */
     LLVMLinkInMCJIT();
     LLVMInitializeNativeTarget();
     LLVMInitializeNativeAsmPrinter();
-    LLVMExecutionEngineRef engine = NULL;
     LLVMCreateExecutionEngineForModule(&engine, ctxt->mod, &error);
-    if (error) {
+
+    if (!error) {
+      /* Do IR dump */
+      dump = LLVMPrintModuleToString(ctxt->mod);
+      fprintf(stderr, "\n\n%s\n\n", dump);
+      /*
+       * Package up the pointers that comprise the module and stash it in
+       * the original HParser
+       */
+      llvm_parser = h_new(HLLVMParser, 1);
+      llvm_parser->mod = ctxt->mod;
+      llvm_parser->func = ctxt->func;
+      llvm_parser->engine = engine;
+      llvm_parser->builder = ctxt->builder;
+      llvm_parser->compile_ctxt = ctxt;
+      parser->backend_data = llvm_parser;
+      /* Sweet lemony-fresh victory is mine! */
+      rv = 0;
+    } else {
       fprintf(stderr, "error: %s\n", error);
       LLVMDisposeMessage(error);
-      return -1;
+      rv = -1;
     }
-    char* dump = LLVMPrintModuleToString(ctxt->mod);
-    fprintf(stderr, "\n\n%s\n\n", dump);
-    // Package up the pointers that comprise the module and stash it in the original HParser
-    HLLVMParser *llvm_parser = h_new(HLLVMParser, 1);
-    llvm_parser->mod = ctxt->mod;
-    llvm_parser->func = ctxt->func;
-    llvm_parser->engine = engine;
-    llvm_parser->builder = ctxt->builder;
-    llvm_parser->compile_ctxt = ctxt;
-    parser->backend_data = llvm_parser;
-    return 0;
   } else {
-    return -1;
+    rv = -1;
+  }
+
+  /* Cleanup */
+  if (preamble_name) {
+    h_free(preamble_name);
+    preamble_name = NULL;
+  }
+
+  if (postamble_name) {
+    h_free(postamble_name);
+    postamble_name = NULL;
   }
+
+  return rv;
 }
 
 void h_llvm_free(HParser *parser) {
diff --git a/src/internal.h b/src/internal.h
index 9a9b0214f62705ce71b84ce0d6f620a1bd587bbf..7646e3a6576ae73d9d54b74f02f38f5253a2ed7f 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -505,7 +505,7 @@ struct HParserVtable_ {
   bool (*compile_to_rvm)(HRVMProg *prog, void* env); // FIXME: forgot what the bool return value was supposed to mean.
   void (*desugar)(HAllocator *mm__, HCFStack *stk__, void *env);
 #ifdef HAMMER_LLVM_BACKEND
-  bool (*llvm)(HLLVMParserCompileContext *ctxt, void *env);
+  bool (*llvm)(HLLVMParserCompileContext *ctxt, void *env, LLVMValueRef *result);
 #endif
   bool higher; // false if primitive
 };
diff --git a/src/parsers/bits.c b/src/parsers/bits.c
index bd9fa8e064e7431a1b84a3de520ce35fc43fd7f7..f59849fde9d0d4d66e5ebb678fe061a4161f4633 100644
--- a/src/parsers/bits.c
+++ b/src/parsers/bits.c
@@ -26,9 +26,12 @@ static HParseResult* parse_bits(void* env, HParseState *state) {
 
 #ifdef HAMMER_LLVM_BACKEND
 
-static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env) {
+static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) {
   /* Emit LLVM IR to parse ((struct bits_env *)env)->length bits */
 
+  if (!res) return false;
+  /* This will get set to non-NULL only when we return true */
+  *res = NULL;
   if (!ctxt) return false;
 
   struct bits_env *env_ = env;
@@ -57,7 +60,7 @@ static bool bits_llvm(HLLVMParserCompileContext *ctxt, void* env) {
   h_llvm_make_tt_suint(ctxt, env_->length, env_->signedp, bits, &mr);
 
   /* Return mr */
-  LLVMBuildRet(ctxt->builder, mr);
+  *res = mr;
 
   return true;
 }
diff --git a/src/parsers/ch.c b/src/parsers/ch.c
index e22ed8c105673fd7b989b60e623e83ee9bead050..2db312d6fc45a299261a36be2b2782467382fa11 100644
--- a/src/parsers/ch.c
+++ b/src/parsers/ch.c
@@ -50,55 +50,75 @@ static bool ch_ctrvm(HRVMProg *prog, void* env) {
 
 #ifdef HAMMER_LLVM_BACKEND
 
-static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env) {
-  // Build a new LLVM function to parse a character
+static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) {
+  /* Build a new LLVM function to parse a character */
 
-  // Set up params for calls to h_read_bits() and h_arena_malloc()
+  if (!res) return false;
+  if (!ctxt) return false;
+
+  /* Set up params for calls to h_read_bits() and h_arena_malloc() */
   LLVMValueRef bits_args[3];
   bits_args[0] = ctxt->stream;
   bits_args[1] = LLVMConstInt(LLVMInt32Type(), 8, 0);
   bits_args[2] = LLVMConstInt(LLVMInt8Type(), 0, 0);
 
-  // Set up basic blocks: entry, success and failure branches, then exit
+  /*
+   * Set up basic blocks: entry, success and failure branches, then exit
+   *
+   * TODO should these basic block names reflect the particular HParser to
+   * make the IR dump more comprehensible?
+   */
   LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "ch_entry");
   LLVMBasicBlockRef success = LLVMAppendBasicBlock(ctxt->func, "ch_success");
   LLVMBasicBlockRef end = LLVMAppendBasicBlock(ctxt->func, "ch_end");
 
-  // Basic block: entry
+  /* Basic block: entry */
   LLVMBuildBr(ctxt->builder, entry);
   LLVMPositionBuilderAtEnd(ctxt->builder, entry);
 
-  // Call to h_read_bits()
-  // %read_bits = call i64 @h_read_bits(%struct.HInputStream_* %8, i32 8, i8 signext 0)
+  /*
+   * Call to h_read_bits()
+   *
+   * %read_bits = call i64 @h_read_bits(%struct.HInputStream_* %8,
+   *                                    i32 8, i8 signext 0)
+   */
   LLVMValueRef bits = LLVMBuildCall(ctxt->builder,
       LLVMGetNamedFunction(ctxt->mod, "h_read_bits"), bits_args, 3, "read_bits");
-  // %2 = trunc i64 %read_bits to i8
+  /* %2 = trunc i64 %read_bits to i8 */
   LLVMValueRef r = LLVMBuildTrunc(ctxt->builder,
-      bits, LLVMInt8Type(), ""); // do we actually need this?
+      bits, LLVMInt8Type(), "");
 
-  // Check if h_read_bits succeeded
-  // %"c == r" = icmp eq i8 -94, %2 ; the -94 comes from c_
+  /*
+   * Check if h_read_bits succeeded
+   *
+   * %"c == r" = icmp eq i8 -94, %2 ; the -94 comes from c_
+   */
   uint8_t c_ = (uint8_t)(uintptr_t)(env);
   LLVMValueRef c = LLVMConstInt(LLVMInt8Type(), c_, 0);
   LLVMValueRef icmp = LLVMBuildICmp(ctxt->builder, LLVMIntEQ, c, r, "c == r");
 
-  // Branch so success or failure basic block, as appropriate
-  // br i1 %"c == r", label %ch_success, label %ch_fail
+  /*
+   * Branch so success or failure basic block, as appropriate
+   * br i1 %"c == r", label %ch_success, label %ch_fail
+   */
   LLVMBuildCondBr(ctxt->builder, icmp, success, end);
 
-  // Basic block: success
+  /* Basic block: success */
   LLVMPositionBuilderAtEnd(ctxt->builder, success);
 
   /* Make a token */
   LLVMValueRef mr;
   h_llvm_make_tt_suint(ctxt, 8, 0, r, &mr);
 
-  // br label %ch_end
+  /* br label %ch_end */
   LLVMBuildBr(ctxt->builder, end);
   
-  // Basic block: end
+  /* Basic block: end */
   LLVMPositionBuilderAtEnd(ctxt->builder, end);
-  // %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], [ null, %ch_entry ]
+  /*
+   * %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ],
+   *       [ null, %ch_entry ]
+   */
   LLVMValueRef rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv");
   LLVMBasicBlockRef rv_phi_incoming_blocks[] = {
     success,
@@ -109,8 +129,9 @@ static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env) {
     LLVMConstNull(ctxt->llvm_parseresultptr)
     };
   LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2);
-  // ret %struct.HParseResult_.3* %rv
-  LLVMBuildRet(ctxt->builder, rv);
+  /* Pass rv out to caller */
+  *res = rv;
+
   return true;
 }
 
diff --git a/src/parsers/charset.c b/src/parsers/charset.c
index 907fe927a79184c3c292a96630a49fc83fc0b1e3..f77d9e78e9e6736950ea81cd295793ba27f6ad24 100644
--- a/src/parsers/charset.c
+++ b/src/parsers/charset.c
@@ -79,36 +79,54 @@ static bool cs_ctrvm(HRVMProg *prog, void *env) {
 
 #ifdef HAMMER_LLVM_BACKEND
 
-static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env) {
+static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) {
   /*
    * LLVM to build a function to parse a charset; the args are a stream and an
    * arena.
    */
-  bool ok;
 
+  /* Current status */
+  bool ok;
+  /* Our charset (passed in env) */
+  HCharset cs;
+  /* Basic blocks for the charset */
+  LLVMBasicBlockRef entry, success, fail, end;
+  /* Args to h_read_bits() */
+  LLVMValueRef bits_args[3];
+  /* Result from h_read_bits() */
+  LLVMValueRef bits;
+  /* Cast result from h_read_bits() */
+  LLVMValueRef r;
+  /* Result */
+  LLVMValueRef rv;
+  /* Phis for rv */
+  LLVMValueRef rv_phi_incoming_values[2];
+  LLVMBasicBlockRef rv_phi_incoming_blocks[2];
+
+  if (!res) return false;
   if (!ctxt) return false;
 
   /* Set up our basic blocks */
-  LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "cs_entry");
-  LLVMBasicBlockRef success = LLVMAppendBasicBlock(ctxt->func, "cs_success");
-  LLVMBasicBlockRef fail = LLVMAppendBasicBlock(ctxt->func, "cs_fail");
-  LLVMBasicBlockRef end = LLVMAppendBasicBlock(ctxt->func, "cs_end");
+  /* TODO should we use distinct names for different HParsers? */
+  entry = LLVMAppendBasicBlock(ctxt->func, "cs_entry");
+  success = LLVMAppendBasicBlock(ctxt->func, "cs_success");
+  fail = LLVMAppendBasicBlock(ctxt->func, "cs_fail");
+  end = LLVMAppendBasicBlock(ctxt->func, "cs_end");
 
   /* Basic block: entry */
   LLVMBuildBr(ctxt->builder, entry);
   LLVMPositionBuilderAtEnd(ctxt->builder, entry);
   /* First we read the char */
-  LLVMValueRef bits_args[3];
   bits_args[0] = ctxt->stream;
   bits_args[1] = LLVMConstInt(LLVMInt32Type(), 8, 0);
   bits_args[2] = LLVMConstInt(LLVMInt8Type(), 0, 0);
-  LLVMValueRef bits = LLVMBuildCall(ctxt->builder,
-      LLVMGetNamedFunction(ctxt->mod, "h_read_bits"), bits_args, 3, "read_bits");
-  LLVMValueRef r =
-    LLVMBuildTrunc(ctxt->builder, bits, LLVMInt8Type(), ""); // TODO Necessary? (same question in ch_llvm())
+  bits = LLVMBuildCall(ctxt->builder,
+                       LLVMGetNamedFunction(ctxt->mod, "h_read_bits"),
+                       bits_args, 3, "read_bits");
+  r = LLVMBuildTrunc(ctxt->builder, bits, LLVMInt8Type(), "");
 
   /* We have a char, need to check if it's in the charset */
-  HCharset cs = (HCharset)env;
+  cs = (HCharset)env;
   /* Branch to either success or end, conditional on whether r is in cs */
   ok = h_llvm_make_charset_membership_test(ctxt, r, cs, success, fail);
 
@@ -132,19 +150,18 @@ static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env) {
 
   /* Basic block: end */
   LLVMPositionBuilderAtEnd(ctxt->builder, end);
-  // %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ], [ null, %ch_entry ]
-  LLVMValueRef rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv");
-  LLVMBasicBlockRef rv_phi_incoming_blocks[] = {
-    success,
-    fail
-  };
-  LLVMValueRef rv_phi_incoming_values[] = {
-    mr,
-    LLVMConstNull(ctxt->llvm_parseresultptr)
-  };
+  /*
+   * %rv = phi %struct.HParseResult_.3* [ %make_result, %ch_success ],
+   *                                    [ null, %ch_entry ]
+   */
+  rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv");
+  rv_phi_incoming_blocks[0] = success;
+  rv_phi_incoming_values[0] = mr;
+  rv_phi_incoming_blocks[1] = fail;
+  rv_phi_incoming_values[1] = LLVMConstNull(ctxt->llvm_parseresultptr);
   LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2);
-  // ret %struct.HParseResult_.3* %rv
-  LLVMBuildRet(ctxt->builder, rv);
+  /* Pass rv back out to caller */
+  *res = rv;
 
   return ok;
 }
diff --git a/src/parsers/end.c b/src/parsers/end.c
index 3643f6c7f109c93dd60d143c2c94c06adc06846f..11dcd33fd152188113bbb2eae10a12ff65cbfb10 100644
--- a/src/parsers/end.c
+++ b/src/parsers/end.c
@@ -28,13 +28,30 @@ static bool end_ctrvm(HRVMProg *prog, void *env) {
 
 #ifdef HAMMER_LLVM_BACKEND
 
-static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) {
+static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) {
+  /* Basic blocks for parsing end */
+  LLVMBasicBlockRef entry, success, end;
+  /* Indices for GEP */
+  LLVMValueRef gep_indices[2];
+  /* Args to make_result() */
+  LLVMValueRef make_result_args[2];
+  /* Return from make_result() */
+  LLVMValueRef result_ptr;
+  /* Result of this parser */
+  LLVMValueRef rv;
+  /* Incoming basic blocks for phi */
+  LLVMBasicBlockRef rv_phi_incoming_blocks[2];
+  /* Incoming values for phi */
+  LLVMValueRef rv_phi_incoming_values[2];
+
+  if (!res) return false;
   if (!ctxt) return false;
 
   /* Set up some basic blocks */
-  LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "end_entry");
-  LLVMBasicBlockRef success = LLVMAppendBasicBlock(ctxt->func, "end_success");
-  LLVMBasicBlockRef end = LLVMAppendBasicBlock(ctxt->func, "end_end");
+  /* TODO distinct names for different HParsers? */
+  entry = LLVMAppendBasicBlock(ctxt->func, "end_entry");
+  success = LLVMAppendBasicBlock(ctxt->func, "end_success");
+  end = LLVMAppendBasicBlock(ctxt->func, "end_end");
 
   /* Basic block: entry */
   LLVMBuildBr(ctxt->builder, entry);
@@ -45,7 +62,7 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) {
    * comparing the index and length fields; build a struct GEP to
    * get at their values.
    */
-  LLVMValueRef gep_indices[2];
+
   /* The struct itself */
   gep_indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
   /* The index field (see HInputStream in internal.h */
@@ -53,16 +70,19 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) {
   /* GEP */
   LLVMValueRef index_ptr = LLVMBuildGEP(ctxt->builder,
       ctxt->stream, gep_indices, 2, "index_ptr");
+
   /* The length field (see HInputStream in internal.h */
   gep_indices[1] = LLVMConstInt(LLVMInt32Type(), 3, 0);
   /* GEP */
   LLVMValueRef length_ptr = LLVMBuildGEP(ctxt->builder,
       ctxt->stream, gep_indices, 2, "length_ptr");
+
   /* Now load them */
   LLVMValueRef index = LLVMBuildLoad(ctxt->builder,
       index_ptr, "index");
   LLVMValueRef length = LLVMBuildLoad(ctxt->builder,
       length_ptr, "length");
+
   /* Compare */
   LLVMValueRef icmp = LLVMBuildICmp(ctxt->builder, LLVMIntEQ, index, length, "index == length");
   /* Branch on comparison */
@@ -71,11 +91,9 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) {
   /* Basic block: success */
   LLVMPositionBuilderAtEnd(ctxt->builder, success);
   /* Set up a call to h_arena_malloc() to get an HParseResult */
-  LLVMValueRef make_result_args[] = {
-    ctxt->arena,
-    LLVMConstNull(ctxt->llvm_parsedtokenptr)
-  };
-  LLVMValueRef result_ptr = LLVMBuildCall(ctxt->builder,
+  make_result_args[0] = ctxt->arena;
+  make_result_args[1] = LLVMConstNull(ctxt->llvm_parsedtokenptr);
+  result_ptr = LLVMBuildCall(ctxt->builder,
       LLVMGetNamedFunction(ctxt->mod, "make_result"),
       make_result_args, 2, "result_ptr");
 
@@ -85,18 +103,14 @@ static bool end_llvm(HLLVMParserCompileContext *ctxt, void* env) {
   /* Basic block: end */
   LLVMPositionBuilderAtEnd(ctxt->builder, end);
   /* Set up a phi depending on whether we have a token or not */
-  LLVMValueRef rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv");
-  LLVMBasicBlockRef rv_phi_incoming_blocks[] = {
-    success,
-    entry
-  };
-  LLVMValueRef rv_phi_incoming_values[] = {
-    result_ptr,
-    LLVMConstNull(ctxt->llvm_parseresultptr)
-  };
+  rv = LLVMBuildPhi(ctxt->builder, ctxt->llvm_parseresultptr, "rv");
+  rv_phi_incoming_blocks[0] = success;
+  rv_phi_incoming_values[0] = result_ptr;
+  rv_phi_incoming_blocks[1] = entry;
+  rv_phi_incoming_values[1] = LLVMConstNull(ctxt->llvm_parseresultptr);
   LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2);
-  /* Return it */
-  LLVMBuildRet(ctxt->builder, rv);
+  /* Pass it back out to the caller */
+  *res = rv;
 
   return true;
 }
diff --git a/src/parsers/epsilon.c b/src/parsers/epsilon.c
index 4c5abc406a390b3fce592a6b041bca5518ebb0ae..2fd163a98a70772e87a0ebf98b83ca8542bf479f 100644
--- a/src/parsers/epsilon.c
+++ b/src/parsers/epsilon.c
@@ -21,10 +21,18 @@ static bool epsilon_ctrvm(HRVMProg *prog, void* env) {
 
 #ifdef HAMMER_LLVM_BACKEND
 
-static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env) {
+static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) {
+  /* Epsilon basic block */
+  LLVMBasicBlockRef epsilon_bb;
+  /* Args for make_result() */
+  LLVMValueRef make_result_args[2];
+  /* Return value from make_result() */
+  LLVMValueRef result_ptr;
+
+  if (!res) return false;
   if (!ctxt) return false;
 
-  LLVMBasicBlockRef epsilon_bb = LLVMAppendBasicBlock(ctxt->func, "epsilon");
+  epsilon_bb = LLVMAppendBasicBlock(ctxt->func, "epsilon");
 
   /* Basic block: epsilon */
   LLVMBuildBr(ctxt->builder, epsilon_bb);
@@ -34,15 +42,13 @@ static bool epsilon_llvm(HLLVMParserCompileContext *ctxt, void* env) {
    * For epsilon we make a null-token parse result like with end, but we
    * do it unconditionally.
    */
-  LLVMValueRef make_result_args[] = {
-    ctxt->arena,
-    LLVMConstNull(ctxt->llvm_parsedtokenptr)
-  };
-  LLVMValueRef result_ptr = LLVMBuildCall(ctxt->builder,
+  make_result_args[0] = ctxt->arena;
+  make_result_args[1] = LLVMConstNull(ctxt->llvm_parsedtokenptr);
+  result_ptr = LLVMBuildCall(ctxt->builder,
     LLVMGetNamedFunction(ctxt->mod, "make_result"),
     make_result_args, 2, "result_ptr");
-  /* Return it */
-  LLVMBuildRet(ctxt->builder, result_ptr);
+  /* Pass it back out */
+  *res = result_ptr;
 
   return true;
 }
diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c
index e4f97fb41cd1993a54941bef1a8ddc4838db9ee0..df9e3f79786fb9275e6dadd479db8a0e3cb611c6 100644
--- a/src/parsers/nothing.c
+++ b/src/parsers/nothing.c
@@ -27,15 +27,22 @@ static bool nothing_ctrvm(HRVMProg *prog, void* env) {
 
 #ifdef HAMMER_LLVM_BACKEND
 
-static bool nothing_llvm(HLLVMParserCompileContext *ctxt, void* env) {
+static bool nothing_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) {
+  /* Nothing entry bb */
+  LLVMBasicBlockRef entry;
+  /* Nothing result */
+  LLVMValueRef rv;
+
+  if (!res) return false;
   if (!ctxt) return false;
 
   /* This one just always returns NULL */
-  LLVMBasicBlockRef entry = LLVMAppendBasicBlock(ctxt->func, "nothing_entry");
+  entry = LLVMAppendBasicBlock(ctxt->func, "nothing_entry");
   LLVMBuildBr(ctxt->builder, entry);
   LLVMPositionBuilderAtEnd(ctxt->builder, entry);
-
-  LLVMBuildRet(ctxt->builder, LLVMConstNull(ctxt->llvm_parseresultptr));
+  rv = LLVMConstNull(ctxt->llvm_parseresultptr);
+  /* Pass it back out */
+  *res = rv;
 
   return true;
 }
diff --git a/src/parsers/token.c b/src/parsers/token.c
index 3899abe8d5abf0e45ba9ac72b544095f1019bfa2..8b031989ff38308a638856a76f105b15ce3c63bf 100644
--- a/src/parsers/token.c
+++ b/src/parsers/token.c
@@ -80,7 +80,10 @@ static bool token_ctrvm(HRVMProg *prog, void *env) {
  * the LLVM module globals.  We use this for longer tokens.
  */
 
-static bool token_llvm_with_global(HLLVMParserCompileContext *ctxt, HToken *t) {
+static bool token_llvm_with_global(
+    HLLVMParserCompileContext *ctxt,
+    HToken *t,
+    LLVMValueRef *res) {
   LLVMValueRef bits_args[3], bits, i, i_init, i_incr, str, str_const, len;
   LLVMValueRef r, c, mr, icmp_i_len, icmp_c_r, rv;
   LLVMValueRef c_gep_indices[2], c_gep;
@@ -186,8 +189,8 @@ static bool token_llvm_with_global(HLLVMParserCompileContext *ctxt, HToken *t) {
     LLVMConstNull(ctxt->llvm_parseresultptr)
   };
   LLVMAddIncoming(rv, rv_phi_incoming_values, rv_phi_incoming_blocks, 2);
-  /* Return it */
-  LLVMBuildRet(ctxt->builder, rv);
+  /* Pass it back out */
+  *res = rv;
 
   return true;
 }
@@ -197,7 +200,10 @@ static bool token_llvm_with_global(HLLVMParserCompileContext *ctxt, HToken *t) {
  * suitable for short tokens.  This also handles the zero-length token case.
  */
 
-static bool token_llvm_with_sequential_comparisons(HLLVMParserCompileContext *ctxt, HToken *t) {
+static bool token_llvm_with_sequential_comparisons(
+    HLLVMParserCompileContext *ctxt,
+    HToken *t,
+    LLVMValueRef *res) {
   HAllocator *mm__;
   LLVMValueRef bits, r, c, icmp, mr, rv;
   LLVMValueRef bits_args[3];
@@ -271,16 +277,18 @@ static bool token_llvm_with_sequential_comparisons(HLLVMParserCompileContext *ct
   /* Free the stuff we allocated to build the phi */
   h_free(bbs_into_phi);
   h_free(values_into_phi);
-  /* Return it */
-  LLVMBuildRet(ctxt->builder, rv);
+  /* Pass it back out */
+  *res = rv;
 
   return true;
 }
 
 #define TOKEN_LENGTH_USE_GLOBAL_CUTOFF 4
 
-static bool token_llvm(HLLVMParserCompileContext *ctxt, void* env) {
+static bool token_llvm(HLLVMParserCompileContext *ctxt, void* env, LLVMValueRef *res) {
   HToken *t;
+
+  if (!res) return false;
   if (!ctxt) return false;
 
   /* Get the token */
@@ -297,9 +305,9 @@ static bool token_llvm(HLLVMParserCompileContext *ctxt, void* env) {
    */
   if (t->len > TOKEN_LENGTH_USE_GLOBAL_CUTOFF &&
       t->len > 0) {
-    return token_llvm_with_global(ctxt, t);
+    return token_llvm_with_global(ctxt, t, res);
   } else {
-    return token_llvm_with_sequential_comparisons(ctxt, t);
+    return token_llvm_with_sequential_comparisons(ctxt, t, res);
   }
 }