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 wrote: > On Mon, Oct 5, 2015 at 1:17 AM, H.J. Lu 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 >> 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.