From patchwork Fri Nov 6 16:27:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 541036 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id AC2C71402D5 for ; Sat, 7 Nov 2015 03:28:17 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=B/kgh9FD; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=EcwE3v4pe2zeZMZEv tiIf3g+7WzIGz0O0MkW2Jxv9HqgmEeBK67N5regAnb4vIBkrm6NPJrs9bnZfxR+i 3W+IKCoNlfBCW+BkwguSed8DSdH8IQwTPB7NXxGFCqcId1xiYzMzwtrdQicXpm5H UUEq2rgz9yMCY28/+gyeYjui/g= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=vcRWYfqeUQwUWcLvWnpVloS tj/4=; b=B/kgh9FD38dpJ/GQDfB0aQyVDQPwdxqJv6O8dep+BoSeWREkgQuC79b LeoJk9dkd04B/9SnCrBgDBA9if7BuGx0IwjnhxPswn8iU5azLBHGMbro/mNN8jQ6 F1ddLXZ1/teV6/AZlLg3P4a7L0M4b95H4Xbaqq1ryKylXXBTdGUo= Received: (qmail 81733 invoked by alias); 6 Nov 2015 16:28:10 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 81719 invoked by uid 89); 6 Nov 2015 16:28:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.7 required=5.0 tests=AWL, BAYES_40, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mailout02.t-online.de Received: from mailout02.t-online.de (HELO mailout02.t-online.de) (194.25.134.17) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 06 Nov 2015 16:27:59 +0000 Received: from fwd29.aul.t-online.de (fwd29.aul.t-online.de [172.20.26.134]) by mailout02.t-online.de (Postfix) with SMTP id D01CB36F298; Fri, 6 Nov 2015 17:27:54 +0100 (CET) Received: from [192.168.2.105] (rxpftZZJohDizI2HeUL4omk186LN1WMO6jM1dm8tYtRAV+H9Ir62xSmM8e73hoSQ0Z@[84.167.116.215]) by fwd29.t-online.de with (TLSv1.2:ECDHE-RSA-AES256-SHA encrypted) esmtp id 1Zujri-1lY40m0; Fri, 6 Nov 2015 17:27:50 +0100 Subject: Re: improved RTL-level if conversion using scratchpads [half-hammock edition] To: Sebastian Pop , Bernd Schmidt References: <563BE9A7.30803@yahoo.com> <563C8748.3040901@redhat.com> <563CB9F4.7020609@redhat.com> Cc: Abe , "gcc-patches@gcc.gnu.org" , Kyrill Tkachov From: Bernd Schmidt Message-ID: <563CD500.7040304@t-online.de> Date: Fri, 6 Nov 2015 17:27:44 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes On 11/06/2015 04:52 PM, Sebastian Pop wrote: >> opinion). If you want a half-finished redzone allocator, I can send you a >> patch. > > Yes please. Let's get it work. Here you go. This is incomplete and does not compile, but it shows the direction I have in mind and isn't too far off. I had a similar patch once for a machine that had two stack pointers (don't ask), and I started to recreate that for the given problem last week. The temp slot handling code in function.c needs more frame arguments, but I got halfway through them and started wondering whether they should be member functions of struct frame_info instead. The bits in cfgexpand and function, once complete, are essentially all that's necessary to support a second frame, but for this to work as a redzone allocator it needs to be integrated with target (i.e. i386) frame layout code. For purposes of optimizing we may also want to establish a maximum frame size for the rz_frame. Bonus points if reload/lra use this for spilled pseudos that don't live across calls, but I can have a go at that if you don't feel like tackling it. Bernd diff --git a/gcc/caller-save.c b/gcc/caller-save.c index 084d079..c3a5256 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -654,7 +654,7 @@ setup_save_areas (void) { saved_reg->slot = assign_stack_local_1 - (regno_save_mode[regno][1], + (&crtl->frame, regno_save_mode[regno][1], GET_MODE_SIZE (regno_save_mode[regno][1]), 0, ASLK_REDUCE_ALIGN); if (dump_file != NULL) @@ -712,7 +712,8 @@ setup_save_areas (void) when we restore and save the hard register in insert_restore and insert_save. */ regno_save_mem[i][j] - = assign_stack_local_1 (regno_save_mode[i][j], + = assign_stack_local_1 (&crtl->frame, + regno_save_mode[i][j], GET_MODE_SIZE (regno_save_mode[i][j]), 0, ASLK_REDUCE_ALIGN); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index bfbc958..8825217 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -335,11 +335,6 @@ static bitmap_obstack stack_var_bitmap_obstack; is non-decreasing. */ static size_t *stack_vars_sorted; -/* The phase of the stack frame. This is the known misalignment of - virtual_stack_vars_rtx from PREFERRED_STACK_BOUNDARY. That is, - (frame_offset+frame_phase) % PREFERRED_STACK_BOUNDARY == 0. */ -static int frame_phase; - /* Used during expand_used_vars to remember if we saw any decls for which we'd like to enable stack smashing protection. */ static bool has_protected_decls; @@ -375,32 +370,34 @@ align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up) return align_up ? (base + align - 1) & -align : base & -align; } -/* Allocate SIZE bytes at byte alignment ALIGN from the stack frame. +/* Allocate SIZE bytes at byte alignment ALIGN from the stack frame FRAME. Return the frame offset. */ static HOST_WIDE_INT -alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align) +alloc_stack_frame_space (frame_info *frame, HOST_WIDE_INT size, + unsigned HOST_WIDE_INT align) { HOST_WIDE_INT offset, new_frame_offset; - if (FRAME_GROWS_DOWNWARD) + if (frame->grows_downward) { - new_frame_offset - = align_base (frame_offset - frame_phase - size, - align, false) + frame_phase; + new_frame_offset = align_base (frame->frame_offset - frame->phase - size, + align, false); + new_frame_offset += frame->phase; offset = new_frame_offset; } else { - new_frame_offset - = align_base (frame_offset - frame_phase, align, true) + frame_phase; + new_frame_offset = align_base (frame->frame_offset - frame->phase, + align, true); + new_frame_offset += frame->phase; offset = new_frame_offset; new_frame_offset += size; } - frame_offset = new_frame_offset; + frame->frame_offset = new_frame_offset; - if (frame_offset_overflow (frame_offset, cfun->decl)) - frame_offset = offset = 0; + if (frame_offset_overflow (frame->frame_offset, cfun->decl)) + frame->frame_offset = offset = 0; return offset; } @@ -965,11 +962,11 @@ dump_stack_var_partition (void) } } -/* Assign rtl to DECL at BASE + OFFSET. */ +/* Assign rtl to DECL at BASE + OFFSET in frame FRAME. */ static void -expand_one_stack_var_at (tree decl, rtx base, unsigned base_align, - HOST_WIDE_INT offset) +expand_one_stack_var_at (frame_info *frame, tree decl, rtx base, + unsigned base_align, HOST_WIDE_INT offset) { unsigned align; rtx x; @@ -988,7 +985,7 @@ expand_one_stack_var_at (tree decl, rtx base, unsigned base_align, If it is we generate stack slots only accidentally so it isn't as important, we'll simply use the alignment that is already set. */ if (base == virtual_stack_vars_rtx) - offset -= frame_phase; + offset -= frame->phase; align = offset & -offset; align *= BITS_PER_UNIT; if (align == 0 || align > base_align) @@ -1120,7 +1117,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) FRAME_GROWS_DOWNWARD); tree repr_decl = NULL_TREE; offset - = alloc_stack_frame_space (stack_vars[i].size + = alloc_stack_frame_space (&crtl->frame, stack_vars[i].size + ASAN_RED_ZONE_SIZE, MAX (alignb, ASAN_RED_ZONE_SIZE)); @@ -1157,7 +1154,8 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) } else { - offset = alloc_stack_frame_space (stack_vars[i].size, alignb); + offset = alloc_stack_frame_space (&crtl->frame, + stack_vars[i].size, alignb); base_align = crtl->max_used_stack_slot_alignment; } } @@ -1181,9 +1179,8 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) partition. */ for (j = i; j != EOC; j = stack_vars[j].next) { - expand_one_stack_var_at (stack_vars[j].decl, - base, base_align, - offset); + expand_one_stack_var_at (&crtl->frame, stack_vars[j].decl, + base, base_align, offset); } } @@ -1276,9 +1273,9 @@ expand_one_stack_var_1 (tree var) /* We handle highly aligned variables in expand_stack_vars. */ gcc_assert (byte_align * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT); - offset = alloc_stack_frame_space (size, byte_align); + offset = alloc_stack_frame_space (&crtl->frame, size, byte_align); - expand_one_stack_var_at (var, virtual_stack_vars_rtx, + expand_one_stack_var_at (&crtl->frame, var, virtual_stack_vars_rtx, crtl->max_used_stack_slot_alignment, offset); } @@ -1995,13 +1992,6 @@ expand_used_vars (void) unsigned len; bool gen_stack_protect_signal = false; - /* Compute the phase of the stack frame for this function. */ - { - int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; - int off = STARTING_FRAME_OFFSET % align; - frame_phase = off ? align - off : 0; - } - /* Set TREE_USED on all variables in the local_decls. */ FOR_EACH_LOCAL_DECL (cfun, i, var) TREE_USED (var) = 1; @@ -2197,12 +2187,13 @@ expand_used_vars (void) redzonesz = ((sz + ASAN_RED_ZONE_SIZE + data.asan_alignb - 1) & ~(data.asan_alignb - HOST_WIDE_INT_1)) - sz; offset - = alloc_stack_frame_space (redzonesz, ASAN_RED_ZONE_SIZE); + = alloc_stack_frame_space (&crtl->frame, redzonesz, ASAN_RED_ZONE_SIZE); data.asan_vec.safe_push (prev_offset); data.asan_vec.safe_push (offset); /* Leave space for alignment if STRICT_ALIGNMENT. */ if (STRICT_ALIGNMENT) - alloc_stack_frame_space ((GET_MODE_ALIGNMENT (SImode) + alloc_stack_frame_space (&crtl->frame, + (GET_MODE_ALIGNMENT (SImode) << ASAN_SHADOW_SHIFT) / BITS_PER_UNIT, 1); diff --git a/gcc/emit-rtl.h b/gcc/emit-rtl.h index f52c335..8f90fd0 100644 --- a/gcc/emit-rtl.h +++ b/gcc/emit-rtl.h @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see struct temp_slot; typedef struct temp_slot *temp_slot_p; -/* Information mainlined about RTL representation of incoming arguments. */ +/* Information maintained about RTL representation of incoming arguments. */ struct GTY(()) incoming_args { /* Number of bytes of args popped by function being compiled on its return. Zero if no bytes are to be popped. @@ -52,6 +52,33 @@ struct GTY(()) incoming_args { rtx internal_arg_pointer; }; +/* Information maintained about layout and size of a stack frame. */ +struct GTY(()) frame_info { + /* Offset to end of allocated area of stack frame. + If stack grows down, this is the address of the last stack slot allocated. + If stack grows up, this is the address for the next slot. */ + HOST_WIDE_INT frame_offset; + + /* List of all used temporaries allocated, by level. */ + VEC(temp_slot_p,gc) *used_temp_slots; + + /* List of available temp slots. */ + struct temp_slot *avail_temp_slots; + + /* The phase of the frame offset. */ + int phase; + + /* List of empty areas in the stack frame. */ + struct frame_space *frame_space_list; + + /* The base register to be used for this frame. */ + rtx base; + + /* True if FRAME_GROWS_DOWNWARD (or any similar definition) + applies to this particular frame. */ + bool grows_downward; +}; + /* Datastructures maintained for currently processed function in RTL form. */ struct GTY(()) rtl_data { @@ -106,12 +133,15 @@ struct GTY(()) rtl_data { Made for the sake of unshare_all_rtl. */ rtx_expr_list *x_stack_slot_list; - /* List of empty areas in the stack frame. */ - struct frame_space *frame_space_list; - /* Place after which to insert the tail_recursion_label if we need one. */ rtx_note *x_stack_check_probe_note; + /* Description of the regular stack frame. */ + frame_info *frame; + + /* Description of the redzone stack frame. */ + frame_info *rz_frame; + /* Location at which to save the argument pointer if it will need to be referenced. There are two cases where this is done: if nonlocal gotos exist, or if vars stored at an offset from the argument pointer will be @@ -121,23 +151,9 @@ struct GTY(()) rtl_data { /* Dynamic Realign Argument Pointer used for realigning stack. */ rtx drap_reg; - /* Offset to end of allocated area of stack frame. - If stack grows down, this is the address of the last stack slot allocated. - If stack grows up, this is the address for the next slot. */ - HOST_WIDE_INT x_frame_offset; - /* Insn after which register parms and SAVE_EXPRs are born, if nonopt. */ rtx_insn *x_parm_birth_insn; - /* List of all used temporaries allocated, by level. */ - vec *x_used_temp_slots; - - /* List of available temp slots. */ - struct temp_slot *x_avail_temp_slots; - - /* Current nesting level for temporaries. */ - int x_temp_slot_level; - /* The largest alignment needed on the stack, including requirement for outgoing stack alignment. */ unsigned int stack_alignment_needed; @@ -290,11 +306,8 @@ struct GTY(()) rtl_data { #define naked_return_label (crtl->x_naked_return_label) #define stack_slot_list (crtl->x_stack_slot_list) #define parm_birth_insn (crtl->x_parm_birth_insn) -#define frame_offset (crtl->x_frame_offset) #define stack_check_probe_note (crtl->x_stack_check_probe_note) #define arg_pointer_save_area (crtl->x_arg_pointer_save_area) -#define used_temp_slots (crtl->x_used_temp_slots) -#define avail_temp_slots (crtl->x_avail_temp_slots) #define temp_slot_level (crtl->x_temp_slot_level) #define nonlocal_goto_handler_labels (crtl->x_nonlocal_goto_handler_labels) #define frame_pointer_needed (crtl->frame_pointer_needed) diff --git a/gcc/function.c b/gcc/function.c index a637cb3..9aec731 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -217,10 +217,10 @@ free_after_compilation (struct function *f) HOST_WIDE_INT get_frame_size (void) { - if (FRAME_GROWS_DOWNWARD) - return -frame_offset; + if (-crtl->frame.grows_downward) + return -crtl->frame.frame_offset; else - return frame_offset; + return crtl->frame.frame_offset; } /* Issue an error message and return TRUE if frame OFFSET overflows in @@ -272,19 +272,14 @@ get_stack_local_alignment (tree type, machine_mode mode) given a start/length pair that lies at the end of the frame. */ static bool -try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length, +try_fit_stack_local (frame_info *frame, + HOST_WIDE_INT start, HOST_WIDE_INT length, HOST_WIDE_INT size, unsigned int alignment, HOST_WIDE_INT *poffset) { HOST_WIDE_INT this_frame_offset; int frame_off, frame_alignment, frame_phase; - /* Calculate how many bytes the start of local variables is off from - stack alignment. */ - frame_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; - frame_off = STARTING_FRAME_OFFSET % frame_alignment; - frame_phase = frame_off ? frame_alignment - frame_off : 0; - /* Round the frame offset to the specified alignment. */ /* We must be careful here, since FRAME_OFFSET might be negative and @@ -293,14 +288,14 @@ try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length, use logical operations which are unambiguous. */ if (FRAME_GROWS_DOWNWARD) this_frame_offset - = (FLOOR_ROUND (start + length - size - frame_phase, + = (FLOOR_ROUND (start + length - size - frame->phase, (unsigned HOST_WIDE_INT) alignment) - + frame_phase); + + frame->phase); else this_frame_offset = (CEIL_ROUND (start - frame_phase, (unsigned HOST_WIDE_INT) alignment) - + frame_phase); + + frame->phase); /* See if it fits. If this space is at the edge of the frame, consider extending the frame to make it fit. Our caller relies on @@ -324,17 +319,17 @@ try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length, function's frame_space_list. */ static void -add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end) +add_frame_space (frame_info *frame, HOST_WIDE_INT start, HOST_WIDE_INT end) { struct frame_space *space = ggc_alloc (); - space->next = crtl->frame_space_list; - crtl->frame_space_list = space; + space->next = frame->frame_space_list; + frame->frame_space_list = space; space->start = start; space->length = end - start; } -/* Allocate a stack slot of SIZE bytes and return a MEM rtx for it - with machine mode MODE. +/* Allocate a stack slot of SIZE bytes in FRAME and return a MEM rtx + for it with machine mode MODE. ALIGN controls the amount of alignment for the address of the slot: 0 means according to MODE, @@ -351,12 +346,13 @@ add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end) We do not round to stack_boundary here. */ rtx -assign_stack_local_1 (machine_mode mode, HOST_WIDE_INT size, - int align, int kind) +assign_stack_local_1 (frame_info *frame, machine_mode mode, + HOST_WIDE_INT size, int align, int kind) { rtx x, addr; int bigend_correction = 0; HOST_WIDE_INT slot_offset = 0, old_frame_offset; + HOST_WIDE_INT frame_offset = frame->frame_offset; unsigned int alignment, alignment_in_bits; if (align == 0) @@ -424,17 +420,17 @@ assign_stack_local_1 (machine_mode mode, HOST_WIDE_INT size, { struct frame_space **psp; - for (psp = &crtl->frame_space_list; *psp; psp = &(*psp)->next) + for (psp = &frame->frame_space_list; *psp; psp = &(*psp)->next) { struct frame_space *space = *psp; - if (!try_fit_stack_local (space->start, space->length, size, - alignment, &slot_offset)) + if (!try_fit_stack_local (frame, space->start, space->length, + size, alignment, &slot_offset)) continue; *psp = space->next; if (slot_offset > space->start) - add_frame_space (space->start, slot_offset); + add_frame_space (frame, space->start, slot_offset); if (slot_offset + size < space->start + space->length) - add_frame_space (slot_offset + size, + add_frame_space (frame, slot_offset + size, space->start + space->length); goto found_space; } @@ -450,28 +446,30 @@ assign_stack_local_1 (machine_mode mode, HOST_WIDE_INT size, if (FRAME_GROWS_DOWNWARD) { - frame_offset -= size; - try_fit_stack_local (frame_offset, size, size, alignment, &slot_offset); + frame->x_frame_offset -= size; + try_fit_stack_local (frame, frame_offset, size, size, alignment, + &slot_offset); if (kind & ASLK_RECORD_PAD) { if (slot_offset > frame_offset) - add_frame_space (frame_offset, slot_offset); + add_frame_space (frame, frame_offset, slot_offset); if (slot_offset + size < old_frame_offset) - add_frame_space (slot_offset + size, old_frame_offset); + add_frame_space (frame, slot_offset + size, old_frame_offset); } } else { - frame_offset += size; - try_fit_stack_local (old_frame_offset, size, size, alignment, &slot_offset); + frame->x_frame_offset += size; + try_fit_stack_local (frame, old_frame_offset, size, size, alignment, + &slot_offset); if (kind & ASLK_RECORD_PAD) { if (slot_offset > old_frame_offset) - add_frame_space (old_frame_offset, slot_offset); + add_frame_space (frame, old_frame_offset, slot_offset); if (slot_offset + size < frame_offset) - add_frame_space (slot_offset + size, frame_offset); + add_frame_space (frame, slot_offset + size, frame_offset); } } @@ -481,10 +479,11 @@ assign_stack_local_1 (machine_mode mode, HOST_WIDE_INT size, if (BYTES_BIG_ENDIAN && mode != BLKmode && GET_MODE_SIZE (mode) < size) bigend_correction = size - GET_MODE_SIZE (mode); + rtx reg = frame->base; /* If we have already instantiated virtual registers, return the actual address relative to the frame pointer. */ - if (virtuals_instantiated) - addr = plus_constant (Pmode, frame_pointer_rtx, + if (reg != frame_pointer_rtx || virtuals_instantiated) + addr = plus_constant (Pmode, reg, trunc_int_for_mode (slot_offset + bigend_correction + STARTING_FRAME_OFFSET, Pmode)); @@ -504,6 +503,7 @@ assign_stack_local_1 (machine_mode mode, HOST_WIDE_INT size, if (frame_offset_overflow (frame_offset, current_function_decl)) frame_offset = 0; + frame->frame_offset = frame_offset; return x; } @@ -573,7 +573,6 @@ struct temp_address_hasher : ggc_ptr_hash /* A table of addresses that represent a stack slot. The table is a mapping from address RTXen to a temp slot. */ static GTY(()) hash_table *temp_slot_address_table; -static size_t n_temp_slots_in_use; /* Removes temporary slot TEMP from LIST. */ @@ -602,35 +601,35 @@ insert_slot_to_list (struct temp_slot *temp, struct temp_slot **list) *list = temp; } -/* Returns the list of used temp slots at LEVEL. */ +/* Returns the list of used temp slots at LEVEL in frame FRAME. */ static struct temp_slot ** -temp_slots_at_level (int level) +temp_slots_at_level (frame_info *frame, int level) { - if (level >= (int) vec_safe_length (used_temp_slots)) - vec_safe_grow_cleared (used_temp_slots, level + 1); + if (level >= (int) vec_safe_length (frame->used_temp_slots)) + vec_safe_grow_cleared (frame->used_temp_slots, level + 1); - return &(*used_temp_slots)[level]; + return &(*frame->used_temp_slots)[level]; } -/* Returns the maximal temporary slot level. */ +/* Returns the maximal temporary slot level in frame FRAME. */ static int -max_slot_level (void) +max_slot_level (frame_info *frame) { - if (!used_temp_slots) + if (!frame->used_temp_slots) return -1; - return used_temp_slots->length () - 1; + return frame->used_temp_slots->length () - 1; } -/* Moves temporary slot TEMP to LEVEL. */ +/* Moves temporary slot TEMP to LEVEL in frame FRAME. */ static void -move_slot_to_level (struct temp_slot *temp, int level) +move_slot_to_level (frame_info *frame, struct temp_slot *temp, int level) { - cut_slot_from_list (temp, temp_slots_at_level (temp->level)); - insert_slot_to_list (temp, temp_slots_at_level (level)); + cut_slot_from_list (temp, temp_slots_at_level (frame, temp->level)); + insert_slot_to_list (temp, temp_slots_at_level (frame, level)); temp->level = level; } @@ -1196,16 +1195,40 @@ pop_temp_slots (void) temp_slot_level--; } +/* Initialize temporary slots for frame FRAME. DOWNWARD is the value of + the applicable FRAME_GROWS_DOWNWARD setting. BASE is the base register + for this frame. */ + +void +init_temp_slots_frame (frame_info *frame, rtx base, bool downward) +{ + /* We have not allocated any temporaries yet. */ + frame->avail_temp_slots = 0; + vec_alloc (frame->used_temp_slots, 0); + frame->temp_slot_level = 0; + frame->n_temp_slots_in_use = 0; + frame->grows_downward = downward; + frame->base = base; +} + /* Initialize temporary slots. */ void init_temp_slots (void) { - /* We have not allocated any temporaries yet. */ - avail_temp_slots = 0; - vec_alloc (used_temp_slots, 0); - temp_slot_level = 0; - n_temp_slots_in_use = 0; + init_temp_slots_frame (&crtl->frame, frame_pointer_rtx, + FRAME_GROWS_DOWNWARD); + init_temp_slots_frame (&crtl->rz_frame, stack_pointer_rtx, false); + + /* Calculate how many bytes the start of local variables is off from + stack alignment. This is only used for the regular frame, if it + becomes necessary to do something for the redzone frame, we should + add the necessary starting offset macro. */ + int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; + int off = STARTING_FRAME_OFFSET % align; + + crtl->frame.phase = off ? align - off : 0; + crtl->rz_frame.phase = 0; /* Set up the table to map addresses to temp slots. */ if (! temp_slot_address_table) diff --git a/gcc/function.h b/gcc/function.h index b2e4f71..b436f73 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -563,7 +563,8 @@ extern HOST_WIDE_INT get_frame_size (void); return FALSE. */ extern bool frame_offset_overflow (HOST_WIDE_INT, tree); -extern rtx assign_stack_local_1 (machine_mode, HOST_WIDE_INT, int, int); +extern rtx assign_stack_local_1 (frame_info *, machine_mode, HOST_WIDE_INT, + int, int); extern rtx assign_stack_local (machine_mode, HOST_WIDE_INT, int); extern rtx assign_stack_temp_for_type (machine_mode, HOST_WIDE_INT, tree); extern rtx assign_stack_temp (machine_mode, HOST_WIDE_INT);