From b1c26eb74ed82550708926f27b01ba3512b9580d Mon Sep 17 00:00:00 2001
From: Andrea Shepard <andrea@persephoneslair.org>
Date: Wed, 23 Nov 2016 06:27:21 +0000
Subject: [PATCH] Make h_llvm_make_tt_suint support variable bit lengths and
 signed/unsigned distinction

---
 src/backends/llvm/llvm.h       |  1 +
 src/backends/llvm/llvm_suint.c | 29 ++++++++++++++++++-----------
 src/parsers/ch.c               |  2 +-
 src/parsers/charset.c          |  2 +-
 4 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/src/backends/llvm/llvm.h b/src/backends/llvm/llvm.h
index 900f53ff..0721c373 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 0cce9a3e..571d6b00 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 2a46ae16..e22ed8c1 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 08b45f28..907fe927 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);
-- 
GitLab