From 1195bdc6327827b3791bb0815b34652d2a8041cb Mon Sep 17 00:00:00 2001
From: Andrea Shepard <andrea@persephoneslair.org>
Date: Wed, 9 Nov 2016 18:33:32 +0000
Subject: [PATCH] Invoke LLVM parsers directly with a function pointer rather
 than LLVMRunFunction()

---
 src/backends/llvm.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/backends/llvm.c b/src/backends/llvm.c
index bf6f5133..39302c96 100644
--- a/src/backends/llvm.c
+++ b/src/backends/llvm.c
@@ -138,12 +138,22 @@ void h_llvm_free(HParser *parser) {
 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);
-  LLVMGenericValueRef args[] = {
-    LLVMCreateGenericValueOfPointer(input_stream),
-    LLVMCreateGenericValueOfPointer(arena)
-  };
-  LLVMGenericValueRef res = LLVMRunFunction(llvm_parser->engine, llvm_parser->func, 2, args);
-  HParseResult *ret = (HParseResult*)LLVMGenericValueToPointer(res);
+
+  // LLVMRunFunction only supports certain signatures for dumb reasons; it's this hack with
+  // memcpy and function pointers, or writing a shim in LLVM IR.
+  //
+  // LLVMGenericValueRef args[] = {
+  //   LLVMCreateGenericValueOfPointer(input_stream),
+  //   LLVMCreateGenericValueOfPointer(arena)
+  // };
+  // LLVMGenericValueRef res = LLVMRunFunction(llvm_parser->engine, llvm_parser->func, 2, args);
+  // HParseResult *ret = (HParseResult*)LLVMGenericValueToPointer(res);
+
+  void *parse_func_ptr_v;
+  HParseResult * (*parse_func_ptr)(HInputStream *input_stream, HArena *arena);
+  parse_func_ptr_v = LLVMGetPointerToGlobal(llvm_parser->engine, llvm_parser->func);
+  memcpy(&parse_func_ptr, &parse_func_ptr_v, sizeof(parse_func_ptr));
+  HParseResult *ret = parse_func_ptr(input_stream, arena);
   if (ret) {
     ret->arena = arena;
     if (!input_stream->overrun) {
-- 
GitLab