This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: sysv/ms_abi attribute fix, part 5, proper call clobbered registers for ms->sysv calls


> > This is actually good idea ;)
> 
> Phew, got my good idea for 2008 just in time.  I was getting worried.

Too bad for me, I missed the obvious chance when I was doing the initial
patch ;))
This is version I comitted with unspecs and -2 used to represent MSABI
calls.

	* 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.mc (function_arg_ms_64): Pass magical value of -2 as callarg.
	(ix86_expand_call): Emit extra clobbers for ms->sysv ABI calls.
Index: config/i386/i386.md
===================================================================
*** config/i386/i386.md	(revision 142858)
--- config/i386/i386.md	(working copy)
***************
*** 105,110 ****
--- 105,111 ----
     (UNSPEC_LFENCE		45)
     (UNSPEC_PSADBW		46)
     (UNSPEC_LDDQU		47)
+    (UNSPEC_MS_TO_SYSV_CALL	48)
  
     ; Generic math support
     (UNSPEC_COPYSIGN		50)
***************
*** 15039,15044 ****
--- 15040,15059 ----
  }
    [(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 "" ""))]
***************
*** 21361,21366 ****
--- 21376,21397 ----
  }
    [(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"))
***************
*** 21398,21403 ****
--- 21429,21449 ----
  }
    [(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"))
Index: config/i386/i386.c
===================================================================
*** config/i386/i386.c	(revision 142858)
--- config/i386/i386.c	(working copy)
*************** function_arg_ms_64 (CUMULATIVE_ARGS *cum
*** 5690,5698 ****
  {
    unsigned int regno;
  
!   /* Avoid the AL settings for the Unix64 ABI.  */
    if (mode == VOIDmode)
!     return constm1_rtx;
  
    /* If we've run out of registers, it goes on the stack.  */
    if (cum->nregs == 0)
--- 5690,5699 ----
  {
    unsigned int regno;
  
!   /* 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 GEN_INT (-2);
  
    /* If we've run out of registers, it goes on the stack.  */
    if (cum->nregs == 0)
*************** construct_plt_address (rtx symbol)
*** 18095,18105 ****
  
  void
  ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
! 		  rtx callarg2 ATTRIBUTE_UNUSED,
  		  rtx pop, int sibcall)
  {
    rtx use = NULL, call;
  
    if (pop == const0_rtx)
      pop = NULL;
    gcc_assert (!TARGET_64BIT || !pop);
--- 18098,18113 ----
  
  void
  ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
! 		  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);
*************** ix86_expand_call (rtx retval, rtx fnaddr
*** 18155,18160 ****
--- 18163,18180 ----
        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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]