From 1fe8d40ebdb232ab6be27af1a3b94a2869cc3779 Mon Sep 17 00:00:00 2001
From: notaz <notasas@gmail.com>
Date: Sun, 18 Oct 2015 18:00:58 +0300
Subject: [PATCH] translate: support for data imports

---
 c_auto.h           |  6 ++++++
 run_imp.sh         | 10 ++++++++--
 tools/protoparse.h | 10 ++++++++++
 tools/translate.c  | 25 +++++++++++++++++++------
 4 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/c_auto.h b/c_auto.h
index 9b34f88..b3b1afc 100644
--- a/c_auto.h
+++ b/c_auto.h
@@ -35,6 +35,12 @@ typedef struct {
 #define BYTE2(x)    (*((u8*)&(x)+2))
 #define BYTE3(x)    (*((u8*)&(x)+3))
 
+#ifndef __WINE__
+#define DECL_IMPORT __declspec(dllimport)
+#else
+#define DECL_IMPORT
+#endif
+
 #define memcpy_0 memcpy
 
 #define noreturn __attribute__((noreturn))
diff --git a/run_imp.sh b/run_imp.sh
index 15381b7..b069eba 100755
--- a/run_imp.sh
+++ b/run_imp.sh
@@ -37,8 +37,14 @@ cat $implist | while read i; do
     done
   sym=`cat $tmpsym`
   if test -z "$sym"; then
-    echo "$target_s: no file/sym for $i"
-    exit 1
+    # could be a data import
+    if test -n "$data_symf" && grep -q "$si" $data_symf; then
+      continue
+    else
+      echo "$target_s: no file/sym for $i"
+      rm $target_s
+      exit 1
+    fi
   fi
 
   echo ".globl $i" >> $target_s
diff --git a/tools/protoparse.h b/tools/protoparse.h
index a3eb0e6..7acd63a 100644
--- a/tools/protoparse.h
+++ b/tools/protoparse.h
@@ -42,8 +42,10 @@ struct parsed_proto {
 	unsigned int is_fastcall:1;
 	unsigned int is_vararg:1;     // vararg func
 	unsigned int is_fptr:1;
+	unsigned int is_import:1;     // data import
 	unsigned int is_noreturn:1;
 	unsigned int is_unresolved:1;
+	unsigned int is_guessed:1;    // for extra checking
 	unsigned int is_userstack:1;
 	unsigned int is_include:1;    // not from top-level header
 	unsigned int is_osinc:1;      // OS/system library func
@@ -402,6 +404,9 @@ static int parse_arg(char **p_, struct parsed_proto_arg *arg, int xarg)
 	if (ret < 0)
 		return -1;
 
+	if (IS_START(arg->pp->name, "guess"))
+		arg->pp->is_guessed = 1;
+
 	// we don't use actual names right now...
 	snprintf(arg->pp->name, sizeof(arg->pp->name), "a%d", xarg);
 
@@ -462,6 +467,11 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp)
 			p = sskip(p + l + 1);
 	}
 
+	if (IS_START(p, "DECL_IMPORT ")) {
+		pp->is_import = 1;
+		p = sskip(p + 12);
+	}
+
 	ret = check_type(p, &pp->ret_type);
 	if (ret <= 0) {
 		printf("%s:%d:%zd: unhandled return in '%s'\n",
diff --git a/tools/translate.c b/tools/translate.c
index 50af3bf..e6ab802 100644
--- a/tools/translate.c
+++ b/tools/translate.c
@@ -2142,7 +2142,7 @@ static void check_func_pp(struct parsed_op *po,
 }
 
 static const char *check_label_read_ref(struct parsed_op *po,
-  const char *name)
+  const char *name, int *is_import)
 {
   const struct parsed_proto *pp;
 
@@ -2153,6 +2153,9 @@ static const char *check_label_read_ref(struct parsed_op *po,
   if (pp->is_func)
     check_func_pp(po, pp, "ref");
 
+  if (is_import != NULL)
+    *is_import = pp->is_import;
+
   return pp->name;
 }
 
@@ -2171,6 +2174,7 @@ static char *out_src_opr(char *buf, size_t buf_size,
   char tmp1[256], tmp2[256];
   char expr[256];
   const char *name;
+  int is_import = 0;
   char *p;
   int ret;
 
@@ -2243,7 +2247,11 @@ static char *out_src_opr(char *buf, size_t buf_size,
     break;
 
   case OPT_LABEL:
-    name = check_label_read_ref(po, popr->name);
+    name = check_label_read_ref(po, popr->name, &is_import);
+    if (is_import)
+      // for imported data, asm is loading the offset
+      goto do_offset;
+
     if (cast[0] == 0 && popr->is_ptr)
       cast = "(u32)";
 
@@ -2259,7 +2267,8 @@ static char *out_src_opr(char *buf, size_t buf_size,
     break;
 
   case OPT_OFFSET:
-    name = check_label_read_ref(po, popr->name);
+  do_offset:
+    name = check_label_read_ref(po, popr->name, NULL);
     if (cast[0] == 0)
       cast = "(u32)";
     if (is_lea)
@@ -6310,6 +6319,9 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
 
       if (pp->is_fptr && !(pp->name[0] != 0 && pp->is_arg)) {
         if (pp->name[0] != 0) {
+          if (IS_START(pp->name, "guess"))
+            pp->is_guessed = 1;
+
           memmove(pp->name + 2, pp->name, strlen(pp->name) + 1);
           memcpy(pp->name, "i_", 2);
 
@@ -7347,9 +7359,10 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt)
           fprintf(fout, "%s%s = %s;\n", buf3, pp->name,
             out_src_opr(buf1, sizeof(buf1), po, &po->operand[0],
               "(void *)", 0));
-          if (pp->is_unresolved || IS_START(pp->name, "i_guess"))
-            fprintf(fout, "%sunresolved_call(\"%s:%d\", %s);\n",
-              buf3, asmfn, po->asmln, pp->name);
+        }
+        if (pp->is_fptr && (pp->is_unresolved || pp->is_guessed)) {
+          fprintf(fout, "%sunresolved_call(\"%s:%d\", %s);\n",
+            buf3, asmfn, po->asmln, pp->name);
         }
 
         fprintf(fout, "%s", buf3);
-- 
2.39.5