Here is the current version of the patch with all the fixes.
Regtested\bootstraped it on 64 bit.

We need a pointer since interrupt handler will update data pointing
to by frame.  Since error_code isn't at the normal location where the
parameter is passed on stack and frame isn't in a hard register, we
changed ix86_function_arg:

+  if (!cum->caller && cfun->machine->func_type != TYPE_NORMAL)
+    {
+      /* The first argument of interrupt handler is a pointer and
+        points to the return address slot on stack.  The optional
+        second argument is an integer for error code on stack.  */
+      gcc_assert (type != NULL_TREE);
+      if (POINTER_TYPE_P (type))
+       {
+         if (cfun->machine->func_type == TYPE_EXCEPTION)
+           /* (AP) in the current frame in exception handler.  */
+           arg = arg_pointer_rtx;
+         else
+           /* -WORD(AP) in the current frame in interrupt handler.  */
+           arg = force_reg (Pmode,
+                            plus_constant (Pmode, arg_pointer_rtx,
+                                           -UNITS_PER_WORD));
+         if (mode != Pmode)
+           arg = convert_to_mode (mode, arg, 1);
+       }
+      else
+       {
+         gcc_assert (TREE_CODE (type) == INTEGER_TYPE
+                     && cfun->machine->func_type == TYPE_EXCEPTION
+                     && mode == word_mode);
+         /* The error code is at -WORD(AP) in the current frame in
+            exception handler.  */
+         arg = gen_rtx_MEM (word_mode,
+                            plus_constant (Pmode, arg_pointer_rtx,
+                                           -UNITS_PER_WORD));
+       }
+
+      return arg;
+    }
+

to return a pseudo register.  It violates

   Return where to put the arguments to a function.
   Return zero to push the argument on the stack, or a hard register in
   which to store the argument.

Register allocator has no problem with parameters in pseudo registers.
But GCC crashes when it tries to access DECL_INCOMING_RTL as a hard
register when generating debug information.  We worked around it by
doing

+
+  if (cfun->machine->func_type != TYPE_NORMAL)
+    {
+      /* Since the pointer argument of interrupt handler isn't a real
+         argument, adjust DECL_INCOMING_RTL for debug output.  */
+      tree arg = DECL_ARGUMENTS (current_function_decl);
+      gcc_assert (arg != NULL_TREE
+                 && POINTER_TYPE_P (TREE_TYPE (arg)));
+      if (cfun->machine->func_type == TYPE_EXCEPTION)
+       /* (AP) in the current frame in exception handler.  */
+       DECL_INCOMING_RTL (arg) = arg_pointer_rtx;
+      else
+       /* -WORD(AP) in the current frame in interrupt handler.  */
+       DECL_INCOMING_RTL (arg) = plus_constant (Pmode,
+                                                arg_pointer_rtx,
+                                                -UNITS_PER_WORD);
+    }


On Mon, Oct 5, 2015 at 12:29 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
> On Mon, Oct 5, 2015 at 1:17 AM, H.J. Lu <hjl.to...@gmail.com> wrote:
>
>>>>>>> Looking a bit deeper into the code, it looks that we want to realign
>>>>>>> the stack in the interrupt handler. Let's assume that interrupt
>>>>>>> handler is calling some other function that saves SSE vector regs to
>>>>>>> the stack. According to the x86 ABI, incoming stack of the called
>>>>>>> function is assumed to be aligned to 16 bytes. But, interrupt handler
>>>>>>> violates this assumption, since the stack could be aligned to only 4
>>>>>>> bytes for 32bit and 8 bytes for 64bit targets. Entering the called
>>>>>>> function with stack, aligned to less than 16 bytes will certainly
>>>>>>> violate ABI.
>>>>>>>
>>>>>>> So, it looks to me that we need to realign the stack in the interrupt
>>>>>>> handler unconditionally to 16bytes. In this case, we also won't need
>>>>>>> the following changes:
>>>>>>>
>>>>>>
>>>>>> Current stack alignment implementation requires at least
>>>>>> one, maybe two, scratch registers:
>>>>>>
>>>>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67841
>>>>>>
>>>>>> Extend it to the interrupt handler, which doesn't have any scratch
>>>>>> registers may require significant changes in backend as well as
>>>>>> register allocator.
>>>>>
>>>>> But without realignment, the handler is unusable for anything but
>>>>> simple functions. The handler will crash when called function will try
>>>>> to save vector reg to stack.
>>>>>
>>>>
>>>> We can use unaligned load and store to avoid crash.
>>>
>>> Oh, sorry, I meant "called function will crash", like:
>>>
>>> -> interrupt when %rsp = 0x...8 ->
>>> -> interrupt handler ->
>>> -> calls some function that tries to save xmm reg to stack
>>> -> crash in the called function
>>>
>>
>> It should be fixed by this patch.   But we need to fix stack
>> alignment in interrupt handler to avoid scratch register.
>>
>>
>> --
>> H.J.
>> ---
>> commit 15f48be1dc7ff48207927d0b835e593d058f695b
>> Author: H.J. Lu <hjl.to...@gmail.com>
>> Date:   Sun Oct 4 16:14:03 2015 -0700
>>
>>     Correctly set incoming stack boundary for interrupt handler
>>
>> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
>> index 7ebdcd9..0f0cc3c 100644
>> --- a/gcc/config/i386/i386.c
>> +++ b/gcc/config/i386/i386.c
>> @@ -12037,8 +12037,11 @@ ix86_minimum_incoming_stack_boundary (bool sibcall)
>>  {
>>    unsigned int incoming_stack_boundary;
>>
>> +  /* Stack of interrupt handler is always aligned to word_mode.  */
>> +  if (cfun->machine->func_type != TYPE_NORMAL)
>> +    incoming_stack_boundary = TARGET_64BIT ? 64 : 32;
>
> Just a heads up that in order to support stack realignmnent on x86_64,
> MIN_STACK_BOUNDARY will soon be changed to BITS_PER_WORD, so you can
> use it in the line above. Please see comment #5 and #6 of PR 66697
> [1].
>
>>    /* Prefer the one specified at command line. */
>> -  if (ix86_user_incoming_stack_boundary)
>> +  else if (ix86_user_incoming_stack_boundary)
>>      incoming_stack_boundary = ix86_user_incoming_stack_boundary;
>>    /* In 32bit, use MIN_STACK_BOUNDARY for incoming stack boundary
>>       if -mstackrealign is used, it isn't used for sibcall check and
>
> [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66697
>
> Uros.

Attachment: patch
Description: Binary data

Reply via email to