diff --git a/src/backends/llvm/llvm.h b/src/backends/llvm/llvm.h
index 900f53ff337d664d77b73a0974ca3c1b26c58cbe..0721c3733b818877090af2e420d611902b375e5b 100644
--- a/src/backends/llvm/llvm.h
+++ b/src/backends/llvm/llvm.h
@@ -37,6 +37,7 @@ bool h_llvm_make_charset_membership_test(HLLVMParserCompileContext *ctxt,
                                          LLVMValueRef r, HCharset cs,
                                          LLVMBasicBlockRef yes, LLVMBasicBlockRef no);
 void h_llvm_make_tt_suint(HLLVMParserCompileContext *ctxt,
+                          uint8_t length, uint8_t signedp,
                           LLVMValueRef r, LLVMValueRef *mr_out);
 
 #endif // #ifndef HAMMER_LLVM__H
diff --git a/src/backends/llvm/llvm_suint.c b/src/backends/llvm/llvm_suint.c
index 0cce9a3e33b71821391fefd3e152c66b6a9c1635..571d6b00d39cbfc30f7b66d65c44e6554372ec0b 100644
--- a/src/backends/llvm/llvm_suint.c
+++ b/src/backends/llvm/llvm_suint.c
@@ -24,6 +24,7 @@
  */
 
 void h_llvm_make_tt_suint(HLLVMParserCompileContext *ctxt,
+                          uint8_t length, uint8_t signedp,
                           LLVMValueRef r, LLVMValueRef *mr_out) {
   /* Set up call to h_arena_malloc() for a new HParsedToken */
   LLVMValueRef tok_size = LLVMConstInt(LLVMInt32Type(), sizeof(HParsedToken), 0);
@@ -36,29 +37,36 @@ void h_llvm_make_tt_suint(HLLVMParserCompileContext *ctxt,
   LLVMValueRef tok = LLVMBuildBitCast(ctxt->builder, amalloc, ctxt->llvm_parsedtokenptr, "tok");
 
   /*
-   * tok->token_type = TT_UINT;
+   * tok->token_type = signedp ? TT_SINT : 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);
+  LLVMBuildStore(ctxt->builder, LLVMConstInt(LLVMInt32Type(),
+        signedp ? TT_SINT : TT_UINT, 0), toktype);
 
   /*
+   * tok->sint = r;
+   * or
    * 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
+   * the token_data field is a union, but either an int64_t or a uint64_t in the
+   * cases we can be called for.
    */
-  LLVMBuildStore(ctxt->builder, LLVMBuildZExt(ctxt->builder, r, LLVMInt64Type(), "r"), tokdata);
+  if (length < 64) {
+    /* Extend needed */
+    LLVMValueRef r_ext;
+    if (signedp) r_ext = LLVMBuildSExt(ctxt->builder, r, LLVMInt64Type(), "r_sext");
+    else r_ext = LLVMBuildZExt(ctxt->builder, r, LLVMInt64Type(), "r_zext");
+    LLVMBuildStore(ctxt->builder, r_ext, tokdata);
+  } else {
+    LLVMBuildStore(ctxt->builder, r, tokdata);
+  }
   /*
    * Store the index from the stream into the token
    */
@@ -71,8 +79,7 @@ void h_llvm_make_tt_suint(HLLVMParserCompileContext *ctxt,
   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);
+  LLVMBuildStore(ctxt->builder, LLVMConstInt(LLVMInt64Type(), length, 0), tokbitlen);
 
   /*
    * Now call make_result()
diff --git a/src/parsers/ch.c b/src/parsers/ch.c
index 2a46ae16be33eea2017ec73e2fc4ab30cf3cbe7b..e22ed8c105673fd7b989b60e623e83ee9bead050 100644
--- a/src/parsers/ch.c
+++ b/src/parsers/ch.c
@@ -91,7 +91,7 @@ static bool ch_llvm(HLLVMParserCompileContext *ctxt, void* env) {
 
   /* Make a token */
   LLVMValueRef mr;
-  h_llvm_make_tt_suint(ctxt, r, &mr);
+  h_llvm_make_tt_suint(ctxt, 8, 0, r, &mr);
 
   // br label %ch_end
   LLVMBuildBr(ctxt->builder, end);
diff --git a/src/parsers/charset.c b/src/parsers/charset.c
index 08b45f280be9d0c8d717dd0bac3126a2d3c50da6..907fe927a79184c3c292a96630a49fc83fc0b1e3 100644
--- a/src/parsers/charset.c
+++ b/src/parsers/charset.c
@@ -116,7 +116,7 @@ static bool cs_llvm(HLLVMParserCompileContext *ctxt, void* env) {
   LLVMPositionBuilderAtEnd(ctxt->builder, success);
 
   LLVMValueRef mr;
-  h_llvm_make_tt_suint(ctxt, r, &mr);
+  h_llvm_make_tt_suint(ctxt, 8, 0, r, &mr);
 
   /* br label %ch_end */
   LLVMBuildBr(ctxt->builder, end);