From patchwork Wed Jul 24 18:00:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raphael Moreira Zinsly X-Patchwork-Id: 1964457 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=ventanamicro.com header.i=@ventanamicro.com header.a=rsa-sha256 header.s=google header.b=BXa6iGyv; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WThg71QwXz1yXx for ; Thu, 25 Jul 2024 04:02:11 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6D3A2386100A for ; Wed, 24 Jul 2024 18:02:09 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by sourceware.org (Postfix) with ESMTPS id E89373858283 for ; Wed, 24 Jul 2024 18:00:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E89373858283 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=ventanamicro.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=ventanamicro.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E89373858283 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::636 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1721844038; cv=none; b=PSUJNXVL54fNCY0YZ8RvGUMrzD6wz9CEGLFm5Lxdx8Nub34D32yG+31lIWseeLcDp7c9FKzWAptHtGwOkRLP4nqikpnYoaPkfD4uI9720nkVmJjku2Dke5Wi634ods2IYSxMICXmWEyOl0pFiiVepM0IJq5N1Jrn+PufJKE/qvk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1721844038; c=relaxed/simple; bh=8/nrGhtgf8NbwT0aFliCyyr7ATQuM+9m7sjTFEQapDY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=g/+LXmX5MblPp3/sA5GeYDo34iberH525HhvYv2Q3eRNxcc5hSo/ERPdP+3EbXtW0ek93+MMLiK0aDNyZmYRwezw9bxcsfTzcIRA5OYVNm6Sm4tAECcZuU2mi0kqOjvn14G1CEVzHrFAaV+RWYZTuy7zy29w8nXDo73yBIo7NN4= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x636.google.com with SMTP id d9443c01a7336-1fb3b7d0d3aso224025ad.2 for ; Wed, 24 Jul 2024 11:00:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1721844030; x=1722448830; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=L5UGLe2o8A1NsPPbyEgyxerQOTzVJ4hlPK+gvwR4cQA=; b=BXa6iGyvFCDlNwanca/k+QsufmRAHMbFT056KTVu04v4ezIKII4NbPtKwf2CwyzqYt UAcmRSZZJZWGm4ZTzDt/bbE6AO11GtCrc52KEmLFCYxvOwYHxtRe6Xw7VTj+1V66nzPa j0hxkhdcJCPsgu8Rl0jQ0GM3Klo4zgDB7O1DpXtNrQfX1qYd0jbwXPNT72qQOoe/qi5J L3rtln/a1iKw16121IS1Xjz61c/iWWDkkYcmxuHEY7Dh6CQiwSKKu3I4LA4Hk7hNiCzY 0wLfHSTjUXZKAa0QMPKhbJjc6+NtGVgKz3oES5VbLjdt2fLtf3RpDXMxIYzjb6V9tvgP wkrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721844030; x=1722448830; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=L5UGLe2o8A1NsPPbyEgyxerQOTzVJ4hlPK+gvwR4cQA=; b=LDpsTvtyJZBNIpeqhBSZ2oufl4pMXujpBtgf0R/w6YljYh4d9WaRkcJPXAB4o+H0UC bAslh6WPdb9JgwYbNA9SwekpZhHCEv/Fv9k/VGd6X/+uOkE/3qsXTasckFaHB03CxBnh 7JB8qr1mBv22+lsD5GNn8d2k0XMEs35QODYFZ+PwN0cwfUkPXD8Eq3UGfYgWEvgw5fk9 Dalb/3RbRWaZ7xuGF4ye8OpsprwVKjZ5LxB7Him/zqvJvBDxn8u1qhfhii0kgMX59DjQ hXc7NyTW8rkY5nzVPUcnapHbyIorAs+6u3V8Znpnaujn8gqkkA35AKWQDAtpuWMReIMy x0aw== X-Gm-Message-State: AOJu0YwxqFAagTmLSYinCdMKbo41j0nVS7E6sUX+pCDeJU4UpvWOL49E vYwdE3CEtQaA88hnwYfUt6l8R2z0LHXfanqxmP8741WhAl9Uf9MrSGaNK0XO/8qgjGW0WExXksP J X-Google-Smtp-Source: AGHT+IEMpG819XjvoCn7vAzlH8//4110kDxTRNqAksOOaVQGKv8V0L9ZU91acAElOy2GT0SXdYTdMQ== X-Received: by 2002:a17:902:e54c:b0:1fa:4187:7397 with SMTP id d9443c01a7336-1fed3bf03f0mr3541775ad.60.1721844029431; Wed, 24 Jul 2024 11:00:29 -0700 (PDT) Received: from marvin.dc1.ventanamicro.com ([189.4.72.88]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fd6f4713f8sm97261705ad.268.2024.07.24.11.00.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Jul 2024 11:00:29 -0700 (PDT) From: Raphael Moreira Zinsly To: gcc-patches@gcc.gnu.org Cc: jlaw@ventanamicro.com, Raphael Moreira Zinsly Subject: [PATCH 3/5] RISC-V: Stack-clash protection implemention Date: Wed, 24 Jul 2024 15:00:11 -0300 Message-ID: <6f8bab519688aed305898320d1735409e4c46e10.1721681845.git.rzinsly@ventanamicro.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Status: No, score=-10.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This implements stack-clash protection for riscv, with riscv_allocate_and_probe_stack_space being based of aarch64_allocate_and_probe_stack_space from aarch64's implementation. We enforce the probing interval and the guard size to always be equal, their default value is 4Kb which is riscv page size. We also probe up by 1024 bytes in the general case when a probe is required. gcc/ChangeLog: * config/riscv/riscv.cc (riscv_option_override): Enforce that interval is the same size as guard size. (riscv_allocate_and_probe_stack_space): New function. (riscv_expand_prologue): Call riscv_allocate_and_probe_stack_space to the final allocation of the stack and add stack-clash dump information. * config/riscv/riscv.h: Define STACK_CLASH_CALLER_GUARD and STACK_CLASH_MAX_UNROLL_PAGES. gcc/testsuite/ChangeLog: * gcc.dg/params/blocksort-part.c: Skip riscv for stack-clash protection intervals. * gcc.dg/pr82788.c: Skip riscv. * gcc.dg/stack-check-6.c: Skip residual check for riscv. * gcc.dg/stack-check-6a.c: Skip riscv. * gcc.target/riscv/stack-check-12.c: New test. * gcc.target/riscv/stack-check-13.c: New test. * gcc.target/riscv/stack-check-cfa-1.c: New test. * gcc.target/riscv/stack-check-cfa-2.c: New test. * gcc.target/riscv/stack-check-prologue-1.c: New test. * gcc.target/riscv/stack-check-prologue-10.c: New test. * gcc.target/riscv/stack-check-prologue-11.c: New test. * gcc.target/riscv/stack-check-prologue-12.c: New test. * gcc.target/riscv/stack-check-prologue-13.c: New test. * gcc.target/riscv/stack-check-prologue-14.c: New test. * gcc.target/riscv/stack-check-prologue-15.c: New test. * gcc.target/riscv/stack-check-prologue-2.c: New test. * gcc.target/riscv/stack-check-prologue-3.c: New test. * gcc.target/riscv/stack-check-prologue-4.c: New test. * gcc.target/riscv/stack-check-prologue-5.c: New test. * gcc.target/riscv/stack-check-prologue-6.c: New test. * gcc.target/riscv/stack-check-prologue-7.c: New test. * gcc.target/riscv/stack-check-prologue-8.c: New test. * gcc.target/riscv/stack-check-prologue-9.c: New test. * gcc.target/riscv/stack-check-prologue.h: New file. * lib/target-supports.exp (check_effective_target_supports_stack_clash_protection): Add riscv. (check_effective_target_caller_implicit_probes): Likewise. --- gcc/config/riscv/riscv.cc | 244 +++++++++++++++--- gcc/config/riscv/riscv.h | 8 + gcc/testsuite/gcc.dg/params/blocksort-part.c | 2 +- gcc/testsuite/gcc.dg/pr82788.c | 2 +- gcc/testsuite/gcc.dg/stack-check-6.c | 2 +- gcc/testsuite/gcc.dg/stack-check-6a.c | 2 +- .../gcc.target/riscv/stack-check-12.c | 23 ++ .../gcc.target/riscv/stack-check-13.c | 26 ++ .../gcc.target/riscv/stack-check-cfa-1.c | 12 + .../gcc.target/riscv/stack-check-cfa-2.c | 13 + .../gcc.target/riscv/stack-check-prologue-1.c | 9 + .../riscv/stack-check-prologue-10.c | 11 + .../riscv/stack-check-prologue-11.c | 11 + .../riscv/stack-check-prologue-12.c | 15 ++ .../riscv/stack-check-prologue-13.c | 20 ++ .../riscv/stack-check-prologue-14.c | 24 ++ .../riscv/stack-check-prologue-15.c | 23 ++ .../gcc.target/riscv/stack-check-prologue-2.c | 10 + .../gcc.target/riscv/stack-check-prologue-3.c | 11 + .../gcc.target/riscv/stack-check-prologue-4.c | 11 + .../gcc.target/riscv/stack-check-prologue-5.c | 11 + .../gcc.target/riscv/stack-check-prologue-6.c | 11 + .../gcc.target/riscv/stack-check-prologue-7.c | 11 + .../gcc.target/riscv/stack-check-prologue-8.c | 10 + .../gcc.target/riscv/stack-check-prologue-9.c | 11 + .../gcc.target/riscv/stack-check-prologue.h | 5 + gcc/testsuite/lib/target-supports.exp | 6 +- 27 files changed, 504 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-12.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-13.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-cfa-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-cfa-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-10.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-11.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-12.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-13.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-14.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-15.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-5.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-6.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-7.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-8.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue-9.c create mode 100644 gcc/testsuite/gcc.target/riscv/stack-check-prologue.h diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 89fc8966654..292d190f319 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -7950,6 +7950,191 @@ get_multi_push_fpr_mask (unsigned max_fprs_push) return mask_fprs_push; } +/* Allocate SIZE bytes of stack space using TEMP1 as a scratch register. + If SIZE is not large enough to require a probe this function will only + adjust the stack. + + We emit barriers after each stack adjustment to prevent optimizations from + breaking the invariant that we never drop the stack more than a page. This + invariant is needed to make it easier to correctly handle asynchronous + events, e.g. if we were to allow the stack to be dropped by more than a page + and then have multiple probes up and we take a signal somewhere in between + then the signal handler doesn't know the state of the stack and can make no + assumptions about which pages have been probed. */ + +static void +riscv_allocate_and_probe_stack_space (rtx temp1, HOST_WIDE_INT size) +{ + HOST_WIDE_INT guard_size + = 1 << param_stack_clash_protection_guard_size; + HOST_WIDE_INT guard_used_by_caller = STACK_CLASH_CALLER_GUARD; + HOST_WIDE_INT byte_sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT; + HOST_WIDE_INT min_probe_threshold = guard_size - guard_used_by_caller; + rtx insn; + + /* We should always have a positive probe threshold. */ + gcc_assert (min_probe_threshold > 0); + + /* If SIZE is not large enough to require probing, just adjust the stack and + exit. */ + if (known_lt (size, min_probe_threshold) + || !flag_stack_clash_protection) + { + if (flag_stack_clash_protection) + { + if (known_eq (cfun->machine->frame.total_size, 0)) + dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false); + else + dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true); + } + + if (SMALL_OPERAND (-size)) + { + insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-size)); + RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + } + else if (SUM_OF_TWO_S12_ALGN (-size)) + { + HOST_WIDE_INT one, two; + riscv_split_sum_of_two_s12 (-size, &one, &two); + insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (one)); + RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (two)); + RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + } + else + { + temp1 = riscv_force_temporary (temp1, GEN_INT (-size)); + emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, temp1)); + insn = plus_constant (Pmode, stack_pointer_rtx, -size); + insn = gen_rtx_SET (stack_pointer_rtx, insn); + riscv_set_frame_expr (insn); + } + + /* We must have allocated the remainder of the stack frame. + Emit a stack tie if we have a frame pointer so that the + allocation is ordered WRT fp setup and subsequent writes + into the frame. */ + if (frame_pointer_needed) + riscv_emit_stack_tie (hard_frame_pointer_rtx); + + return; + } + + gcc_assert (multiple_p (size, byte_sp_alignment)); + + if (dump_file) + fprintf (dump_file, + "Stack clash prologue: " HOST_WIDE_INT_PRINT_DEC + " bytes, probing will be required.\n", size); + + /* Round size to the nearest multiple of guard_size, and calculate the + residual as the difference between the original size and the rounded + size. */ + HOST_WIDE_INT rounded_size = ROUND_DOWN (size, guard_size); + HOST_WIDE_INT residual = size - rounded_size; + + /* We can handle a small number of allocations/probes inline. Otherwise + punt to a loop. */ + if (rounded_size <= STACK_CLASH_MAX_UNROLL_PAGES * guard_size) + { + temp1 = riscv_force_temporary (temp1, gen_int_mode (guard_size, Pmode)); + for (HOST_WIDE_INT i = 0; i < rounded_size; i += guard_size) + { + emit_insn (gen_sub3_insn (stack_pointer_rtx, stack_pointer_rtx, temp1)); + insn = plus_constant (Pmode, stack_pointer_rtx, -guard_size); + insn = gen_rtx_SET (stack_pointer_rtx, insn); + riscv_set_frame_expr (insn); + emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, + guard_used_by_caller)); + emit_insn (gen_blockage ()); + } + dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size); + } + else + { + /* Compute the ending address. */ + temp1 = riscv_force_temporary (temp1, gen_int_mode (rounded_size, Pmode)); + insn = emit_insn (gen_sub3_insn (temp1, stack_pointer_rtx, temp1)); + + if (!frame_pointer_needed) + { + /* We want the CFA independent of the stack pointer for the + duration of the loop. */ + add_reg_note (insn, REG_CFA_DEF_CFA, + plus_constant (Pmode, temp1, rounded_size)); + RTX_FRAME_RELATED_P (insn) = 1; + } + + /* Allocate and probe the stack. */ + + rtx temp2 = gen_rtx_REG (Pmode, RISCV_PROLOGUE_TEMP2_REGNUM); + temp2 = riscv_force_temporary (temp2, gen_int_mode (guard_size, Pmode)); + + /* Loop. */ + rtx label = gen_label_rtx (); + emit_label (label); + + emit_insn (gen_sub3_insn (stack_pointer_rtx, stack_pointer_rtx, temp2)); + emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, + guard_used_by_caller)); + emit_insn (gen_blockage ()); + + /* Check if the stack pointer is at the ending address. */ + riscv_expand_conditional_branch (label, NE, stack_pointer_rtx, temp1); + JUMP_LABEL (get_last_insn ()) = label; + + emit_insn (gen_blockage ()); + + /* Now reset the CFA register if needed. */ + if (!frame_pointer_needed) + { + insn = get_last_insn (); + add_reg_note (insn, REG_CFA_DEF_CFA, + plus_constant (Pmode, stack_pointer_rtx, rounded_size)); + RTX_FRAME_RELATED_P (insn) = 1; + } + + dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size); + } + + /* Handle any residuals. Residuals of at least MIN_PROBE_THRESHOLD have to + be probed. This maintains the requirement that each page is probed at + least once. For initial probing we probe only if the allocation is + more than GUARD_SIZE - buffer, and below the saved registers we probe + if the amount is larger than buffer. GUARD_SIZE - buffer + buffer == + GUARD_SIZE. This works that for any allocation that is large enough to + trigger a probe here, we'll have at least one, and if they're not large + enough for this code to emit anything for them, The page would have been + probed by the saving of FP/LR either by this function or any callees. If + we don't have any callees then we won't have more stack adjustments and so + are still safe. */ + if (residual) + { + gcc_assert (guard_used_by_caller + byte_sp_alignment <= size); + + temp1 = riscv_force_temporary (temp1, gen_int_mode (residual, Pmode)); + emit_insn (gen_sub3_insn (stack_pointer_rtx, stack_pointer_rtx, temp1)); + insn = plus_constant (Pmode, stack_pointer_rtx, -residual); + insn = gen_rtx_SET (stack_pointer_rtx, insn); + riscv_set_frame_expr (insn); + if (residual >= min_probe_threshold) + { + if (dump_file) + fprintf (dump_file, + "Stack clash prologue residuals: " + HOST_WIDE_INT_PRINT_DEC " bytes, probing will be required." + "\n", residual); + + emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, + guard_used_by_caller)); + emit_insn (gen_blockage ()); + } + } +} + /* Expand the "prologue" pattern. */ void @@ -8112,42 +8297,14 @@ riscv_expand_prologue (void) return; } - if (SMALL_OPERAND (-constant_frame)) - { - insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-constant_frame)); - RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; - } - else if (SUM_OF_TWO_S12_ALGN (-constant_frame)) - { - HOST_WIDE_INT one, two; - riscv_split_sum_of_two_s12 (-constant_frame, &one, &two); - insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (one)); - RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; - insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (two)); - RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; - } + riscv_allocate_and_probe_stack_space (RISCV_PROLOGUE_TEMP (Pmode), constant_frame); + } + else if (flag_stack_clash_protection) + { + if (known_eq (frame->total_size, 0)) + dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false); else - { - riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), GEN_INT (-constant_frame)); - emit_insn (gen_add3_insn (stack_pointer_rtx, - stack_pointer_rtx, - RISCV_PROLOGUE_TEMP (Pmode))); - - /* Describe the effect of the previous instructions. */ - insn = plus_constant (Pmode, stack_pointer_rtx, -constant_frame); - insn = gen_rtx_SET (stack_pointer_rtx, insn); - riscv_set_frame_expr (insn); - } - - /* We must have allocated the remainder of the stack frame. - Emit a stack tie if we have a frame pointer so that the - allocation is ordered WRT fp setup and subsequent writes - into the frame. */ - if (frame_pointer_needed) - riscv_emit_stack_tie (hard_frame_pointer_rtx); + dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true); } } @@ -9894,6 +10051,23 @@ riscv_option_override (void) riscv_stack_protector_guard_offset = offs; } + int guard_size = param_stack_clash_protection_guard_size; + + /* Enforce that interval is the same size as guard size so the mid-end does + the right thing. */ + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + param_stack_clash_protection_probe_interval, + guard_size); + + /* The maybe_set calls won't update the value if the user has explicitly set + one. Which means we need to validate that probing interval and guard size + are equal. */ + int probe_interval + = param_stack_clash_protection_probe_interval; + if (guard_size != probe_interval) + error ("stack clash guard size %<%d%> must be equal to probing interval " + "%<%d%>", guard_size, probe_interval); + SET_OPTION_IF_UNSET (&global_options, &global_options_set, param_sched_pressure_algorithm, SCHED_PRESSURE_MODEL); diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 6f040011864..9670c7df8f7 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -1260,4 +1260,12 @@ extern void riscv_remove_unneeded_save_restore_calls (void); /* Check TLS Descriptors mechanism is selected. */ #define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS) +/* This value is the amount of bytes a caller is allowed to drop the stack + before probing has to be done for stack clash protection. */ +#define STACK_CLASH_CALLER_GUARD 1024 + +/* This value controls how many pages we manually unroll the loop for when + generating stack clash probes. */ +#define STACK_CLASH_MAX_UNROLL_PAGES 4 + #endif /* ! GCC_RISCV_H */ diff --git a/gcc/testsuite/gcc.dg/params/blocksort-part.c b/gcc/testsuite/gcc.dg/params/blocksort-part.c index cc15223c0de..72cd5da322c 100644 --- a/gcc/testsuite/gcc.dg/params/blocksort-part.c +++ b/gcc/testsuite/gcc.dg/params/blocksort-part.c @@ -1,4 +1,4 @@ -/* { dg-skip-if "AArch64 does not support these bounds." { aarch64*-*-* } { "--param stack-clash-protection-*" } } */ +/* { dg-skip-if "RISC-V and AArch64 do not support these bounds." { riscv*-*-* aarch64*-*-* } { "--param stack-clash-protection-*" } } */ /* { dg-skip-if "For 32-bit hosts such param is too much and even for 64-bit might require hundreds of GB of RAM" { *-*-* } { "--param min-nondebug-insn-uid=1073741824" } } */ /*-------------------------------------------------------------*/ diff --git a/gcc/testsuite/gcc.dg/pr82788.c b/gcc/testsuite/gcc.dg/pr82788.c index 41c442f61a6..f5cb333f619 100644 --- a/gcc/testsuite/gcc.dg/pr82788.c +++ b/gcc/testsuite/gcc.dg/pr82788.c @@ -1,5 +1,5 @@ /* { dg-do run } */ /* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-probe-interval=10 --param stack-clash-protection-guard-size=12" } */ /* { dg-require-effective-target supports_stack_clash_protection } */ -/* { dg-skip-if "AArch64 does not support this interval." { aarch64*-*-* } } */ +/* { dg-skip-if "RISC-V and AArch64 do not support this interval." { riscv*-*-* aarch64*-*-* } } */ int main() { int a[1442]; return 0;} diff --git a/gcc/testsuite/gcc.dg/stack-check-6.c b/gcc/testsuite/gcc.dg/stack-check-6.c index fe75612b737..50eb1924602 100644 --- a/gcc/testsuite/gcc.dg/stack-check-6.c +++ b/gcc/testsuite/gcc.dg/stack-check-6.c @@ -48,7 +48,7 @@ f7 (void) /* { dg-final { scan-rtl-dump-times "Stack clash inline probes" 2 "pro_and_epilogue" } } */ /* { dg-final { scan-rtl-dump-times "Stack clash probe loop" 2 "pro_and_epilogue" } } */ -/* { dg-final { scan-rtl-dump-times "Stack clash residual allocation in prologue" 4 "pro_and_epilogue" } } */ +/* { dg-final { scan-rtl-dump-times "Stack clash residual allocation in prologue" 4 "pro_and_epilogue" { target { ! riscv*-*-* } } } } */ /* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 4 "pro_and_epilogue" } } */ /* { dg-final { scan-rtl-dump-times "Stack clash no frame pointer needed" 4 "pro_and_epilogue" { target { ! frame_pointer_for_non_leaf } } } } */ diff --git a/gcc/testsuite/gcc.dg/stack-check-6a.c b/gcc/testsuite/gcc.dg/stack-check-6a.c index 68dd9bc48a0..8c6b5367afc 100644 --- a/gcc/testsuite/gcc.dg/stack-check-6a.c +++ b/gcc/testsuite/gcc.dg/stack-check-6a.c @@ -5,7 +5,7 @@ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=16" } */ /* { dg-require-effective-target supports_stack_clash_protection } */ /* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ -/* { dg-skip-if "" { aarch64*-*-* } } */ +/* { dg-skip-if "" { riscv*-*-* aarch64*-*-* } } */ #include "stack-check-6.c" diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-12.c b/gcc/testsuite/gcc.target/riscv/stack-check-12.c new file mode 100644 index 00000000000..ceb9acc3c40 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-12.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector --param stack-clash-protection-guard-size=16" } */ +/* { dg-skip-if "" { *-*-* } { "-g"} } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +typedef unsigned __attribute__((mode(DI))) uint64_t; + +extern void arf (uint64_t *, uint64_t *); +void +frob () +{ + uint64_t num[10000]; + uint64_t den[10000]; + arf (den, num); +} + +/* This verifies that the scheduler did not break the dependencies + by adjusting the offsets within the probe and that the scheduler + did not reorder around the stack probes. */ +/* { dg-final { scan-assembler-times "li\\tt0,65536" 1 } } */ +/* { dg-final { scan-assembler-times "sub\\tsp,sp,t0\\n\\tsd\\tzero,1024\\(sp\\)" 2 } } */ +/* There is some residual allocation, but we don't care about that. Only that it's not probed. */ +/* { dg-final { scan-assembler-times "sd\\tzero," 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-13.c b/gcc/testsuite/gcc.target/riscv/stack-check-13.c new file mode 100644 index 00000000000..abd8a32b712 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-13.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -fno-asynchronous-unwind-tables -fno-unwind-tables" } */ +/* { dg-skip-if "" { *-*-* } { "-g"} } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define ARG32(X) X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X +#define ARG384(X) ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X), ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X),ARG32(X) +void out1(ARG384(__int128)); +int t1(int); + +int t3(int x) +{ + if (x < 1000) + return t1 (x) + 1; + + out1 (ARG384(1)); + return 0; +} + + + +/* This test creates a large (> 1k) outgoing argument area that needs + to be probed. We don't test the exact size of the space or the + exact offset to make the test a little less sensitive to trivial + output changes. */ +/* { dg-final { scan-assembler-times "sub\\tsp,sp,t0\\n\\tsd\\tzero,1024\\(sp\\)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-cfa-1.c b/gcc/testsuite/gcc.target/riscv/stack-check-cfa-1.c new file mode 100644 index 00000000000..60b01578692 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-cfa-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -funwind-tables -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 128*1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {\.cfi_def_cfa [0-9]+, 131072} 1 } } */ +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_register 2} 1 } } */ +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 0} 1 } } */ + +/* Checks that the CFA notes are correct for every sp adjustment. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-cfa-2.c b/gcc/testsuite/gcc.target/riscv/stack-check-cfa-2.c new file mode 100644 index 00000000000..9d36a302222 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-cfa-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -funwind-tables -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 80*1024 + 512 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {\.cfi_def_cfa [0-9]+, 81920} 1 } } */ +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_register 2} 1 } } */ +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 82432} 1 } } */ +/* { dg-final { scan-assembler-times {\.cfi_def_cfa_offset 0} 1 } } */ + +/* Checks that the CFA notes are correct for every sp adjustment. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-1.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-1.c new file mode 100644 index 00000000000..9f2c527a5ed --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 128 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-not "sd\tzero," } } */ +/* SIZE is smaller than guard-size - 1Kb so no probe expected. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-10.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-10.c new file mode 100644 index 00000000000..fd171c30f89 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-10.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE (6 * 4 * 1024) + (1 * 3 * 1024) + 512 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 2 } } */ + +/* SIZE is more than 4x guard-size and remainder larger than guard-size - 1Kb, + 1 probe expected in a loop and 1 residual probe. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-11.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-11.c new file mode 100644 index 00000000000..ebe3b139eb0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-11.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE (6 * 4 * 1024) + (1 * 2 * 1024) +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ + +/* SIZE is more than 4x guard-size and remainder larger than guard-size - 1Kb, + 1 probe expected in a loop and 1 residual probe. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-12.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-12.c new file mode 100644 index 00000000000..2a001ea8b1f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-12.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection --param stack-clash-protection-guard-size=16 -fomit-frame-pointer -momit-leaf-frame-pointer -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +void +f (void) +{ + volatile int x[16384 + 1000]; + x[0] = 0; +} + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ + +/* SIZE is more than 1 guard-size, but only one 64KB page is used, expect only 1 + probe. Leaf function and omitting leaf pointers. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-13.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-13.c new file mode 100644 index 00000000000..d97f69a943f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-13.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection --param stack-clash-protection-guard-size=16 -fomit-frame-pointer -momit-leaf-frame-pointer -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +void h (void) __attribute__ ((noreturn)); + +void +f (void) +{ + volatile int x[16384 + 1000]; + x[30]=0; + h (); +} + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ +/* { dg-final { scan-assembler-times {sw\tzero,120\(sp\)} 1 } } */ + +/* SIZE is more than 1 guard-size, but only one 64KB page is used, expect only 1 + probe. Leaf function and omitting leaf pointers, tail call to noreturn which + may only omit an epilogue and not a prologue. Checking for LR saving. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-14.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-14.c new file mode 100644 index 00000000000..bd263fbbd80 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-14.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection --param stack-clash-protection-guard-size=16 -fomit-frame-pointer -momit-leaf-frame-pointer -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +void h (void) __attribute__ ((noreturn)); + +void +f (void) +{ + volatile int x[16384 + 1000]; + if (x[0]) + h (); + x[345] = 1; + h (); +} + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ +/* { dg-final { scan-assembler-times {sd\tra,8\(sp\)} 1 } } */ + +/* SIZE is more than 1 guard-size, two 64k pages used, expect only 1 explicit + probe at 1024 and one implicit probe due to LR being saved. Leaf function + and omitting leaf pointers, tail call to noreturn which may only omit an + epilogue and not a prologue and control flow in between. Checking for + LR saving. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-15.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-15.c new file mode 100644 index 00000000000..f175e6f5b8f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-15.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection --param stack-clash-protection-guard-size=16 -fomit-frame-pointer -momit-leaf-frame-pointer -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +void g (volatile int *x) ; +void h (void) __attribute__ ((noreturn)); + +void +f (void) +{ + volatile int x[16384 + 1000]; + g (x); + h (); +} + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ +/* { dg-final { scan-assembler-times {sd\tra,8\(sp\)} 1 } } */ + +/* SIZE is more than 1 guard-size, two 64k pages used, expect only 1 explicit + probe at 1024 and one implicit probe due to LR being saved. Leaf function + and omitting leaf pointers, normal function call followed by a tail call to + noreturn which may only omit an epilogue and not a prologue and control flow + in between. Checking for LR saving. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-2.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-2.c new file mode 100644 index 00000000000..9c78b1ebaf1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 2 * 1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-not "sd\tzero," } } */ + +/* SIZE is smaller than guard-size - 1Kb so no probe expected. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-3.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-3.c new file mode 100644 index 00000000000..2c7e55acae6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 3 * 1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times "sd\tzero," 1 } } */ + +/* SIZE is exactly guard-size - 1Kb, boundary condition so 1 probe expected. +*/ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-4.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-4.c new file mode 100644 index 00000000000..506ea7b19c8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 3 * 1024 + 512 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ + +/* SIZE is more than guard-size - 1Kb and remainder is less than 1kB, + 1 probe expected. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-5.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-5.c new file mode 100644 index 00000000000..4c50a2a47a2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-5.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 4 * 1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ + +/* SIZE is more than guard-size - 1Kb and remainder is zero, + 1 probe expected, boundary condition. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-6.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-6.c new file mode 100644 index 00000000000..db39ecdc39f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-6.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 5 * 1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ + +/* SIZE is more than guard-size - 1Kb and remainder is equal to 1kB, + 1 probe expected. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-7.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-7.c new file mode 100644 index 00000000000..b394849136d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-7.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 7 * 1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 2 } } */ + +/* SIZE is more than 1x guard-size and remainder equal than guard-size - 1Kb, + 2 probe expected, unrolled, no loop. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-8.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-8.c new file mode 100644 index 00000000000..6366cacc520 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-8.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 8 * 1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 2 } } */ + +/* SIZE is more than 2x guard-size and no remainder, unrolled, no loop. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue-9.c b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-9.c new file mode 100644 index 00000000000..5e65750b9e8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue-9.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fstack-clash-protection -fno-stack-protector" } */ +/* { dg-require-effective-target supports_stack_clash_protection } */ + +#define SIZE 6 * 4 * 1024 +#include "stack-check-prologue.h" + +/* { dg-final { scan-assembler-times {sd\tzero,1024\(sp\)} 1 } } */ + +/* SIZE is more than 4x guard-size and no remainder, 1 probe expected in a loop + and no residual probe. */ diff --git a/gcc/testsuite/gcc.target/riscv/stack-check-prologue.h b/gcc/testsuite/gcc.target/riscv/stack-check-prologue.h new file mode 100644 index 00000000000..b7e06aedb81 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/stack-check-prologue.h @@ -0,0 +1,5 @@ +int f_test (int x) +{ + char arr[SIZE]; + return arr[x]; +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index daa0c75d2bc..3d7a4691624 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -12718,7 +12718,7 @@ proc check_effective_target_supports_stack_clash_protection { } { if { [istarget x86_64-*-*] || [istarget i?86-*-*] || [istarget powerpc*-*-*] || [istarget rs6000*-*-*] || [istarget aarch64*-**] || [istarget s390*-*-*] - || [istarget loongarch64*-**] } { + || [istarget loongarch64*-**] || [istarget riscv64*-**] } { return 1 } return 0 @@ -12778,6 +12778,10 @@ proc check_effective_target_caller_implicit_probes { } { return 1; } + if { [istarget riscv64*-*-*] } { + return 1; + } + if { [istarget loongarch64*-*-*] } { return 1; }