Browse Source

Add partial support for arithmetic between 8 bytes integers.

Giovanni Mascellani 5 years ago
parent
commit
dbfe938193
3 changed files with 48 additions and 24 deletions
  1. 32 18
      asmg/c_compile.g
  2. 2 0
      asmg/c_test.g
  3. 14 6
      diskfs/tests/test_llong.c

+ 32 - 18
asmg/c_compile.g

@@ -2574,8 +2574,13 @@ fun lctx_int_convert 4 {
   @from_idx 1 param = ;
   @to_idx 0 param = ;
 
-  to_idx is_integer_type "lctx_int_convert: target is not an integer type" assert_msg ;
+  # Treat pointers as integers
+  if ctx from_idx cctx_get_type TYPE_KIND take TYPE_KIND_POINTER == {
+    @from_idx TYPE_INT = ;
+  }
+
   from_idx is_integer_type "lctx_int_convert: source is not an integer type" assert_msg ;
+  to_idx is_integer_type "lctx_int_convert: target is not an integer type" assert_msg ;
 
   if ctx from_idx cctx_type_footprint 4 == {
     # pop eax
@@ -2771,38 +2776,40 @@ fun ast_push_value_arith 3 {
   $type1
   $type2
   $type_idx
+  $large_idx
   if is_prefix ! {
     @type1 ast AST_LEFT take ctx lctx ast_eval_type = ;
   }
   @type2 ast AST_RIGHT take ctx lctx ast_eval_type = ;
   @type_idx ast ctx lctx ast_eval_type = ;
-
-  # Sanity check: both operands must fit in 4 bytes
-  if is_prefix ! {
-    ctx type1 cctx_type_footprint 4 == "ast_push_value_arith: error 1" assert_msg ;
+  if type_idx TYPE_LONG == type_idx TYPE_ULONG == || {
+    @large_idx type_idx = ;
+  } else {
+    @large_idx TYPE_LONG = ;
   }
-  ctx type2 cctx_type_footprint 4 == "ast_push_value_arith: error 2" assert_msg ;
+  ctx large_idx cctx_type_footprint 8 == "ast_push_value_arith: error 1" assert_msg ;
+
+  # push ebx
+  ctx 0x53 cctx_emit ;
 
   # Recursively evalute both operands
   if is_prefix ! {
     ast AST_LEFT take ctx lctx ast_push_value ;
+    lctx ctx type1 large_idx lctx_int_convert ;
   }
   ast AST_RIGHT take ctx lctx ast_push_value ;
+  lctx ctx type2 large_idx lctx_int_convert ;
 
-  # Pop right result, promote it and store in ECX
-  if type2 is_integer_type {
-    lctx ctx type2 type_idx lctx_int_convert ;
-  }
-  # pop ecx
+  # Pop right result and store in EBX:ECX
+  # pop ecx; pop ebx
   ctx 0x59 cctx_emit ;
+  ctx 0x5b cctx_emit ;
 
-  # Pop left result, promote it and store in EAX
+  # Pop left result and store in EDX:EAX
   if is_prefix ! {
-    if type1 is_integer_type {
-      lctx ctx type1 type_idx lctx_int_convert ;
-    }
-    # pop eax
+    # pop eax; pop edx
     ctx 0x58 cctx_emit ;
+    ctx 0x5a cctx_emit ;
   }
 
   # Invoke the operation specific operation
@@ -3076,9 +3083,16 @@ fun ast_push_value_arith 3 {
 
   processed "ast_push_value_arith: not implemented" assert_msg ;
 
-  # Push result stored in EAX
-  # push eax
+  # pop ebx
+  ctx 0x5b cctx_emit ;
+
+  # Push result stored in EDX:EAX
+  # push edx; push eax
+  ctx 0x52 cctx_emit ;
   ctx 0x50 cctx_emit ;
+
+  # Convert result to the output type
+  lctx ctx large_idx type_idx lctx_int_convert ;
 }
 
 fun cctx_gen_push_data 2 {

+ 2 - 0
asmg/c_test.g

@@ -142,6 +142,8 @@ fun c_run_testcases 0 {
   tests "/disk1/tests/test_lang.c" "test_logic" 1 "" c_run_testcase ;
 
   tests "/disk1/tests/test_llong.c" "test_llong" 1 "" c_run_testcase ;
+  tests "/disk1/tests/test_llong.c" "test_llong_sum" 1 "" c_run_testcase ;
+  tests "/disk1/tests/test_llong.c" "test_llong_sum2" 1 "" c_run_testcase ;
 
   tests "/disk1/tests/test_stdio.c" "test_fputs" 1 "This is a test string\n" c_run_testcase ;
   tests "/disk1/tests/test_stdio.c" "test_puts" 1 "This is a test string\n" c_run_testcase ;

+ 14 - 6
diskfs/tests/test_llong.c

@@ -21,9 +21,17 @@ int test_llong() {
     return y == 10;
 }
 
-/* int test_llong_sum() { */
-/*     long long x = 10; */
-/*     long long y = 20; */
-/*     long long z = x + y; */
-/*     return z == 30; */
-/* } */
+int test_llong_sum() {
+    long long x = 10;
+    long long y = 20;
+    long long z = x + y;
+    return z == 30;
+}
+
+int test_llong_sum2() {
+    unsigned long long x = 4000000000;
+    unsigned long long y = 4000000000;
+    unsigned long long z = x + y;
+    unsigned long long w = 2 * x;
+    return z == w;
+}