OSDN Git Service

* i376.md (UNSPEC_MS_TO_SYSV_CALL): New constant.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 21 Dec 2008 13:28:26 +0000 (13:28 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 21 Dec 2008 13:28:26 +0000 (13:28 +0000)
(call_1_rex64_ms_sysv, call_value_0_rex64_ms_sysv,
call_value_1_rex64_ms_sysv): New patterns.
* i386.c (function_arg_ms_64): Pass magical value of -2 as callarg.
(ix86_expand_call): Emit extra clobbers for ms->sysv ABI calls.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142859 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index 98b4531..17054a9 100644 (file)
@@ -1,3 +1,12 @@
+2008-12-21  Jan Hubicka  <jh@suse.cz>
+           Kai Tietz <kai.tietz@onevision.com>
+
+       * i376.md (UNSPEC_MS_TO_SYSV_CALL): New constant.
+       (call_1_rex64_ms_sysv, call_value_0_rex64_ms_sysv,
+       call_value_1_rex64_ms_sysv): New patterns.
+       * i386.c (function_arg_ms_64): Pass magical value of -2 as callarg.
+       (ix86_expand_call): Emit extra clobbers for ms->sysv ABI calls.
+
 2008-12-21  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/alpha/alpha.c (alpha_pad_noreturn): New static function.
index 824a11d..bae3f42 100644 (file)
@@ -5690,9 +5690,10 @@ function_arg_ms_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 {
   unsigned int regno;
 
-  /* Avoid the AL settings for the Unix64 ABI.  */
+  /* We need to add clobber for MS_ABI->SYSV ABI calls in expand_call.
+     We use value of -2 to specify that current function call is MSABI.  */
   if (mode == VOIDmode)
-    return constm1_rtx;
+    return GEN_INT (-2);
 
   /* If we've run out of registers, it goes on the stack.  */
   if (cum->nregs == 0)
@@ -18095,11 +18096,16 @@ construct_plt_address (rtx symbol)
 
 void
 ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
-                 rtx callarg2 ATTRIBUTE_UNUSED,
+                 rtx callarg2,
                  rtx pop, int sibcall)
 {
   rtx use = NULL, call;
+  enum calling_abi function_call_abi;
 
+  if (callarg2 && INTVAL (callarg2) == -2)
+    function_call_abi = MS_ABI;
+  else
+    function_call_abi = SYSV_ABI;
   if (pop == const0_rtx)
     pop = NULL;
   gcc_assert (!TARGET_64BIT || !pop);
@@ -18155,6 +18161,18 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
       pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
       pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
       call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
+      gcc_assert (ix86_cfun_abi () != MS_ABI || function_call_abi != SYSV_ABI);
+    }
+  /* We need to represent that SI and DI registers are clobbered by SYSV calls.
+     */
+  if (ix86_cfun_abi () == MS_ABI && function_call_abi == SYSV_ABI)
+    {
+      rtx clobber1 = gen_rtx_CLOBBER (DImode, gen_rtx_REG (DImode, SI_REG));
+      rtx clobber2 = gen_rtx_CLOBBER (DImode, gen_rtx_REG (DImode, DI_REG));
+      rtx unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx),
+                                  UNSPEC_MS_TO_SYSV_CALL);
+      call = gen_rtx_PARALLEL (VOIDmode,
+                              gen_rtvec (4, call, unspec, clobber1, clobber2));
     }
 
   call = emit_call_insn (call);
index 068738d..c722389 100644 (file)
    (UNSPEC_LFENCE              45)
    (UNSPEC_PSADBW              46)
    (UNSPEC_LDDQU               47)
+   (UNSPEC_MS_TO_SYSV_CALL     48)
 
    ; Generic math support
    (UNSPEC_COPYSIGN            50)
 }
   [(set_attr "type" "call")])
 
+(define_insn "*call_1_rex64_ms_sysv"
+  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
+        (match_operand 1 "" ""))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+{
+  if (constant_call_address_operand (operands[0], Pmode))
+    return "call\t%P0";
+  return "call\t%A0";
+}
+  [(set_attr "type" "call")])
+
 (define_insn "*call_1_rex64_large"
   [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm"))
         (match_operand 1 "" ""))]
 }
   [(set_attr "type" "callv")])
 
+(define_insn "*call_value_0_rex64_ms_sysv"
+  [(set (match_operand 0 "" "")
+       (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
+             (match_operand:DI 2 "const_int_operand" "")))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+{
+  if (SIBLING_CALL_P (insn))
+    return "jmp\t%P1";
+  else
+    return "call\t%P1";
+}
+  [(set_attr "type" "callv")])
+
 (define_insn "*call_value_1"
   [(set (match_operand 0 "" "")
        (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm"))
 }
   [(set_attr "type" "callv")])
 
+(define_insn "*call_value_1_rex64_ms_sysv"
+  [(set (match_operand 0 "" "")
+       (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
+             (match_operand:DI 2 "" "")))
+   (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
+   (clobber (reg:DI SI_REG))
+   (clobber (reg:DI DI_REG))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+{
+  if (constant_call_address_operand (operands[1], Pmode))
+    return "call\t%P1";
+  return "call\t%A1";
+}
+  [(set_attr "type" "callv")])
+
 (define_insn "*call_value_1_rex64_large"
   [(set (match_operand 0 "" "")
        (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm"))