changeset 741:ebf5ae3f3863

i64 continue...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 09 Nov 2010 17:56:33 +0900
parents 8cd40338aee6
children bdae6a221174
files .gdbinit mc-code-i64.c test/tstdarg.c
diffstat 3 files changed, 159 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/.gdbinit	Mon Nov 08 22:30:10 2010 +0900
+++ b/.gdbinit	Tue Nov 09 17:56:33 2010 +0900
@@ -20,7 +20,8 @@
 # r -s test/tmpa.c
 # r -s test/code-gen-all.c
 # r -s mc-code-powerpc.c
-r -s test/macro.c
+# r -s test/macro.c
+r -s test/basic.c
 # r -s test/strinit.c
 # r -s test/arg.c
 # r -s -DINLINE=inline test/strinit.c
--- a/mc-code-i64.c	Mon Nov 08 22:30:10 2010 +0900
+++ b/mc-code-i64.c	Tue Nov 09 17:56:33 2010 +0900
@@ -305,7 +305,7 @@
 	   %rdi  arg1
             see enter/enter1/leave           see code_enter
  */
-// static int arg_offset;
+static int arg_offset_v;
 
 static int code_disp_label;
 
@@ -371,7 +371,7 @@
 #define REG_EAX   7
 #define REG_EBX   8
 #define is_int_reg(reg) (1<=reg&&reg<MAX_REGISTER)
-#define is_float_reg(reg) (RET_FREGISTER<=reg&&reg<REAL_MAX_REGISTER)
+#define is_float_reg(reg) (RET_FREGISTER<=reg&&reg<FREG_OFFSET+REAL_MAX_DREGISTER)
 
 //  return value register
 #define RET_FREGISTER   18
@@ -1083,6 +1083,75 @@
     printf("\n");
 }
 
+/*
+    store input argument into stack
+    we need this always because of one path compiler
+ */
+static void
+code_save_input_registers(int dots)
+{
+    int args;
+    NMTBL *n;
+    int reg;
+    int tag;
+    int t;
+    int offset = 0;
+    int reg_var = 0;
+    int freg_var = 0;
+
+    for(args = fnptr->dsp;args;args = cadr(args)) {
+        n = ncadddr(args);
+        tag = n->sc;
+        reg = n->dsp;
+        if (!n||n==&null_nptr) error(REG_ERR);
+        if (tag==REGISTER) {
+            n->dsp = offset;
+            offset+=SIZE_OF_INT;
+            t = INT;
+            reg_var++;
+        } else if (tag==FREGISTER) {
+            n->dsp = offset;
+            t = n->ty;
+	    offset+=SIZE_OF_FLOAT; 
+            freg_var++;
+        } else if (tag==DREGISTER) {
+            n->dsp = offset;
+            t = n->ty;
+            offset+=SIZE_OF_DOUBLE; 
+            freg_var++;
+        } else if (tag==LREGISTER) {
+            n->dsp = offset;
+            t = n->ty;
+            offset+=SIZE_OF_LONGLONG; 
+            reg_var++;
+        } else {
+            offset += size(n->ty);
+            continue;
+        }
+        n->sc  = LVAR;
+        g_expr_u(assign_expr0(list3n(LVAR,n->dsp,0),list3n(tag,reg,n),t,t));
+        if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) {
+            free_register(reg);
+        }
+    }
+    if (dots) {
+        while ((reg = get_input_register_var(reg_var,0,0))) {
+            g_expr_u(assign_expr0(
+                list3n(LVAR,offset,0),reg,INT,INT));
+            offset+=SIZE_OF_INT;
+            reg_var++;
+        }
+	//  Intel64 keeps number of double value in %al
+        while ((reg = get_input_dregister_var(freg_var,0,0,0))) {
+            g_expr_u(assign_expr0(
+                list3n(LVAR,offset,0),reg,DOUBLE,DOUBLE));
+            offset+=SIZE_OF_DOUBLE;
+            freg_var++;
+        }
+    }
+    // my_func_args = offset;
+}
+
 void
 code_arg_register(NMTBL *fnptr)
 {
@@ -1092,39 +1161,65 @@
     int freg_var = 0;
     int type;
     int reg;
-    int offset = 0;
     int is_code0 = is_code(fnptr);
-
+    int dots;
+    arg_offset_v = 0;
+
+    function_type(fnptr->ty,&dots);
     while (args) {
         /* process in reverse order */
         n = ncadddr(args);
         type = n->ty;
-	// n->dsp = offset;
-// printf("###  %s %d %d\n",n->nm,n->dsp,n->ty);
         if (scalar(type)) {
-	    int sz =size(type)<=SIZE_OF_INT?SIZE_OF_INT:size(type); 
             if ((reg = get_input_register_var(reg_var,n,is_code0))) {
                 n->sc = REGISTER;
                 n->dsp = cadr(reg);
                 regs[n->dsp]= INPUT_REG;
                 reg_var++;
-                caddr(args)=sz;
+                arg_offset_v += (caddr(args)=SIZE_OF_INT);
             }
-	    offset+=sz;
-        } else if (type==FLOAT||type==DOUBLE) {
+        } else if (type==FLOAT) {
+            if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) {
+                n->sc = DREGISTER;
+                n->dsp = cadr(reg);
+                regs[n->dsp]= INPUT_REG;
+                freg_var++;
+                arg_offset_v += (caddr(args)=size(type));
+            }
+        } else if (type==DOUBLE) {
             if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) {
                 n->sc = DREGISTER;
                 n->dsp = cadr(reg);
                 regs[n->dsp]= INPUT_REG;
                 freg_var++;
-                caddr(args)=size(type); /* why we need this? */
+                arg_offset_v += (caddr(args)=size(type));
             }
-	    offset+=size(type);
-        } else
-	    offset+=size(type);
+        } else if (type==LONGLONG||type==ULONGLONG) {
+            if ((reg = get_input_lregister_var(reg_var,n,is_code0))) {
+                n->sc = LREGISTER;
+                n->dsp = cadr(reg);
+                regs[n->dsp]= INPUT_REG;
+                reg_var+=1;
+                arg_offset_v += (caddr(args)=size(type));
+            }
+        }
         args = cadr(args);
     }
-}
+    if (is_function(fnptr)) {
+#ifndef __APPLE__
+        if (dots) {
+		//  %al の値によって float を適切にloadする必要がある  sigh...
+                arg_offset_v =
+                    MAX_INPUT_REGISTER_VAR*SIZE_OF_INT +
+                    MAX_INPUT_DREGISTER_VAR*SIZE_OF_DOUBLE;
+        }
+        printf(".set %s%d, %d\n",lpfx, arg_offset_label,
+            arg_offset_v+ arg_offset);
+#endif
+        code_save_input_registers(dots);
+    }
+}
+
 
 void 
 gexpr_init(void)
@@ -1863,10 +1958,9 @@
     }
     if(scalar(t)) {
         nargs ++ ; reg_arg++;
-        if (size(t)>SIZE_OF_INT) nargs++;
     } else if (t==LONGLONG||t==ULONGLONG) {
+        nargs ++ ; reg_arg++;
         nargs ++ ; 
-        nargs ++ ; reg_arg++;
     } else if (t==FLOAT) {
         freg_arg++;
         nargs += size(t)/SIZE_OF_INT;
@@ -1885,52 +1979,61 @@
 }
 
 
+
 #define AS_SAVE 1
 #define AS_ARG  0
 
+/*
+     set storage type of caller's arguments
+         register or stack
+     this muse corprate with code_arg_register();
+     if AS_SAVE is set, register variable (or temporary local variable)
+     is used.
+ */
+
 static int
-get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) 
+get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg)
 {
+    t = type_value(t);
+    if (t>=0&&(car(t)==BIT_FIELD)) {
+        t = type_value(cadr(t));
+    }
     if(scalar(t)) {
         if (mode==AS_SAVE) {
-	    if (parse_mode)
-		return get_register_var(0);
-	    return list3n(LVAR,new_lvar(size(t)),0);
-        } else 
+            return get_register_var(0);
+        } else if (reg_arg>=MAX_INPUT_REGISTER_VAR) {
             return list3n(LVAR,caller_arg_offset_v(nargs),0);
+        } else
+            return get_input_register_var(reg_arg,0,0);
     } else if (t==LONGLONG||t==ULONGLONG) {
         if (mode==AS_SAVE) {
-	    if (parse_mode)
-		return get_lregister_var(0);
-	    return list3n(LVAR,new_lvar(size(t)),0);
-        } else 
+            return get_lregister_var(0);
+        } else if (reg_arg>=MAX_INPUT_REGISTER_VAR)  {
             return list3n(LVAR,caller_arg_offset_v(nargs),0);
+        } else
+            return get_input_lregister_var(reg_arg,0,0);
     } else if (t==FLOAT) {
         if (mode==AS_SAVE) {
-	    if (parse_mode)
-		return get_dregister_var(0,0);
-	    return list3n(LVAR,new_lvar(size(t)),0);
+            return get_dregister_var(0,0);
+        } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
+            return list3n(LVAR,caller_arg_offset_v(nargs),0);
         } else
-            return list3n(LVAR,caller_arg_offset_v(nargs),0);
+            return get_input_dregister_var(freg_arg,0,0,0);
     } else if (t==DOUBLE) {
         if (mode==AS_SAVE) {
-	    if (parse_mode)
-		return get_dregister_var(0,1);
-	    return list3n(LVAR,new_lvar(size(t)),0);
+            return get_dregister_var(0,1);
+        } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) {
+            return list3n(LVAR,caller_arg_offset_v(nargs),0);
         } else
-            return list3n(LVAR,caller_arg_offset_v(nargs),0);
+            return get_input_dregister_var(freg_arg,0,0,1);
     } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) {
         if (mode==AS_SAVE) {
-	    if (parse_mode)
-		return get_register_var(0);
-	    return list3n(LVAR,new_lvar(size(t)),0);
+            return get_register_var(0);
         } else
             return list3n(LVAR,caller_arg_offset_v(nargs),0);
     } else {
         error(-1);
-	if (parse_mode)
-	    return get_register_var(0);
-	return list3n(LVAR,new_lvar(size(t)),0);
+        return get_register_var(0);
     }
 }
 
@@ -2097,7 +2200,6 @@
         }
 #endif
     }
-
     nargs = reg_arg = freg_arg = 0;
     // calc stack arguments first, it may requires extra registers,
     // and we can still use input registers now.
@@ -2116,6 +2218,10 @@
         g_expr_u(car(arg_assign));
     }
     clear_ptr_cache();
+    if (dots) {
+	// needs number of fregister in double
+	printf("\tmovl $%d,%%eax\n", freg_arg);
+    }
     code_call(e2,fn,jmp);
     free_register_var(reg_arg_list);
     if (ret_type==DOUBLE||ret_type==FLOAT) {
@@ -3211,10 +3317,10 @@
     printf("\t%s %s,",fstore(d),fregister_name(freg)); lvar(e2); printf("\n");
 }
 
-void code_dassign_dregister(int e,int d,int freg)
+void code_dassign_dregister(int e,int d,int f)
 {
-    int reg = cadr(e);
-    printf("\tmovapd %s,%s",fregister_name(freg),register_name(reg,0)); 
+    use_float(d,f);
+    printf("\tmovapd %s,%s",fregister_name(f),fregister_name(e)); 
 }
 
 void code_dassign(int e2,int freg,int d)
@@ -3409,7 +3515,7 @@
 
 void code_drlvar(int e2,int d,int freg)
 { 
-    printf("\t%s ",fload(d)); lvar(e2); printf(",%s\n", register_name(freg,0));
+    printf("\t%s ",fload(d)); lvar(e2); printf(",%s\n", fregister_name(freg));
 }
 
 void code_cmp_drgvar(int e2,int reg,int d,int label,int cond)
@@ -3707,7 +3813,11 @@
 void 
 code_dregister(int e2,int freg,int d)
 {
-    error(-1);
+    use_float(d,freg);
+    if (freg!=e2) {
+        if (is_int_reg(e2)) error(-1);
+        printf("\ttmovap%s %s,%s\n",d?"d":"s",fregister_name(freg),fregister_name(e2));
+    }
 }
 
 void
--- a/test/tstdarg.c	Mon Nov 08 22:30:10 2010 +0900
+++ b/test/tstdarg.c	Tue Nov 09 17:56:33 2010 +0900
@@ -20,7 +20,7 @@
 	if (t=='i') {
 	    i = va_arg(ap,int);
 	    printf("#0021:int arg: %d\n",i);
-#if 0
+#if 0        /*  ‘float’ is promoted to ‘double’ when passed through ‘...’ */
 	} else if (t=='f') {
 	    f = va_arg(ap,float);
 	    printf("#0025:float arg: %g\n",f);