From af301180802a5c9ae23a5fef2f87c7f4f226ce04 Mon Sep 17 00:00:00 2001
From: Andrea Shepard <andrea@persephoneslair.org>
Date: Sat, 12 Nov 2016 02:35:37 +0000
Subject: [PATCH] Move TT_UINT token construction LLVM into reusable function
 from ch_llvm()

---
 src/backends/llvm.c | 77 +++++++++++++++++++++++++++++++++++++++++++++
 src/llvm.h          |  4 +++
 src/parsers/ch.c    | 39 ++---------------------
 3 files changed, 84 insertions(+), 36 deletions(-)

diff --git a/src/backends/llvm.c b/src/backends/llvm.c
index 1c422591..edbe3ebb 100644
--- a/src/backends/llvm.c
+++ b/src/backends/llvm.c
@@ -145,6 +145,83 @@ 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(LLVMModuleRef mod, LLVMBuilderRef builder,
+                          LLVMValueRef stream, LLVMValueRef arena,
+                          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[] = { arena, tok_size };
+  /* %h_arena_malloc = call void* @h_arena_malloc(%struct.HArena_.1* %1, i32 48) */
+  LLVMValueRef amalloc = LLVMBuildCall(builder, LLVMGetNamedFunction(mod, "h_arena_malloc"),
+      amalloc_args, 2, "h_arena_malloc");
+  /* %tok = bitcast void* %h_arena_malloc to %struct.HParsedToken_.2* */
+  LLVMValueRef tok = LLVMBuildBitCast(builder, amalloc, 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(builder, tok, 0, "token_type");
+  /* store i32 8, i32* %token_type */
+  LLVMBuildStore(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(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(builder, LLVMBuildZExt(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(builder, tok, 2, "t_index");
+  /* %s_index = getelementptr inbounds %struct.HInputStream_.0, %struct.HInputStream_.0* %0, i32 0, i32 2 */
+  LLVMValueRef streamindex = LLVMBuildStructGEP(builder, stream, 2, "s_index");
+  /* %4 = load i64, i64* %s_index */
+  /* store i64 %4, i64* %t_index */
+  LLVMBuildStore(builder, LLVMBuildLoad(builder, streamindex, ""), tokindex);
+  /* Store the bit length into the token */
+  LLVMValueRef tokbitlen = LLVMBuildStructGEP(builder, tok, 3, "bit_length");
+  /* TODO handle multiple bit lengths */
+  LLVMBuildStore(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[] = { arena, tok };
+  LLVMValueRef mr = LLVMBuildCall(builder, LLVMGetNamedFunction(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/llvm.h b/src/llvm.h
index 3b6c7ed5..927241f7 100644
--- a/src/llvm.h
+++ b/src/llvm.h
@@ -9,4 +9,8 @@
 LLVMTypeRef llvm_inputstream, llvm_inputstreamptr, llvm_arena, llvm_arenaptr;
 LLVMTypeRef llvm_parsedtoken, llvm_parsedtokenptr, llvm_parseresult, llvm_parseresultptr;
 
+void h_llvm_make_tt_suint(LLVMModuleRef mod, LLVMBuilderRef builder,
+                          LLVMValueRef stream, LLVMValueRef arena, 
+                          LLVMValueRef r, LLVMValueRef *mr_out);
+
 #endif // #ifndef HAMMER_LLVM__H
diff --git a/src/parsers/ch.c b/src/parsers/ch.c
index a7ac9bec..1c396a2f 100644
--- a/src/parsers/ch.c
+++ b/src/parsers/ch.c
@@ -85,42 +85,9 @@ static bool ch_llvm(LLVMBuilderRef builder, LLVMValueRef func, LLVMModuleRef mod
   // Basic block: success
   LLVMPositionBuilderAtEnd(builder, success);
 
-  // Set up call to h_arena_malloc() for a new HParsedToken
-  LLVMValueRef tok_size = LLVMConstInt(LLVMInt32Type(), sizeof(HParsedToken), 0);
-  LLVMValueRef amalloc_args[] = { arena, tok_size };
-  // %h_arena_malloc = call void* @h_arena_malloc(%struct.HArena_.1* %1, i32 48)
-  LLVMValueRef amalloc = LLVMBuildCall(builder, LLVMGetNamedFunction(mod, "h_arena_malloc"), amalloc_args, 2, "h_arena_malloc");
-  // %3 = bitcast void* %h_arena_malloc to %struct.HParsedToken_.2*
-  LLVMValueRef tok = LLVMBuildBitCast(builder, amalloc, llvm_parsedtokenptr, "");
-
-  // tok->token_type = TT_UINT;
-  //
-  // %token_type = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 0
-  LLVMValueRef toktype = LLVMBuildStructGEP(builder, tok, 0, "token_type");
-  // store i32 8, i32* %token_type
-  LLVMBuildStore(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(builder, tok, 1, "token_data");
-  // %r = zext i8 %2 to i64
-  // store i64 %r, i64* %token_data
-  LLVMBuildStore(builder, LLVMBuildZExt(builder, r, LLVMInt64Type(), "r"), tokdata);
-  // %t_index = getelementptr inbounds %struct.HParsedToken_.2, %struct.HParsedToken_.2* %3, i32 0, i32 2
-  LLVMValueRef tokindex = LLVMBuildStructGEP(builder, tok, 2, "t_index");
-  // %s_index = getelementptr inbounds %struct.HInputStream_.0, %struct.HInputStream_.0* %0, i32 0, i32 2
-  LLVMValueRef streamindex = LLVMBuildStructGEP(builder, stream, 2, "s_index");
-  // %4 = load i64, i64* %s_index
-  // store i64 %4, i64* %t_index
-  LLVMBuildStore(builder, LLVMBuildLoad(builder, streamindex, ""), tokindex);
-  LLVMValueRef tokbitlen = LLVMBuildStructGEP(builder, tok, 3, "bit_length");
-  LLVMBuildStore(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[] = { arena, tok };
-  LLVMValueRef mr = LLVMBuildCall(builder, LLVMGetNamedFunction(mod, "make_result"), result_args, 2, "make_result");
+  /* Make a token */
+  LLVMValueRef mr;
+  h_llvm_make_tt_suint(mod, builder, stream, arena, r, &mr);
 
   // br label %ch_end
   LLVMBuildBr(builder, end);
-- 
GitLab