Re: [PATCH V2] rs6000: Support to build constants by li/lis+oris/xoris

2022-10-26 Thread Jiufu Guo via Gcc-patches
Jiufu Guo  writes:

> index 000..ebd9ea88993
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/pr106708.c
> @@ -0,0 +1,12 @@
> +/* PR target/106708 */
> +/* { dg-do compile } } */
Typo, should be: +/* { dg-do compile } */>

BR,
Jeff(Jiufu)


[PATCH v2] Add -gcodeview option

2022-10-26 Thread Mark Harmstone
Changed to double dashes as per
https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604287.html.

---
 gcc/common.opt  | 4 
 gcc/doc/invoke.texi | 7 +++
 gcc/gcc.cc  | 4 
 gcc/opts.cc | 3 +++
 4 files changed, 18 insertions(+)

diff --git a/gcc/common.opt b/gcc/common.opt
index 8a0dafc522d..77103f961d8 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3253,6 +3253,10 @@ gas-locview-support
 Common Driver Var(dwarf2out_as_locview_support)
 Assume assembler support for view in (DWARF2+) .loc directives.
 
+gcodeview
+Common Driver JoinedOrMissing
+Generate debug information in CodeView format.
+
 gcoff
 Common Driver WarnRemoved
 Does nothing.  Preserved for backward compatibility.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ff6c338bedb..2d29fd2611d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -483,6 +483,7 @@ Objective-C and Objective-C++ Dialects}.
 -gstabs  -gstabs+  -gstrict-dwarf  -gno-strict-dwarf @gol
 -gas-loc-support  -gno-as-loc-support @gol
 -gas-locview-support  -gno-as-locview-support @gol
+-gcodeview @gol
 -gcolumn-info  -gno-column-info  -gdwarf32  -gdwarf64 @gol
 -gstatement-frontiers  -gno-statement-frontiers @gol
 -gvariable-location-views  -gno-variable-location-views @gol
@@ -10358,6 +10359,12 @@ assembler (GAS) to fail with an error.
 Produce debugging information in Alpha/VMS debug format (if that is
 supported).  This is the format used by DEBUG on Alpha/VMS systems.
 
+@item -gcodeview
+@opindex gcodeview
+Produce debugging information in CodeView debug format (if that is
+supported).  This is the format used by Microsoft Visual C++ on
+Windows.
+
 @item -g@var{level}
 @itemx -ggdb@var{level}
 @itemx -gstabs@var{level}
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index bb07cc244e3..d3aa3deeaf7 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -4608,6 +4608,10 @@ driver_handle_option (struct gcc_options *opts,
   do_save = false;
   break;
 
+case OPT_gcodeview:
+  add_infile ("--pdb=", "*");
+  break;
+
 default:
   /* Various driver options need no special processing at this
 point, having been handled in a prescan above or being
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 3a89da2dd03..e2633ee5439 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -3089,6 +3089,9 @@ common_handle_option (struct gcc_options *opts,
   set_debug_level (NO_DEBUG, 2, arg, opts, opts_set, loc);
   break;
 
+case OPT_gcodeview:
+  break;
+
 case OPT_gstabs:
 case OPT_gstabs_:
   set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set,
-- 
2.37.4



Re: [PATCH] Add -gcodeview option

2022-10-26 Thread Mark Harmstone

On 25/10/22 09:21, Martin Storsjö wrote:

Btw, stylistically, should we strive towards using double dashes for the pdb option? I 
think that's the most canonical way for such getopt options (even though it doesn't make 
any practical difference). I've started trying to update various users to prefer that form 
(together with preferring -Wl,--pdb= over -Wl,--pdb,) and probably 
will send a few more.

Thanks Martin. Yes, I agree.


Re: [PATCH 1/2]middle-end: RFC: On expansion of conditional branches, give hint if argument is a truth type to backend

2022-10-26 Thread Andrew Pinski via Gcc-patches
On Fri, Sep 23, 2022 at 2:26 AM Tamar Christina via Gcc-patches
 wrote:
>
> Hi All,
>
> This is an RFC to figure out how to deal with targets that don't have native
> comparisons against QImode values.
>
> Booleans, at least in C99 and higher are 0-1 valued.  This means that we only
> really need to test a single bit.  However in RTL we no longer have this
> information available and just have an SImode value (due to the promotion of
> QImode to SImode).
>
> This RFC fixes it by emitting an explicit & 1 during the expansion of the
> conditional branch.
>
> However it's unlikely that we want to do this unconditionally.  Most targets
> I've tested seem to have harmless code changes, like x86 changes from testb to
> andl, $1.
>
> So I have two questions:
>
> 1. Should I limit this behind a target macro? Or should I just leave it for 
> all
>targets and deal with the fallout.
> 2. How can I tell whether the C99 0-1 values bools are being used or the older
>0, non-0 variant?
>
> Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
> However there are some benign codegen changes on x86, testb changed to andl 
> $1.
>
> This pattern occurs more than 120,000 times in SPECCPU 2017 and so is quite 
> common.
>
> Thanks,
> Tamar
>
> gcc/ChangeLog:
>
> * tree.h (tree_zero_one_valued_p): New.
> * dojump.cc (do_jump): Add & 1 if truth type.

Just FYI, I think this fixes/improves https://gcc.gnu.org/PR101806 .

Thanks,
Andrew

>
> --- inline copy of patch --
> diff --git a/gcc/dojump.cc b/gcc/dojump.cc
> index 
> 2af0cd1aca3b6af13d5d8799094ee93f18022296..8eaf1be49cd12298e61c6946ae79ca9de6197864
>  100644
> --- a/gcc/dojump.cc
> +++ b/gcc/dojump.cc
> @@ -605,7 +605,17 @@ do_jump (tree exp, rtx_code_label *if_false_label,
>/* Fall through and generate the normal code.  */
>  default:
>  normal:
> -  temp = expand_normal (exp);
> +  tree cmp = exp;
> +  /* If the expression is a truth type then explicitly generate an & 1
> +to indicate to the target that it's a zero-one values type.  This
> +allows the target to further optimize the comparison should it
> +choose to.  */
> +  if (tree_zero_one_valued_p (exp))
> +   {
> + type = TREE_TYPE (exp);
> + cmp = build2 (BIT_AND_EXPR, type, exp, build_int_cstu (type, 1));
> +   }
> +  temp = expand_normal (cmp);
>do_pending_stack_adjust ();
>/* The RTL optimizers prefer comparisons against pseudos.  */
>if (GET_CODE (temp) == SUBREG)
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 
> 8f8a9660c9e0605eb516de194640b8c1b531b798..be3d2dee82f692e81082cf21c878c10f9fe9e1f1
>  100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -4690,6 +4690,7 @@ extern tree signed_or_unsigned_type_for (int, tree);
>  extern tree signed_type_for (tree);
>  extern tree unsigned_type_for (tree);
>  extern bool is_truth_type_for (tree, tree);
> +extern bool tree_zero_one_valued_p (tree);
>  extern tree truth_type_for (tree);
>  extern tree build_pointer_type_for_mode (tree, machine_mode, bool);
>  extern tree build_pointer_type (tree);
>
>
>
>
> --


Re: [PATCH 2/3]AArch64 Promote function arguments using a paradoxical subreg when beneficial.

2022-10-26 Thread Andrew Pinski via Gcc-patches
On Fri, May 13, 2022 at 10:14 AM Tamar Christina via Gcc-patches
 wrote:
>
> Hi All,
>
> The PROMOTE_MODE always promotes 8 and 16-bit parameters to 32-bits.
> This promotion is not required for the ABI which states:
>
>
> ```
> C.9 If the argument is an Integral or Pointer Type, the size of the 
> argument is
> less than or equal to 8 bytes and the NGRN is less than 8, the argument is
> copied to the least significant bits in x[NGRN]. The NGRN is incremented by 
> one.
> The argument has now been allocated.
>
> C.16If the size of the argument is less than 8 bytes then the size of the
> argument is set to 8 bytes. The effect is as if the argument was copied to the
> least significant bits of a 64-bit register and the remaining bits filled with
> unspecified values
> ```
>
> That is, the bits in the registers are unspecified and callees cannot assume
> any particular status.
>
> This means that we can avoid the promotion and still get correct code as the
> language level promotion rules require values to be extended when the bits are
> significant.
>
> So if we are .e.g OR-ing two 8-bit values no extend is needed as the top bits
> are irrelevant.  If we are doing e.g. addition, then the top bits *might* be
> relevant depending on the result type.  But the middle end will always
> contain the appropriate extend in those cases.
>
> The mid-end also has optimizations around this assumption and the AArch64 port
> actively undoes them.
>
> So for instance
>
> uint16_t fd (uint8_t xr){
> return xr + 1;
> }
>
> uint8_t fd2 (uint8_t xr){
> return xr + 1;
> }
>
> should produce
>
> fd: // @fd
> and w8, w0, #0xff
> add w0, w8, #1
> ret
> fd2:// @fd2
> add w0, w0, #1
> ret
>
> like clang does instead of
>
> fd:
> and w0, w0, 255
> add w0, w0, 1
> ret
> fd2:
> and w0, w0, 255
> add w0, w0, 1
> ret
>
> like we do now.  Removing this forced expansion maintains correctness but 
> fixes
> issues with various codegen defects.  It also brings us inline with clang.
>
> Note that C, C++ and Fortran etc all correctly specify what should happen 
> w.r.t
> extends and e.g. array indexing, pointer arith etc so we never get incorrect
> code.
>
> There is however a second reason for doing this promotion: RTL efficiency.
> The promotion stops us from having to promote the values to SI to be able to
> use them in instructions and then truncating again afterwards.
>
> To get both the efficiency and the simpler RTL we can instead promote to a
> paradoxical subreg.  This patch implements the hook for AArch64 and adds an
> explicit opt-out for values that feed into comparisons.  This is done because:
>
> 1. our comparisons patterns already allow us to absorb the zero extend
> 2. The extension allows us to use cbz/cbnz/tbz etc.  In some cases such as
>
> int foo (char a, char b)
> {
>if (a)
>  if (b)
>bar1 ();
>  else
>...
> else
>  if (b)
>bar2 ();
>  else
>...
> }
>
> by zero extending the value we can avoid having to repeatedly test the value
> before a branch.  Allowing the zero extend also allows our existing `ands`
> patterns to work as expected.
>
> Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
> I have to commit this and the last patch together but ease of review
> I have split them up here. However 209 missed optimization xfails are
> fixed.
>
> No performance difference on SPECCPU 2017 but no failures.
>
> Ok for master?

Did this patch ever get approved? It is a nice improvement that would
be nice to get into GCC 13 before the close of stage 1.

Thanks,
Andrew

>
> Thanks,
> Tamar
>
> gcc/ChangeLog:
>
> * config/aarch64/aarch64.cc (aarch64_promote_function_args_subreg_p):
> (TARGET_PROMOTE_FUNCTION_ARGS_SUBREG_P): New.
> * config/aarch64/aarch64.h (PROMOTE_MODE): Expand doc.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/aarch64/apc-subreg.c: New test.
>
> --- inline copy of patch --
> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
> index 
> efa46ac0b8799b5849b609d591186e26e5cb37ff..cc74a816fcc6458aa065246a30a4d2184692ad74
>  100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -34,7 +34,8 @@
>
>  #define REGISTER_TARGET_PRAGMAS() aarch64_register_pragmas ()
>
> -/* Target machine storage layout.  */
> +/* Target machine storage layout.  See also
> +   TARGET_PROMOTE_FUNCTION_ARGS_SUBREG_P.  */
>
>  #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE)\
>if (GET_MODE_CLASS (MODE) == MODE_INT\
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 
> 2f559600cff55af9d468e8d0810545583cc986f5..252d6c2af72afc1dfee1a86644a5753784b41f59
>  100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ 

Re: [v4 PATCH 0/4] RISC-V: Support z*inx extensions.

2022-10-26 Thread Kito Cheng via Gcc-patches
Verified with qemu, committed to master, thanks!

On Thu, Oct 20, 2022 at 5:43 PM jiawei  wrote:
>
> Zfinx extension[1] had already ratified. Here is the
> implementation patch set that reuse floating point pattern and ban
> the use of fpr when use z*inx as a target.
>
> Current works can be find in follow links, binutils and simulator
> works already supported on upstream.
>   https://github.com/pz9115/riscv-gcc/tree/zfinx-rebase
>
> Thanks for Tariq Kurd, Kito Cheng, Jim Willson,
> Jeremy Bennett helped us a lot with this work.
>
> [1] https://github.com/riscv/riscv-zfinx/blob/main/zfinx-1.0.0-rc.pdf
>
> Version log:
>
> v2: As Kito Cheng's comment, add Changelog part in patches, update imply
> info in riscv-common.c, remove useless check and update annotation in
> riscv.c.
>
> v3: Update with new isa-spec version 20191213, make zfinx imply zicsr as
> default, fix the lack of fcsr use in zfinx.
>
> v4: Rebase patch with upstream, add zhinx/zhinxmin extensions support.
> Add additional zhinx/zhinxmin same like zfh/zfhmin.
>
> Jiawei (4):
>   RISC-V: Minimal support of z*inx extension.
>   RISC-V: Target support for z*inx extension.
>   RISC-V: Limit regs use for z*inx extension.
>   RISC-V: Add zhinx/zhinxmin testcases.
>
>  gcc/common/config/riscv/riscv-common.cc   | 18 +
>  gcc/config/riscv/arch-canonicalize|  5 ++
>  gcc/config/riscv/constraints.md   |  5 +-
>  gcc/config/riscv/iterators.md |  6 +-
>  gcc/config/riscv/riscv-builtins.cc|  4 +-
>  gcc/config/riscv/riscv-c.cc   |  2 +-
>  gcc/config/riscv/riscv-opts.h | 10 +++
>  gcc/config/riscv/riscv.cc | 21 -
>  gcc/config/riscv/riscv.md | 78 ++-
>  gcc/config/riscv/riscv.opt|  3 +
>  .../gcc.target/riscv/_Float16-zhinx-1.c   | 10 +++
>  .../gcc.target/riscv/_Float16-zhinx-2.c   |  9 +++
>  .../gcc.target/riscv/_Float16-zhinx-3.c   |  9 +++
>  .../gcc.target/riscv/_Float16-zhinxmin-1.c| 10 +++
>  .../gcc.target/riscv/_Float16-zhinxmin-2.c| 10 +++
>  .../gcc.target/riscv/_Float16-zhinxmin-3.c| 10 +++
>  16 files changed, 160 insertions(+), 50 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zhinx-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zhinx-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zhinx-3.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zhinxmin-3.c
>
> --
> 2.25.1
>


Re: [v4 PATCH 3/4] RISC-V: Limit regs use for z*inx extension.

2022-10-26 Thread Kito Cheng via Gcc-patches
Hmmm 2 issue, but I fixed that anyway, otherwise LGTM.

> From: Jiawei 
>
> Limit z*inx abi support with 'ilp32','ilp32e','lp64' only.
> Use GPR instead FPR when 'zfinx' enable, Only use even registers
> in RV32 when 'zdinx' enable.
> Enable FLOAT16 when Zhinx/Zhinxmin enabled.
>
> Co-Authored-By: Sinan Lin.
>
> gcc/ChangeLog:
>
> * config/riscv/constraints.md (TARGET_ZFINX ? GR_REGS): Set GPRS
>   use while Zfinx is enable.
> * config/riscv/riscv.cc (riscv_hard_regno_mode_ok): Limit odd
>   registers use when Zdinx enable in RV32 cases.
> (riscv_option_override): New target enable MASK_FDIV.
> (riscv_libgcc_floating_mode_supported_p): New error info when
>   use incompatible arch
> (riscv_excess_precision): New target enable FLOAT16.
>
> ---
>  gcc/config/riscv/constraints.md |  5 +++--
>  gcc/config/riscv/riscv.cc   | 21 +
>  2 files changed, 20 insertions(+), 6 deletions(-)
>
> diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
> index 8997284f32e..c53e0f38920 100644
> --- a/gcc/config/riscv/constraints.md
> +++ b/gcc/config/riscv/constraints.md
> @@ -21,8 +21,9 @@
>
>  ;; Register constraints
>
> -(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
> -  "A floating-point register (if available).")
> +(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS :
> +  (TARGET_ZFINX ? GR_REGS) : NO_REGS"

(TARGET_ZFINX ? GR_REGS : NO_REGS)"

> +  "A floating-point register (if available, reuse GPR as FPR when use 
> zfinx).")
>
>  (define_register_constraint "j" "SIBCALL_REGS"
>"@internal")
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index ad57b995e7b..38631605b2c 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -5356,6 +5356,13 @@ riscv_hard_regno_mode_ok (unsigned int regno, 
> machine_mode mode)
> != call_used_or_fixed_reg_p (regno + i))
>return false;
>
> +  /* Only use even registers in RV32 ZDINX */
> +  if (!TARGET_64BIT && TARGET_ZDINX){
> +if (GET_MODE_CLASS (mode) == MODE_FLOAT &&
> + GET_MODE_UNIT_SIZE (mode) == GET_MODE_SIZE (DFmode))
> +return !(regno & 1);
> +  }
> +
>return true;
>  }
>
> @@ -5595,7 +5602,7 @@ riscv_option_override (void)
>  error ("%<-mdiv%> requires %<-march%> to subsume the % extension");
>
>/* Likewise floating-point division and square root.  */
> -  if (TARGET_HARD_FLOAT && (target_flags_explicit & MASK_FDIV) == 0)
> +  if ((TARGET_HARD_FLOAT || TARGET_ZFINX) && (target_flags_explicit & 
> MASK_FDIV) == 0)
>  target_flags |= MASK_FDIV;
>
>/* Handle -mtune, use -mcpu if -mtune is not given, and use default -mtune
> @@ -5641,6 +5648,11 @@ riscv_option_override (void)
>if (TARGET_RVE && riscv_abi != ABI_ILP32E)
>  error ("rv32e requires ilp32e ABI");
>
> +  // Zfinx require abi ilp32,ilp32e or lp64.
> +  if (TARGET_ZFINX && riscv_abi != ABI_ILP32
> +  && riscv_abi != ABI_LP64 && riscv_abi != ABI_ILP32E)
> +error ("z*inx requires ABI ilp32, ilp32e or lp64");
> +
>/* We do not yet support ILP32 on RV64.  */
>if (BITS_PER_WORD != POINTER_SIZE)
>  error ("ABI requires %<-march=rv%d%>", POINTER_SIZE);
> @@ -6273,7 +6285,7 @@ riscv_libgcc_floating_mode_supported_p 
> (scalar_float_mode mode)
> precision of the _FloatN type; evaluate all other operations and
> constants to the range and precision of the semantic type;
>
> -   If we have the zfh extensions then we support _Float16 in native
> +   If we have the zfh/zhinx extensions then we support _Float16 in native
> precision, so we should set this to 16.  */
>  static enum flt_eval_method
>  riscv_excess_precision (enum excess_precision_type type)
> @@ -6282,8 +6294,9 @@ riscv_excess_precision (enum excess_precision_type type)
>  {
>  case EXCESS_PRECISION_TYPE_FAST:
>  case EXCESS_PRECISION_TYPE_STANDARD:
> -  return (TARGET_ZFH ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
> -: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
> +  return ((TARGET_ZFH || TARGET_ZHINX || TARGET_ZHINXMIN)

Should be (TARGET_ZFH || TARGET_ZHINX)


> +   ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
> +   : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
>  case EXCESS_PRECISION_TYPE_IMPLICIT:
>  case EXCESS_PRECISION_TYPE_FLOAT16:
>return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> --
> 2.25.1
>


Re: [PATCH v3] Re: OpenMP: Generate SIMD clones for functions with "declare target"

2022-10-26 Thread Sandra Loosemore

On 10/20/22 08:07, Jakub Jelinek wrote:

Thus, IMHO it is exactly the pass_omp_simd_clone pass where you want to
implement this auto-simdization discovery, guarded with
#ifdef ACCEL_COMPILER and the new option (which means it will be done
only for gcn and not on the host right now).


I'm running into a practical difficulty with making this controlled by a 
static #ifdef: namely, testing.


One of my test cases examines the .s output to make sure that the clones 
are emitted as local symbols and not global.  I have not been able to 
find the symbol linkage information in any of the dump files, and I have 
also not been able to figure out how to get a .s file from the offload 
compiler even outside of the DejaGnu test harness.  (It's possible I am 
just an extreme dummy about the latter problem, but so far none of my 
colleagues here has been able to give me a recipe either.)


On top of that, I worry that this should be tested more broadly than for 
the one target we're presently focusing on (AMD GCN), and we'll get much 
more regular test coverage if it's also enabled for x86_64 target which 
has the necessary compute_vecsize_and_simdlen target hook.


I remember Carlos O'Donnell used to have a favorite mantra, "design for 
test".  So, maybe generalize the new -fopenmp-target-simd-clone option 
to take a parameter to force clones to be generated on the OpenMP host 
for test purposes?  The "declare target" directive already has a clause


device_type(host|nohost|any)

that defaults to "any"; maybe we could use that syntax like
-fopenmp-target-simd-clone=any
and use the intersection of the two sets to determine what to 
auto-generate clones for?


-Sandra


[committed] wwwdocs: style: Remove link to validator.w3.org in footer

2022-10-26 Thread Gerald Pfeifer
Martin reported that the link to validator.w3.org we had on every page
(hidden in the footer) is not working any more.

This used to be a nice feature, where following that link "hidden" in
a full stop would validate the respective page. Alas due to abuse by
marketing tools and increased focus on privacy current browers do not
provide so called referer information anymore, breaking this use case.

Pushed, with a bit of sadness. And I reran the preprocesser on all (and 
checked some) web pages.

Gerald
---
 htdocs/style.mhtml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/htdocs/style.mhtml b/htdocs/style.mhtml
index 98641c25..8afaa1e1 100644
--- a/htdocs/style.mhtml
+++ b/htdocs/style.mhtml
@@ -166,8 +166,7 @@ permitted in any medium, provided this notice is 
preserved.
 
 These pages are
 https://gcc.gnu.org/about.html;>maintained by the GCC team.
-Last modified http://validator.w3.org/check/referer;>.
+Last modified .
 
 
 
-- 
2.38.0


Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs

2022-10-26 Thread Alexandre Oliva via Gcc-patches
On Oct 25, 2022, Qing Zhao  wrote:

>> 'all' for leaf functions is likely wasteful.  If no other functions are
>> called, one can determine exactly which registers might carry
>> information out and thus need zeroing, and 'used' is thus likely enough,
>> depending on the purpose of register scrubbing.  (In some scenarios, it
>> might make sense to want scrubbing of all registers, even unused ones
>> that carry incoming values)

> Under what kinds of situations, we should clear the un-used registers
> for leaf functions?

The one (admittedly contrived) scenario that comes to mind is calling an
out-of-line, empty leaf function with 'all' for explicit register
scrubbing at desired points in the program.  I.e., this empty leaf
function would be in charge of scrubbing the caller's registers.  It
could even be tail-called.

I'm sure there are other scenarios in which keeping at least the
possibility of 'all' is useful.

> Now I am wondering whether we should make “leafy” mode by default then?

I'm not sure what you mean by default.  I think "skip" is the right
default for general use, where register scrubbing is not explicitly
requested.  When it is, perhaps -fzero-call-used-regs without
'=' could be 'leafy' indeed or, even better, the extended form
thereof that is in search of a name and so far unimplemented.

> Another thing is, do you have any information on how much this new mode can 
> save the 
> code size and run-time compared to mode “all”?

I'm afraid I have not performed any measurements.

>> I have not (yet?) implemented this variant; I haven't even found a name
>> I'm happy with for it.  (seal?  plug?  cork?  another leak antonym?)

> For this improvement, I am still thinking no need to add a new mode,
> just add it by default?

Even if it is default, it may still need a name to appear before
e.g. '-gpr'.  'default-gpr' might do, but I'm not happy with it either.


-- 
Alexandre Oliva, happy hackerhttps://FSFLA.org/blogs/lxo/
   Free Software Activist   GNU Toolchain Engineer
Disinformation flourishes because many people care deeply about injustice
but very few check the facts.  Ask me about 


[committed] analyzer: fixes to file-descriptor handling

2022-10-26 Thread David Malcolm via Gcc-patches
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r13-3515-g57bbf3a403bb1e.

gcc/analyzer/ChangeLog:
* sm-fd.cc (fd_state_machine::on_open): Transition to "unchecked"
when the mode is symbolic, rather than just on integer constants.
(fd_state_machine::check_for_open_fd): Don't complain about
unchecked values in the start state.

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/fd-3.c (test_5): Expect "opened here" message
even when flags are symbolic.
(test_read_from_symbolic_fd): New.
(test_write_to_symbolic_fd): New.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/sm-fd.cc| 34 ++--
 gcc/testsuite/gcc.dg/analyzer/fd-3.c | 18 ---
 2 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/gcc/analyzer/sm-fd.cc b/gcc/analyzer/sm-fd.cc
index 8a4c2088c74..ae846cd6ec8 100644
--- a/gcc/analyzer/sm-fd.cc
+++ b/gcc/analyzer/sm-fd.cc
@@ -940,25 +940,25 @@ fd_state_machine::on_open (sm_context *sm_ctxt, const 
supernode *node,
   if (lhs)
 {
   tree arg = gimple_call_arg (call, 1);
+  enum access_mode mode = READ_WRITE;
   if (TREE_CODE (arg) == INTEGER_CST)
{
  int flag = TREE_INT_CST_LOW (arg);
- enum access_mode mode = get_access_mode_from_flag (flag);
-
- switch (mode)
-   {
-   case READ_ONLY:
- sm_ctxt->on_transition (node, stmt, lhs, m_start,
- m_unchecked_read_only);
- break;
-   case WRITE_ONLY:
- sm_ctxt->on_transition (node, stmt, lhs, m_start,
- m_unchecked_write_only);
- break;
-   default:
- sm_ctxt->on_transition (node, stmt, lhs, m_start,
- m_unchecked_read_write);
-   }
+ mode = get_access_mode_from_flag (flag);
+   }
+  switch (mode)
+   {
+   case READ_ONLY:
+ sm_ctxt->on_transition (node, stmt, lhs, m_start,
+ m_unchecked_read_only);
+ break;
+   case WRITE_ONLY:
+ sm_ctxt->on_transition (node, stmt, lhs, m_start,
+ m_unchecked_write_only);
+ break;
+   default:
+ sm_ctxt->on_transition (node, stmt, lhs, m_start,
+ m_unchecked_read_write);
}
 }
   else
@@ -1096,7 +1096,7 @@ fd_state_machine::check_for_open_fd (
 
   else
 {
-  if (!(is_valid_fd_p (state) || (state == m_stop)))
+  if (!(is_valid_fd_p (state) || state == m_start || state == m_stop))
{
  if (!is_constant_fd_p (state))
sm_ctxt->warn (
diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-3.c 
b/gcc/testsuite/gcc.dg/analyzer/fd-3.c
index 55e84e3634a..8e71b14f71b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/fd-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/fd-3.c
@@ -50,9 +50,9 @@ test_5 (char *path, void *buf)
 int flags = O_RDONLY;
 if (some_condition())
 flags |= O_NOATIME;
-int fd = open (path, flags);
+int fd = open (path, flags); /* { dg-message "\\(1\\) opened here" } */
 read (fd, buf, 1); /* { dg-warning "'read' on possibly invalid file 
descriptor 'fd'" } */
-/* { dg-message "\\(1\\) 'fd' could be invalid" "" { target *-*-* } .-1 } 
*/
+/* { dg-message "\\(2\\) 'fd' could be invalid" "" { target *-*-* } .-1 } 
*/
 close (fd);   
 }
 
@@ -82,4 +82,16 @@ test_7 (char *path, void *buf)
 
 }
 close(fd);
-}
\ No newline at end of file
+}
+
+void
+test_read_from_symbolic_fd (int fd, void *buf)
+{
+  read (fd, buf, 1);
+}
+
+void
+test_write_to_symbolic_fd (int fd, void *buf)
+{
+  write (fd, buf, 1);
+}
-- 
2.26.3



[committed] analyzer: add sm-fd.dot

2022-10-26 Thread David Malcolm via Gcc-patches
Add a .dot file to document the file descriptor state machine.

gcc/analyzer/ChangeLog:
* sm-fd.dot: New file.

Signed-off-by: David Malcolm 
---
 gcc/analyzer/sm-fd.dot | 109 +
 1 file changed, 109 insertions(+)
 create mode 100644 gcc/analyzer/sm-fd.dot

diff --git a/gcc/analyzer/sm-fd.dot b/gcc/analyzer/sm-fd.dot
new file mode 100644
index 000..175daae44ae
--- /dev/null
+++ b/gcc/analyzer/sm-fd.dot
@@ -0,0 +1,109 @@
+/* An overview of the state machine from sm-fd.cc.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+   Contributed by David Malcolm .
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+/* Keep this in-sync with sm-dot.cc  */
+
+digraph "fd" {
+
+  /* STATES. */
+
+  /* Start state.  */
+  start;
+
+  /* States representing a file descriptor that hasn't yet been
+checked for validity after opening, for three different
+access modes.  */
+  unchecked_read_write;
+  unchecked_read_only;
+  unchecked_write_only;
+
+  /* States for representing a file descriptor that is known to be valid (>=
+0), for three different access modes.  */
+  valid_read_write;
+  valid_read_only;
+  valid_write_only;
+
+  /* State for a file descriptor that is known to be invalid (< 0). */
+  invalid;
+
+  /* State for a file descriptor that has been closed.  */
+  closed;
+
+  /* State for a file descriptor that we do not want to track anymore . */
+  stop;
+
+  /* TRANSITIONS. */
+
+  /* On "open".  */
+  start -> unchecked_read_only [label="on 'X = open(..., O_RDONLY);'"];
+  start -> unchecked_write_only [label="on 'X = open(..., O_WRONLY);'"];
+  start -> unchecked_read_write [label="on 'X = open(..., ...);'"];
+
+  /* On "creat".  */
+  start -> unchecked_write_only [label="on 'X = create(...);'"];
+
+  /* On "close".  */
+  start -> closed [label="on 'close(X);'"];
+  unchecked_read_write -> closed [label="on 'close(X);'"];
+  unchecked_read_only -> closed [label="on 'close(X);'"];
+  unchecked_write_only -> closed [label="on 'close(X);'"];
+  valid_read_write -> closed [label="on 'close(X);'"];
+  valid_read_only -> closed [label="on 'close(X);'"];
+  valid_write_only -> closed [label="on 'close(X);'"];
+  constant_fd -> closed [label="on 'close(X);'"];
+  closed -> stop [label="on 'close(X);':\nWarn('double close')"];
+
+  /* On "read".  */
+  closed -> closed [label="on 'read(X);':\nWarn('use after close')"];
+  unchecked_read_write -> unchecked_read_write [label="on 
'read(X);:\nWarn('use without check')'"];
+  unchecked_read_only -> unchecked_read_only [label="on 'read(X);:\nWarn('use 
without check')'"];
+  unchecked_write_only -> unchecked_write_only [label="on 
'read(X);:\nWarn('use without check')'"];
+  valid_write_only -> valid_write_only [label="on 'read(X);:\nWarn('access 
mode mismatch')'"];
+
+  /* On "write".  */
+  closed -> closed [label="on 'write(X);':\nWarn('use after close')"];
+  unchecked_read_write -> unchecked_read_write [label="on 
'write(X);:\nWarn('use without check')'"];
+  unchecked_read_only -> unchecked_read_only [label="on 'write(X);:\nWarn('use 
without check')'"];
+  unchecked_write_only -> unchecked_write_only [label="on 
'write(X);:\nWarn('use without check')'"];
+  valid_read_only -> valid_read_only [label="on 'write(X);:\nWarn('access mode 
mismatch')'"];
+
+  /* On "dup".  */
+  closed -> closed [label="on 'dup(X);':\nWarn('use after close')"];
+  /* plus stuff for the new fd.  */
+
+  /* On "pipe".  */
+  start -> valid_read_write [label="when 'pipe()' succeeds"];
+
+  /* on_condition.  */
+  unchecked_read_write -> valid_read_write [label="on 'X >= 0'"];
+  unchecked_read_only -> valid_read_only [label="on 'X >= 0'"];
+  unchecked_write_only -> valid_write_only [label="on 'X >= 0'"];
+  unchecked_read_write -> invalid [label="on 'X < 0'"];
+  unchecked_read_only -> invalid [label="on 'X < 0'"];
+  unchecked_write_only -> invalid [label="on 'X < 0'"];
+
+  /* Leaks.  */
+  unchecked_read_write -> stop [label="on leak:\nWarn('leak')"];
+  unchecked_read_only -> stop [label="on leak:\nWarn('leak')"];
+  unchecked_write_only -> stop [label="on leak:\nWarn('leak')"];
+  valid_read_write -> stop [label="on leak:\nWarn('leak')"];
+  valid_read_only -> stop [label="on leak:\nWarn('leak')"];
+  valid_write_only -> stop [label="on leak:\nWarn('leak')"];
+}
-- 
2.26.3



Re: Rust frontend patches v3

2022-10-26 Thread David Malcolm via Gcc-patches
On Wed, 2022-10-26 at 10:17 +0200, arthur.co...@embecosm.com wrote:
> This is the fixed version of our previous patch set for gccrs - We've
> adressed
> the comments raised in our previous emails.

[...snip...]

(Caveat: I'm not a global reviewer)

Sorry if this is answered in the docs in the patch kit, but a high-
level question: what's the interaction between gccrs and gcc's garbage
collector?  Are the only GC-managed objects (such as trees) either (a)
created near the end of the gccrs, or (b) common globals created at
initialization and with GTY roots?  Are there any points where a
collection happen within gccrs?  Or is almost everything stored using
gccrs's own data structures, and are these managed in the regular (non-
GC) heap?

I skimmed the patches and see that gccrs uses e.g. std::vector,
std::unique_ptr, std::map, and std::string; this seems reasonable to
me, but it got me thinking about memory management strategies.

I see various std::map e.g. in Rust::Compile::Context; so e.g.
is the GC guaranteed never to collect whilst this is live?

Hope this is constructive
Dave



Re: [PATCH Rust front-end v3 35/46] gccrs: Add metadata ouptput pass

2022-10-26 Thread David Malcolm via Gcc-patches
%{On Wed, 2022-10-26 at 10:18 +0200, arthur.co...@embecosm.com wrote:
> From: Philip Herron 
> 
> Extern crates statements to tell the front-end to look for another
> library.
> The mechanism here is heavily inspired from gccgo, so when we compile
> a
> library for example we invoke:
> 

[...snip...]

> +  rust_error_at (Location (),
> +    "expected metadata-output path to have base file
> name of: "
> +    "%<%s%> got %<%s%>",
> +    expected_file_name.c_str (), path_base_name);

I can't comment on the patch in depth, but does rust_error_at call into
GCC's regular diagnostics?

If so, "%qs" is a more idiomatic way to express printing a string
argument in quotes (and bold), rather than "%<%s%>", though IIRC they
do the same thing (unless I'm missing something?).

This shows up in a few places in this patch, and might affect other
patches in the kit - though it's a minor nitpick, of course.

Dave



Re: [PATCH Rust front-end v3 20/46] gccrs: Add wrapper for make_unique

2022-10-26 Thread David Malcolm via Gcc-patches
On Wed, 2022-10-26 at 10:17 +0200, arthur.co...@embecosm.com wrote:
> From: Philip Herron 
> 
> This is a wrapper for make_unique we can likely get rid of this as
> there
> are other implementations available or simply keep using the
> unique_ptr
> constructor.

[CCing Jonathan]

As it happens, I just posted something similar here for review:
  [PATCH v3] Add gcc/make-unique.h
https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604442.html
which I hope to use in many places in the analyzer.

Dave

> ---
>  gcc/rust/util/rust-make-unique.h | 35
> 
>  1 file changed, 35 insertions(+)
>  create mode 100644 gcc/rust/util/rust-make-unique.h
> 
> diff --git a/gcc/rust/util/rust-make-unique.h b/gcc/rust/util/rust-
> make-unique.h
> new file mode 100644
> index 000..7b79e625ff1
> --- /dev/null
> +++ b/gcc/rust/util/rust-make-unique.h
> @@ -0,0 +1,35 @@
> +// Copyright (C) 2020-2022 Free Software Foundation, Inc.
> +
> +// This file is part of GCC.
> +
> +// GCC is free software; you can redistribute it and/or modify it
> under
> +// the terms of the GNU General Public License as published by the
> Free
> +// Software Foundation; either version 3, or (at your option) any
> later
> +// version.
> +
> +// GCC is distributed in the hope that it will be useful, but
> WITHOUT ANY
> +// WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> License
> +// for more details.
> +
> +// You should have received a copy of the GNU General Public License
> +// along with GCC; see the file COPYING3.  If not see
> +// .
> +
> +#ifndef RUST_MAKE_UNIQUE_H
> +#define RUST_MAKE_UNIQUE_H
> +
> +#include "rust-system.h"
> +
> +namespace Rust {
> +
> +template 
> +std::unique_ptr
> +make_unique (Ts &&...params)
> +{
> +  return std::unique_ptr (new T (std::forward (params)...));
> +}
> +
> +} // namespace Rust
> +
> +#endif // RUST_MAKE_UNIQUE_H



[PATCH v3] Add gcc/make-unique.h

2022-10-26 Thread David Malcolm via Gcc-patches
Changed in v3: added include of 
v2: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604137.html
v1: https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598189.html

On Tue, 2022-07-12 at 07:48 +0100, Jonathan Wakely wrote:
> On Tue, 12 Jul 2022, 01:25 David Malcolm, 
> wrote:
> 
> > On Fri, 2022-07-08 at 22:16 +0100, Jonathan Wakely wrote:
> > > On Fri, 8 Jul 2022 at 21:47, David Malcolm via Gcc
> > > 
> > > wrote:
> > > > 
> > > > std::unique_ptr is C++11, and I'd like to use it in the
> > > > gcc/analyzer
> > > > subdirectory, at least.  The following patch eliminates a bunch
> > > > of
> > > > "takes ownership" comments and manual "delete" invocations in
> > > > favor
> > > > of simply using std::unique_ptr.
> > > > 
> > > > The problem is that the patch makes use of std::make_unique,
> > > > but
> > > > that
> > > > was added in C++14.
> > > > 
> > > > I've heard that it's reasonably easy to reimplement
> > > > std::make_unique,
> > > > but I'm not sure that my C++11 skills are up to it.
> > > 
> > > You know we have an implementation of std::make_unique in GCC,
> > > with a
> > > GCC-compatible licence that you can look at, right? :-)
> > > 
> > > But it's not really necessary. There are only two reasons to
> > > prefer
> > > make_unique over just allocating an object with new and
> > > constructing
> > > a
> > > unique_ptr from it:
> > > 
> > > 1) avoid a "naked" new in your code (some coding styles like
> > > this,
> > > but
> > > it's not really important as long as the 'delete' is managed
> > > automatically by unique_ptr).
> > > 
> > > 2) exception-safety when allocating multiple objects as args to a
> > > function, see https://herbsutter.com/gotw/_102/ for details.
> > > Irrelevant for GCC, because we build without exceptions.
> > 
> > [moving from gcc to gcc-patches mailing list]
> > 
> > Also, I *think* it's a lot less typing, since I can write just:
> > 
> >   std::make_unique (args)
> > 
> > rather than
> > 
> >   std::unique_ptr (new
> > name_of_type_which_could_be_long (args));
> > 
> > > 
> > > 
> > > 
> > > > Is there:
> > > > (a) an easy way to implement a std::make_unique replacement
> > > > (e.g. in system.h? what to call it?), or
> > > 
> > > If you don't care about using it to create unique_ptr
> > > arrays,
> > > it's trivial:
> > > 
> > >   template
> > > inline typename std::enable_if::value,
> > > std::unique_ptr>::type
> > > make_unique(Args&&... args)
> > > { return std::unique_ptr(new
> > > T(std::forward(args)...));
> > > }
> > > 
> > > To add the overload that works for arrays is a little trickier.
> > 
> > Thanks!
> > 
> > I tried adding it to gcc/system.h, but anything that uses it needs
> > to
> > have std::unique_ptr declared, which meant forcibly including
> > 
> > from gcc/system.h
> > 
> > So instead, here's a patch that adds a new gcc/make-unique.h
> > header,
> > containing just the template decl above (in the root namespace,
> > rather
> > than std::, which saves a bit more typing).
> > 
> 
> Adding things to std isn't allowed anyway, so that's correct.
> 
> 
> > I've successfully bootstrapped a version of my
> > earlier
> > analyzer patch that uses this patch (see patch 2 of the kit, which
> > has
> > lots of usage examples).
> > 
> > OK for trunk?
> > 
> > Dave

[...snip...]

> > +#ifndef INCLUDE_MEMORY
> > +# error "You must define INCLUDE_MEMORY before including system.h
> > to use
> > make-unique.h"
> > +#endif
> > 
> 
> You also need  for the enable_if and is_array traits.
> With
> libstdc++ that gets included by  but that's guaranteed for
> other
> library implementations.
> 
> I don't know if that had the same kind of issues as other system
> headers or
> if it can just be included here.

I've added an include of  in this version of the patch.

> 
> 
> +
> > +/* Minimal implementation of make_unique for C++11 compatibility
> > +   (std::make_unique is C++14).  */
> > +
> > +template
> > +inline typename std::enable_if::value,
> > std::unique_ptr>::type
> > +make_unique(Args&&... args)
> > +{
> > +  return std::unique_ptr (new T (std::forward
> > (args)...));
> > +}
> > +
> > +#endif /* ! GCC_MAKE_UNIQUE */
> > --
> > 2.26.3
> > 
> > 

This patch adds gcc/make-unique.h, containing a minimal C++11
implementation of make_unique (std::make_unique is C++14).

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu
in conjunction with a followup series of patches which use this
in dozens of places in the analyzer.

OK for trunk?

gcc/ChangeLog:
* make-unique.h: New file.
---
 gcc/make-unique.h | 44 
 1 file changed, 44 insertions(+)
 create mode 100644 gcc/make-unique.h

diff --git a/gcc/make-unique.h b/gcc/make-unique.h
new file mode 100644
index 000..c9a7d6ef6ce
--- /dev/null
+++ b/gcc/make-unique.h
@@ -0,0 +1,44 @@
+/* Minimal implementation of make_unique for C++11 compatibility.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 

Re: [PATCH] IRA: Make sure array is big enough

2022-10-26 Thread Vladimir Makarov via Gcc-patches



On 2022-10-25 06:01, Torbjörn SVENSSON wrote:

In commit 081c96621da, the call to resize_reg_info() was moved before
the call to remove_scratches() and the latter one can increase the
number of regs and that would cause an out of bounds usage on the
reg_renumber global array.

Without this patch, the following testcase randomly fails with:
during RTL pass: ira
In file included from 
/src/gcc/testsuite/gcc.dg/compat//struct-by-value-5b_y.c:13:
/src/gcc/testsuite/gcc.dg/compat//struct-by-value-5b_y.c: In function 
'checkgSf13':
/src/gcc/testsuite/gcc.dg/compat//fp-struct-test-by-value-y.h:28:1: internal 
compiler error: Segmentation fault
/src/gcc/testsuite/gcc.dg/compat//struct-by-value-5b_y.c:22:1: note: in 
expansion of macro 'TEST'

gcc/ChangeLog:

* ira.c: Resize array after reg number increased.


The patch is ok to commit it into gcc-11,12 branches and master.

Thank you for fixing this.


Co-Authored-By: Yvan ROUX 
Signed-off-by: Torbjörn SVENSSON 
---
  gcc/ira.cc | 1 +
  1 file changed, 1 insertion(+)

diff --git a/gcc/ira.cc b/gcc/ira.cc
index 42c9cead9f8..d28a67b2546 100644
--- a/gcc/ira.cc
+++ b/gcc/ira.cc
@@ -5718,6 +5718,7 @@ ira (FILE *f)
  regstat_free_ri ();
  regstat_init_n_sets_and_refs ();
  regstat_compute_ri ();
+resize_reg_info ();
};
  
int max_regno_before_rm = max_reg_num ();




Re: [PATCH v3] bpf: add preserve_field_info builtin

2022-10-26 Thread David Faust via Gcc-patches


On 10/26/22 12:33, Jose E. Marchesi wrote:
> 
> Hi David.
> 
> Thanks for the updates.
> OK for master.
> 

Pushed, thanks.


Re: [PATCH] Fortran: BOZ literal constants are not compatible to any type [PR103413]

2022-10-26 Thread Mikael Morin

Hello,

Le 26/10/2022 à 21:15, Harald Anlauf via Fortran a écrit :

Dear all,

a BOZ as source-expression in an ALLOCATE statement could lead
to an ICE when the allocate-object was a CLASS variable.
Since a BOZ has no type, we can handle it as type incompatible
with any type.  This is also what the Cray compiler does for
the code in the testcase.

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

The PR is marked as a 10/11/12/13 regression, so OK for backports?


OK for both, thanks.


Re: [PATCH v3] bpf: add preserve_field_info builtin

2022-10-26 Thread Jose E. Marchesi via Gcc-patches


Hi David.

Thanks for the updates.
OK for master.

>>> I'm not sure whether this behavior is a known limitation or an
>>> oversight. In my opinion it makes more sense to error at compile time,
>>> becuase even after the loader patches the return value it still will
>>> not be correct for these cases.
>>>
>>> So for now I've set these cases to error out, but it would be just as
>>> simple to mimic the LLVM behavior. WDYT?
>> 
>> I would say it makes more sense to error out than to return invalid
>> data.
>> 
>> However, the divergence wrt LLVM is a concern.  What about keeping this
>> behavior in the GCC backend and simultaneously raise the issue in
>> bpf@vger?  If it was a design oversight and the change doesn't impact
>> kernel sources, they may be willing to change it.
>> 
>
> OK, I will raise the question there.
>
>>> [...]
>>> +@deftypefn {Built-in Function} unsigned int
>>> __builtin_preserve_field_info (@var{expr}, unsigned int @var{kind})
>>> +BPF Compile Once-Run Everywhere (CO-RE) support. This builtin is used to
>>> +extract information to aid in struct/union relocations.  @var{expr} is
>>> +an access to a field of a struct or union. Depending on @var{kind}, 
>>> different
>>> +information is returned to the program. A CO-RE relocation for the access 
>>> in
>>> +@var{expr} with kind @var{kind} is recorded if @code{-mco-re} is in effect.
>>> +
>>> +The following values are supported for @var{kind}:
>>> +@table @var
>>> +@item FIELD_BYTE_OFFSET = 0
>>> +The returned value is the offset, in bytes, of the field from the
>>> +beginning of the containing structure.
>> 
>> What about bit fields?  Is this the byte offset of the containing word?
>
> Yes.
>
>> 
>>> +@item FIELD_BYTE_SIZE = 1
>>> +The returned value is the size, in bytes, of the field.
>> 
>> For bit fields,  is this the size of the containing word?
>
> Right again. I have updated the docs for these two in v3.
>
>> 
>>> +@item FIELD_EXISTENCE = 2
>>> +The returned value is 1 if the field exists, 0 otherwise. Always 1 at
>>> +compile time.
>>> +
>>> +@item FIELD_SIGNEDNESS = 3
>>> +The returned value is 1 if the field is signed, 0 otherwise.
>>> +
>>> +@item FIELD_LSHIFT_U64 = 4
>>> +@itemx FIELD_RSHIFT_U64 = 5
>>> +Suppose the field were loaded into a value of FIELD_BYTE_SIZE bytes
>>> +and then zero or sign-extended to a 64-bit value. The returned value
>>> +is the number of bits of left or right shifting respectively that
>>> +would be needed to recover the original value of the field.
>> 
>> What are the semantics for bit fields?
>
> The semantics for bit fields are the same. These two are primarily
> useful for bit fields - a common case in eBPF programs is to read
> some field of a struct through a pointer. If it's a kernel struct
> that may change between versions and you are reading a bit field,
> you would use this builtin to get the eBPF loader to patch the
> appropriate steps to extract the field.
>
> So the process to read a bit field is the following:
>
>   1. read FIELD_BYTE_SIZE bytes and zero-extend the value of the
>  read into a u64
>   2. left shift the result FIELD_LSHIFT_U64 bits
>   3. if FIELD_SIGNEDNESS
>then arithmetic right-shift by FIELD_RSHIFT_U64 bits
>  otherwise
>logical right-shift by FIELD_RSHIFT_U64 bits
>
> Where all these FIELD_* values might change between kernels and
> need patching by the eBPF loader.
>
> I struggled a bit trying to find the best wording to describe this
> in the docs, and settled on adding some example code since I think
> that is the most clear.
>
> Please take a look at the updated version and let me know if you
> have any suggestions, I'm happy to hear them.
>
> Thanks
>
> ---
>
> [Changes from v2: update documentation in extend.texi]
>
> Add BPF __builtin_preserve_field_info. This builtin is used to extract
> information to facilitate struct and union relocations performed by the
> BPF loader, especially for bitfields.
>
> The builtin has the following signature:
>
>   unsigned int __builtin_preserve_field_info (EXPR, unsigned int KIND);
>
> Where EXPR is an expression accessing a field of a struct or union.
> Depending on KIND, different information is returned to the program. The
> supported values for KIND are as follows:
>
>   enum {
> FIELD_BYTE_OFFSET = 0,
> FIELD_BYTE_SIZE,
> FIELD_EXISTENCE,
> FIELD_SIGNEDNESS,
> FIELD_LSHIFT_U64,
> FIELD_RSHIFT_U64
>   };
>
> If -mco-re is in effect (explicitly or implicitly specified), a CO-RE
> relocation is added for the access in EXPR recording the relevant
> information according to KIND.
>
> gcc/
>
>   * config/bpf/bpf.cc: Support __builtin_preserve_field_info.
>   (enum bpf_builtins): Add new builtin.
>   (bpf_init_builtins): Likewise.
>   (bpf_core_field_info): New function.
>   (bpf_expand_builtin): Accomodate new builtin. Refactor adding new
>   relocation to...
>   (maybe_make_core_relo): ... here. New function.
>   

[PATCH v3] bpf: add preserve_field_info builtin

2022-10-26 Thread David Faust via Gcc-patches
>> I'm not sure whether this behavior is a known limitation or an
>> oversight. In my opinion it makes more sense to error at compile time,
>> becuase even after the loader patches the return value it still will
>> not be correct for these cases.
>>
>> So for now I've set these cases to error out, but it would be just as
>> simple to mimic the LLVM behavior. WDYT?
> 
> I would say it makes more sense to error out than to return invalid
> data.
> 
> However, the divergence wrt LLVM is a concern.  What about keeping this
> behavior in the GCC backend and simultaneously raise the issue in
> bpf@vger?  If it was a design oversight and the change doesn't impact
> kernel sources, they may be willing to change it.
> 

OK, I will raise the question there.

>> [...]
>> +@deftypefn {Built-in Function} unsigned int __builtin_preserve_field_info 
>> (@var{expr}, unsigned int @var{kind})
>> +BPF Compile Once-Run Everywhere (CO-RE) support. This builtin is used to
>> +extract information to aid in struct/union relocations.  @var{expr} is
>> +an access to a field of a struct or union. Depending on @var{kind}, 
>> different
>> +information is returned to the program. A CO-RE relocation for the access in
>> +@var{expr} with kind @var{kind} is recorded if @code{-mco-re} is in effect.
>> +
>> +The following values are supported for @var{kind}:
>> +@table @var
>> +@item FIELD_BYTE_OFFSET = 0
>> +The returned value is the offset, in bytes, of the field from the
>> +beginning of the containing structure.
> 
> What about bit fields?  Is this the byte offset of the containing word?

Yes.

> 
>> +@item FIELD_BYTE_SIZE = 1
>> +The returned value is the size, in bytes, of the field.
> 
> For bit fields,  is this the size of the containing word?

Right again. I have updated the docs for these two in v3.

> 
>> +@item FIELD_EXISTENCE = 2
>> +The returned value is 1 if the field exists, 0 otherwise. Always 1 at
>> +compile time.
>> +
>> +@item FIELD_SIGNEDNESS = 3
>> +The returned value is 1 if the field is signed, 0 otherwise.
>> +
>> +@item FIELD_LSHIFT_U64 = 4
>> +@itemx FIELD_RSHIFT_U64 = 5
>> +Suppose the field were loaded into a value of FIELD_BYTE_SIZE bytes
>> +and then zero or sign-extended to a 64-bit value. The returned value
>> +is the number of bits of left or right shifting respectively that
>> +would be needed to recover the original value of the field.
> 
> What are the semantics for bit fields?

The semantics for bit fields are the same. These two are primarily
useful for bit fields - a common case in eBPF programs is to read
some field of a struct through a pointer. If it's a kernel struct
that may change between versions and you are reading a bit field,
you would use this builtin to get the eBPF loader to patch the
appropriate steps to extract the field.

So the process to read a bit field is the following:

  1. read FIELD_BYTE_SIZE bytes and zero-extend the value of the
 read into a u64
  2. left shift the result FIELD_LSHIFT_U64 bits
  3. if FIELD_SIGNEDNESS
   then arithmetic right-shift by FIELD_RSHIFT_U64 bits
 otherwise
   logical right-shift by FIELD_RSHIFT_U64 bits

Where all these FIELD_* values might change between kernels and
need patching by the eBPF loader.

I struggled a bit trying to find the best wording to describe this
in the docs, and settled on adding some example code since I think
that is the most clear.

Please take a look at the updated version and let me know if you
have any suggestions, I'm happy to hear them.

Thanks

---

[Changes from v2: update documentation in extend.texi]

Add BPF __builtin_preserve_field_info. This builtin is used to extract
information to facilitate struct and union relocations performed by the
BPF loader, especially for bitfields.

The builtin has the following signature:

  unsigned int __builtin_preserve_field_info (EXPR, unsigned int KIND);

Where EXPR is an expression accessing a field of a struct or union.
Depending on KIND, different information is returned to the program. The
supported values for KIND are as follows:

  enum {
FIELD_BYTE_OFFSET = 0,
FIELD_BYTE_SIZE,
FIELD_EXISTENCE,
FIELD_SIGNEDNESS,
FIELD_LSHIFT_U64,
FIELD_RSHIFT_U64
  };

If -mco-re is in effect (explicitly or implicitly specified), a CO-RE
relocation is added for the access in EXPR recording the relevant
information according to KIND.

gcc/

* config/bpf/bpf.cc: Support __builtin_preserve_field_info.
(enum bpf_builtins): Add new builtin.
(bpf_init_builtins): Likewise.
(bpf_core_field_info): New function.
(bpf_expand_builtin): Accomodate new builtin. Refactor adding new
relocation to...
(maybe_make_core_relo): ... here. New function.
(bpf_resolve_overloaded_builtin): Accomodate new builtin.
(bpf_core_newdecl): Likewise.
(bpf_core_walk): Likewise.
(bpf_core_is_maybe_aggregate_access): Improve logic.
(struct core_walk_data): New.
* 

[PATCH] Fortran: BOZ literal constants are not compatible to any type [PR103413]

2022-10-26 Thread Harald Anlauf via Gcc-patches
Dear all,

a BOZ as source-expression in an ALLOCATE statement could lead
to an ICE when the allocate-object was a CLASS variable.
Since a BOZ has no type, we can handle it as type incompatible
with any type.  This is also what the Cray compiler does for
the code in the testcase.

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

The PR is marked as a 10/11/12/13 regression, so OK for backports?

Thanks,
Harald

From 986bf9cc5abc51598609b16edc9242a87244571b Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Wed, 26 Oct 2022 21:00:44 +0200
Subject: [PATCH] Fortran: BOZ literal constants are not compatible to any type
 [PR103413]

gcc/fortran/ChangeLog:

	PR fortran/103413
	* symbol.cc (gfc_type_compatible): A boz-literal-constant has no type
	and thus is not considered compatible to any type.

gcc/testsuite/ChangeLog:

	PR fortran/103413
	* gfortran.dg/illegal_boz_arg_4.f90: New test.
---
 gcc/fortran/symbol.cc   |  4 
 gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90 | 13 +
 2 files changed, 17 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90

diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 6050359d521..49fb37864bd 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -5139,6 +5139,10 @@ gfc_type_compatible (gfc_typespec *ts1, gfc_typespec *ts2)
   bool is_union1 = (ts1->type == BT_UNION);
   bool is_union2 = (ts2->type == BT_UNION);

+  /* A boz-literal-constant has no type.  */
+  if (ts1->type == BT_BOZ || ts2->type == BT_BOZ)
+return false;
+
   if (is_class1
   && ts1->u.derived->components
   && ((ts1->u.derived->attr.is_class
diff --git a/gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90 b/gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90
new file mode 100644
index 000..856cfa9211f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/illegal_boz_arg_4.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! { dg-options "-std=f2018" }
+! PR fortran/103413
+! Contributed by G.Steinmetz
+
+program p
+  type t
+ class(*), allocatable :: a
+  end type
+  type(t) :: x
+  allocate (x%a, source=z'1') ! { dg-error "type incompatible" }
+  allocate (x%a, mold=z'1')   ! { dg-error "type incompatible" }
+end
--
2.35.3



[PATCH] x86: Replace ne:CCC/ne:CCO with UNSPEC_CC_NE in neg patterns

2022-10-26 Thread H.J. Lu via Gcc-patches
In i386.md, neg patterns which set MODE_CC register like

(set (reg:CCC FLAGS_REG)
 (ne:CCC (match_operand:SWI48 1 "general_reg_operand") (const_int 0)))

can lead to errors when operand 1 is a constant value.  If FLAGS_REG in

(set (reg:CCC FLAGS_REG)
 (ne:CCC (const_int 2) (const_int 0)))

is set to 1, RTX simplifiers may simplify

(set (reg:SI 93)
 (neg:SI (ltu:SI (reg:CCC 17 flags) (const_int 0 [0]

as

(set (reg:SI 93)
 (neg:SI (ltu:SI (const_int 1) (const_int 0 [0]

which leads to incorrect results since LTU on MODE_CC register isn't the
same as "unsigned less than" in x86 backend.  To prevent RTL optimizers
from setting MODE_CC register to a constant, use UNSPEC_CC_NE to replace
ne:CCC/ne:CCO when setting FLAGS_REG in neg patterns.

gcc/

PR target/107172
* config/i386/i386.md (UNSPEC_CC_NE): New.
Replace ne:CCC/ne:CCO with UNSPEC_CC_NE in neg patterns.

gcc/testsuite/

PR target/107172
* gcc.target/i386/pr107172.c: New test.
---
 gcc/config/i386/i386.md  | 45 +---
 gcc/testsuite/gcc.target/i386/pr107172.c | 26 ++
 2 files changed, 51 insertions(+), 20 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr107172.c

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index baf1f1f8fa2..aaa678e7314 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -113,6 +113,7 @@ (define_c_enum "unspec" [
   UNSPEC_PEEPSIB
   UNSPEC_INSN_FALSE_DEP
   UNSPEC_SBB
+  UNSPEC_CC_NE
 
   ;; For SSE/MMX support:
   UNSPEC_FIX_NOTRUNC
@@ -11470,7 +11471,7 @@ (define_insn_and_split "*neg2_doubleword"
   "&& reload_completed"
   [(parallel
 [(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
+ (unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
  (set (match_dup 0) (neg:DWIH (match_dup 1)))])
(parallel
 [(set (match_dup 2)
@@ -11499,7 +11500,8 @@ (define_peephole2
(match_operand:SWI48 1 "nonimmediate_gr_operand"))
(parallel
 [(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_operand:SWI48 2 "general_reg_operand") (const_int 0)))
+ (unspec:CCC [(match_operand:SWI48 2 "general_reg_operand")
+  (const_int 0)] UNSPEC_CC_NE))
  (set (match_dup 2) (neg:SWI48 (match_dup 2)))])
(parallel
 [(set (match_dup 0)
@@ -11517,7 +11519,7 @@ (define_peephole2
&& !reg_mentioned_p (operands[2], operands[1])"
   [(parallel
 [(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 2) (const_int 0)))
+ (unspec:CCC [(match_dup 2) (const_int 0)] UNSPEC_CC_NE))
  (set (match_dup 2) (neg:SWI48 (match_dup 2)))])
(parallel
 [(set (match_dup 0)
@@ -11543,7 +11545,8 @@ (define_peephole2
  (clobber (reg:CC FLAGS_REG))])
(parallel
 [(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_operand:SWI48 1 "general_reg_operand") (const_int 0)))
+ (unspec:CCC [(match_operand:SWI48 1 "general_reg_operand")
+  (const_int 0)] UNSPEC_CC_NE))
  (set (match_dup 1) (neg:SWI48 (match_dup 1)))])
(parallel
 [(set (match_dup 0)
@@ -11559,7 +11562,7 @@ (define_peephole2
   "REGNO (operands[0]) != REGNO (operands[1])"
   [(parallel
 [(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_dup 1) (const_int 0)))
+ (unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
  (set (match_dup 1) (neg:SWI48 (match_dup 1)))])
(parallel
 [(set (match_dup 0)
@@ -11635,9 +11638,9 @@ (define_insn "*negsi_2_zext"
 
 (define_insn "*neg_ccc_1"
   [(set (reg:CCC FLAGS_REG)
-   (ne:CCC
- (match_operand:SWI 1 "nonimmediate_operand" "0")
- (const_int 0)))
+   (unspec:CCC
+ [(match_operand:SWI 1 "nonimmediate_operand" "0")
+  (const_int 0)] UNSPEC_CC_NE))
(set (match_operand:SWI 0 "nonimmediate_operand" "=m")
(neg:SWI (match_dup 1)))]
   ""
@@ -11647,9 +11650,9 @@ (define_insn "*neg_ccc_1"
 
 (define_insn "*neg_ccc_2"
   [(set (reg:CCC FLAGS_REG)
-   (ne:CCC
- (match_operand:SWI 1 "nonimmediate_operand" "0")
- (const_int 0)))
+   (unspec:CCC
+ [(match_operand:SWI 1 "nonimmediate_operand" "0")
+  (const_int 0)] UNSPEC_CC_NE))
(clobber (match_scratch:SWI 0 "="))]
   ""
   "neg{}\t%0"
@@ -11659,8 +11662,8 @@ (define_insn "*neg_ccc_2"
 (define_expand "x86_neg_ccc"
   [(parallel
 [(set (reg:CCC FLAGS_REG)
- (ne:CCC (match_operand:SWI48 1 "register_operand")
- (const_int 0)))
+ (unspec:CCC [(match_operand:SWI48 1 "register_operand")
+  (const_int 0)] UNSPEC_CC_NE))
  (set (match_operand:SWI48 0 "register_operand")
  (neg:SWI48 (match_dup 1)))])])
 
@@ -11686,8 +11689,9 @@ (define_insn "*negqi_ext_2"
 ;; Negate with jump on overflow.
 (define_expand "negv3"
   [(parallel [(set (reg:CCO FLAGS_REG)
-  (ne:CCO (match_operand:SWI 1 "register_operand")
-  

Re: [PATCH v4] c++: Implement -Wdangling-reference [PR106393]

2022-10-26 Thread Jason Merrill via Gcc-patches

On 10/26/22 14:26, Marek Polacek wrote:

On Wed, Oct 26, 2022 at 12:42:27PM -0400, Jason Merrill wrote:

On 10/26/22 12:10, Marek Polacek wrote:

As before, I've tested this patch twice, once with -Wdangling-reference
enabled by default, once with -Wdangling-reference enabled by -Wextra.
The couple of FAILs I saw were true positives (e.g., rv-conv1.C, rv-func2.C).


I might actually add it to -Wall, the false positive rate sounds pretty low
at this point.


Done (and invoke.texi adjusted).
  

+static tree
+do_warn_dangling_reference (tree expr)
+{
+  STRIP_NOPS (expr);
+  switch (TREE_CODE (expr))
+{
+case CALL_EXPR:
+  {
+   tree fndecl = cp_get_callee_fndecl_nofold (expr);
+   if (!fndecl
+   || warning_suppressed_p (fndecl, OPT_Wdangling_reference)
+   || !warning_enabled_at (DECL_SOURCE_LOCATION (fndecl),
+   OPT_Wdangling_reference)
+   /* If the function doesn't return a reference, don't warn.  This
+  can be e.g.
+const int& z = std::min({1, 2, 3, 4, 5, 6, 7});
+  which doesn't dangle: std::min here returns an int.  */
+   || !TYPE_REF_P (TREE_TYPE (TREE_TYPE (fndecl


Maybe TYPE_REF_OBJ_P?  Either way is fine.


Adjusted.
  

--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11246,6 +11246,16 @@ check_return_expr (tree retval, bool *no_warning)
 if (processing_template_decl)
   return saved_retval;
+  /* A naive attempt to reduce the number of -Wdangling-reference false
+ positives: if we know that this function can return a variable with
+ static storage duration rather than one of its parameters, suppress
+ the warning.  */
+  if (warn_dangling_reference
+  && TYPE_REF_P (functype)
+  && bare_retval


You probably need to check VAR_P (bare_retval) here, static_flag is used for
various other things in other tree codes.


Added VAR_P.
  

+  && TREE_STATIC (bare_retval))
+suppress_warning (current_function_decl, OPT_Wdangling_reference);
+
 /* Actually copy the value returned into the appropriate location.  */
 if (retval && retval != result)
   retval = cp_build_init_expr (result, retval);
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 64f77e8367a..0a3a174cdc8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -249,7 +249,8 @@ in the following sections.
   -Wno-class-conversion  -Wclass-memaccess @gol
   -Wcomma-subscript  -Wconditionally-supported @gol
   -Wno-conversion-null  -Wctad-maybe-unsupported @gol
--Wctor-dtor-privacy  -Wno-delete-incomplete @gol
+-Wctor-dtor-privacy  -Wdangling-reference @gol
+-Wno-delete-incomplete @gol
   -Wdelete-non-virtual-dtor  -Wno-deprecated-array-compare @gol
   -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
   -Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion 
@gol
@@ -3627,6 +3628,42 @@ public static member functions.  Also warn if there are 
no non-private
   methods, and there's at least one private member function that isn't
   a constructor or destructor.
+@item -Wdangling-reference @r{(C++ and Objective-C++ only)}
+@opindex Wdangling-reference
+@opindex Wno-dangling-reference
+Warn when a reference is bound to a temporary whose lifetime has ended.
+For example:
+
+@smallexample
+int n = 1;
+const int& r = std::max(n - 1, n + 1); // r is dangling
+@end smallexample
+
+In the example above, two temporaries are created, one for each
+argument, and a reference to one of the temporaries is returned.
+However, both temporaries are destroyed at the end of the full
+expression, so the reference @code{r} is dangling.  This warning
+also detects dangling references in member initializer lists:
+
+@smallexample
+const int& f(const int& i) @{ return i; @}
+struct S @{
+  const int  // r is dangling
+  S() : r(f(10)) @{ @}
+@};
+@end smallexample
+
+Member functions are checked as well, but only their object argument:
+
+@smallexample
+struct S @{
+   const S& self () @{ return *this; @}
+@};
+const S& s = S().self(); // s is dangling
+@end smallexample
+
+This warning is enabled by @option{-Wextra}.


It would be good to mention using #pragma to disable the warning around safe
functions.


Yes, text added.

Now that the warning is in -Wall, I've added -Wno-dangling-reference to
g++.dg/warn/Wdangling-pointer-2.C.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?


OK, thanks.


-- >8 --
This patch implements a new experimental warning (enabled by -Wall) to
detect references bound to temporaries whose lifetime has ended.  The
primary motivation is the Note in
:

   Capturing the result of std::max by reference produces a dangling reference
   if one of the parameters is a temporary and that parameter is returned:

   int n = 1;
   const int& r = std::max(n-1, n+1); // r is dangling

That's because both temporaries for n-1 and n+1 are destroyed at the end
of the full expression.  With 

[PATCH v4] c++: Implement -Wdangling-reference [PR106393]

2022-10-26 Thread Marek Polacek via Gcc-patches
On Wed, Oct 26, 2022 at 12:42:27PM -0400, Jason Merrill wrote:
> On 10/26/22 12:10, Marek Polacek wrote:
> > As before, I've tested this patch twice, once with -Wdangling-reference
> > enabled by default, once with -Wdangling-reference enabled by -Wextra.
> > The couple of FAILs I saw were true positives (e.g., rv-conv1.C, 
> > rv-func2.C).
> 
> I might actually add it to -Wall, the false positive rate sounds pretty low
> at this point.

Done (and invoke.texi adjusted).
 
> > +static tree
> > +do_warn_dangling_reference (tree expr)
> > +{
> > +  STRIP_NOPS (expr);
> > +  switch (TREE_CODE (expr))
> > +{
> > +case CALL_EXPR:
> > +  {
> > +   tree fndecl = cp_get_callee_fndecl_nofold (expr);
> > +   if (!fndecl
> > +   || warning_suppressed_p (fndecl, OPT_Wdangling_reference)
> > +   || !warning_enabled_at (DECL_SOURCE_LOCATION (fndecl),
> > +   OPT_Wdangling_reference)
> > +   /* If the function doesn't return a reference, don't warn.  This
> > +  can be e.g.
> > +const int& z = std::min({1, 2, 3, 4, 5, 6, 7});
> > +  which doesn't dangle: std::min here returns an int.  */
> > +   || !TYPE_REF_P (TREE_TYPE (TREE_TYPE (fndecl
> 
> Maybe TYPE_REF_OBJ_P?  Either way is fine.

Adjusted.
 
> > --- a/gcc/cp/typeck.cc
> > +++ b/gcc/cp/typeck.cc
> > @@ -11246,6 +11246,16 @@ check_return_expr (tree retval, bool *no_warning)
> > if (processing_template_decl)
> >   return saved_retval;
> > +  /* A naive attempt to reduce the number of -Wdangling-reference false
> > + positives: if we know that this function can return a variable with
> > + static storage duration rather than one of its parameters, suppress
> > + the warning.  */
> > +  if (warn_dangling_reference
> > +  && TYPE_REF_P (functype)
> > +  && bare_retval
> 
> You probably need to check VAR_P (bare_retval) here, static_flag is used for
> various other things in other tree codes.

Added VAR_P.
 
> > +  && TREE_STATIC (bare_retval))
> > +suppress_warning (current_function_decl, OPT_Wdangling_reference);
> > +
> > /* Actually copy the value returned into the appropriate location.  */
> > if (retval && retval != result)
> >   retval = cp_build_init_expr (result, retval);
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index 64f77e8367a..0a3a174cdc8 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -249,7 +249,8 @@ in the following sections.
> >   -Wno-class-conversion  -Wclass-memaccess @gol
> >   -Wcomma-subscript  -Wconditionally-supported @gol
> >   -Wno-conversion-null  -Wctad-maybe-unsupported @gol
> > --Wctor-dtor-privacy  -Wno-delete-incomplete @gol
> > +-Wctor-dtor-privacy  -Wdangling-reference @gol
> > +-Wno-delete-incomplete @gol
> >   -Wdelete-non-virtual-dtor  -Wno-deprecated-array-compare @gol
> >   -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
> >   -Wno-deprecated-enum-enum-conversion 
> > -Wno-deprecated-enum-float-conversion @gol
> > @@ -3627,6 +3628,42 @@ public static member functions.  Also warn if there 
> > are no non-private
> >   methods, and there's at least one private member function that isn't
> >   a constructor or destructor.
> > +@item -Wdangling-reference @r{(C++ and Objective-C++ only)}
> > +@opindex Wdangling-reference
> > +@opindex Wno-dangling-reference
> > +Warn when a reference is bound to a temporary whose lifetime has ended.
> > +For example:
> > +
> > +@smallexample
> > +int n = 1;
> > +const int& r = std::max(n - 1, n + 1); // r is dangling
> > +@end smallexample
> > +
> > +In the example above, two temporaries are created, one for each
> > +argument, and a reference to one of the temporaries is returned.
> > +However, both temporaries are destroyed at the end of the full
> > +expression, so the reference @code{r} is dangling.  This warning
> > +also detects dangling references in member initializer lists:
> > +
> > +@smallexample
> > +const int& f(const int& i) @{ return i; @}
> > +struct S @{
> > +  const int  // r is dangling
> > +  S() : r(f(10)) @{ @}
> > +@};
> > +@end smallexample
> > +
> > +Member functions are checked as well, but only their object argument:
> > +
> > +@smallexample
> > +struct S @{
> > +   const S& self () @{ return *this; @}
> > +@};
> > +const S& s = S().self(); // s is dangling
> > +@end smallexample
> > +
> > +This warning is enabled by @option{-Wextra}.
> 
> It would be good to mention using #pragma to disable the warning around safe
> functions.

Yes, text added.

Now that the warning is in -Wall, I've added -Wno-dangling-reference to
g++.dg/warn/Wdangling-pointer-2.C.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
This patch implements a new experimental warning (enabled by -Wall) to
detect references bound to temporaries whose lifetime has ended.  The
primary motivation is the Note in
:

  Capturing the result of std::max by reference 

RE: [PATCH] [X86_64]: Enable support for next generation AMD Zen4 CPU

2022-10-26 Thread Alexander Monakov
On Wed, 26 Oct 2022, Kumar, Venkataramanan wrote:

> > Looking at znver1.md again, I think the problem is caused by incorrect
> > modeling of division instructions: they have descriptions like
> >
> > (define_insn_reservation "znver1_idiv_DI" 41
> > (and (eq_attr "cpu" "znver1,znver2")
> >  (and (eq_attr "type" "idiv")
> >   (and (eq_attr "mode" "DI")
> >(eq_attr "memory" "none"
> > "znver1-double,znver1-ieu2*41")
> >
> > which says that DImode idiv has latency 41 (which is correct) and that it
> > occupies 2nd integer execution unit for 41 consecutive cycles, but that is
> > not correct:
> 
> Yes you are correct. It does not block the 2nd integer execution pipe 
> consecutively for 41 cycles.
> 
> >
> > 1) the division instruction is partially pipelined, and has throughput 1/14
> 
> "Div" unit takes one instruction and in the worst case the latency will be 41 
> cycles in znver1/2.
> But I agree that we can put best case latency of 14 cycles for the scheduler 
> model in znver1/2 .

It is not latency. It is reciprocal throughput. For example, the multiplication
instruction has latency 3 and reciprocal throughput 1, and the corresponding
execution unit can accept a new multiplication instruction each cycle. In the
.md file we are modeling that by saying that multiplication occupies some unit
for one cycle (but has latency 3).

Alexander


Re: [PING] options: Clarify 'Init' option property usage for streaming optimization (was: [PATCH] options, lto: Optimize streaming of optimization nodes)

2022-10-26 Thread Joseph Myers
On Wed, 26 Oct 2022, Thomas Schwinge wrote:

> Hi!
> 
> Ping.  For convenience, I've re-attached
> "options: Clarify 'Init' option property usage for streaming optimization".
> (I've re-verified: "No functional change; no change in generated files.")

OK.

-- 
Joseph S. Myers
jos...@codesourcery.com


RE: [PATCH] [X86_64]: Enable support for next generation AMD Zen4 CPU

2022-10-26 Thread Kumar, Venkataramanan via Gcc-patches
[AMD Official Use Only - General]

Hi Alexander,

Thank you for looking in to this issue.

> -Original Message-
> From: Alexander Monakov 
> Sent: Tuesday, October 25, 2022 12:18 AM
> To: Jan Hubička 
> Cc: Kumar, Venkataramanan ; Jakub
> Jelinek ; Richard Biener
> ; Joshi, Tejas Sanjay
> ; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] [X86_64]: Enable support for next generation AMD
> Zen4 CPU
>
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
>
>
> On Mon, 24 Oct 2022, Jan Hubička wrote:
>
> > > By the way, it appears pre-existing znver[123] models are also
> > > causing some kind of combinatorial blow-up, but before znver4 it was
> > > not a blocking issue:
> > >
> > >
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgc
> > >
> c.gnu.org%2Fbugzilla%2Fshow_bug.cgi%3Fid%3D87832data=05%7C
> 01%7C
> > >
> Venkataramanan.Kumar%40amd.com%7C5d22bec311ac43b3f56a08dab5f
> 03fc7%7C
> > >
> 3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C638022340726474
> 812%7CUnkn
> > >
> own%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik
> 1haW
> > >
> wiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=kg2zKCBxDEeYYKijH
> 204QpOC4
> > > 0SJBADOvqlk0LhzJhc%3Dreserved=0
> >
> >
> > It is really easy to make DFA size to grow if there are possibly many
> > instructions in the pipeline (as every possible state of a modelled
> > pipeline needs to be a new state of the automaton). This is
> > essentially depth_of_pipeline * number_of_units with additional states
> > to repesent special instructions and this naturally keeps growing.
> >
> > We could try to break the FP automata into multiple ones, but there
> > are instructions that can go down any pipe which makes this hard or we
> > can try toreduce number of different reservation types (possibly by
> > breaking the automaton to znver1-3 and 4 or so).
> > With znver2 model I experimented with broken up version and common
> one
> > and ended up with smaller binary for combined one.
>
> Looking at znver1.md again, I think the problem is caused by incorrect
> modeling of division instructions: they have descriptions like
>
> (define_insn_reservation "znver1_idiv_DI" 41
> (and (eq_attr "cpu" "znver1,znver2")
>  (and (eq_attr "type" "idiv")
>   (and (eq_attr "mode" "DI")
>(eq_attr "memory" "none"
> "znver1-double,znver1-ieu2*41")
>
> which says that DImode idiv has latency 41 (which is correct) and that it
> occupies 2nd integer execution unit for 41 consecutive cycles, but that is
> not correct:

Yes you are correct. It does not block the 2nd integer execution pipe 
consecutively for 41 cycles.

>
> 1) the division instruction is partially pipelined, and has throughput 1/14

"Div" unit takes one instruction and in the worst case the latency will be 41 
cycles in znver1/2.
But I agree that we can put best case latency of 14 cycles for the scheduler 
model in znver1/2 .

>
> 2) for the most part it occupies a separate division unit, not the general
> arithmetic unit.

Agreed.

>
> (incidentally, I think the blowup is caused by interaction of such super-long
> 41-cycle paths with the rest of reservations)
>
> I think we should fix this by modeling the separate division unit properly,
> and fixing reservations to use the measured reciprocal throughput of those
> instructions (available from uops.info). The following patch does that for
> integer divisions and completely eliminates the integer part of the problem;
> the issue with floating-point divisions remains.
>
> Top 5 znver table sizes, before:
>
> 68692 r znver1_ieu_check
> 68692 r znver1_ieu_transitions
> 99792 r znver1_ieu_min_issue_delay
> 428108 r znver1_fp_min_issue_delay
> 856216 r znver1_fp_transitions
>
> After:
>
> 1454 r znver1_ieu_translate
> 1454 r znver1_translate
> 2304 r znver1_ieu_transitions
> 428108 r znver1_fp_min_issue_delay
> 856216 r znver1_fp_transitions
>
> Will you help getting this reviewed for trunk?
>
>
>
> diff --git a/gcc/config/i386/znver1.md b/gcc/config/i386/znver1.md index
> 9c25b4e27..39b59343d 100644
> --- a/gcc/config/i386/znver1.md
> +++ b/gcc/config/i386/znver1.md
> @@ -24,7 +24,7 @@
>  ;; AMD znver1, znver2 and znver3 Scheduling  ;; Modeling automatons for
> zen decoders, integer execution pipes,  ;; AGU pipes and floating point
> execution units.
> -(define_automaton "znver1, znver1_ieu, znver1_fp, znver1_agu")
> +(define_automaton "znver1, znver1_ieu, znver1_fp, znver1_agu,
> +znver1_idiv")
>
>  ;; Decoders unit has 4 decoders and all of them can decode fast path  ;; and
> vector type instructions.
> @@ -50,6 +50,7 @@
>  (define_cpu_unit "znver1-ieu1" "znver1_ieu")  (define_cpu_unit "znver1-
> ieu2" "znver1_ieu")  (define_cpu_unit "znver1-ieu3" "znver1_ieu")
> +(define_cpu_unit "znver1-idiv" "znver1_idiv")
>  (define_reservation 

Re: [PATCH] xtensa: Fix out-of-bounds array access

2022-10-26 Thread Max Filippov via Gcc-patches
On Tue, Oct 25, 2022 at 11:27 PM Takayuki 'January June' Suwa
 wrote:
>
> On 2022/10/26 5:09, Jan-Benedict Glaw wrote:
> > I didn't yet actually check the warning, it may be bogus.
>
> This "problem" can occur in the following two places calling 
> xtensa_split_DI_reg_imm():
>
> - (define_expand "movdi") @ line 943-945
> - (define_split) @ line 989
>
> and the former causes the "real" problem:
>
> [from gcc/insn-emit.cc (generated by building)]
>
> > /* ../../gcc/config/xtensa/xtensa.md:932 */
> > rtx
> > gen_movdi (rtx operand0,
> >   rtx operand1)
> > {
> >   rtx_insn *_val = 0;
> >   start_sequence ();
> >   {
> > rtx operands[2];  // only 2 elements
> > operands[0] = operand0;
> > operands[1] = operand1;
> > #define FAIL return (end_sequence (), _val)
> > #define DONE return (_val = get_insns (), end_sequence (), _val)
> > #line 936 "../../gcc/config/xtensa/xtensa.md"
> > {
> >   if (CONSTANT_P (operands[1]))
> > {
> >   /* Split in halves if 64-bit Const-to-Reg moves
> >because of offering further optimization opportunities.  */
> >   if (register_operand (operands[0], DImode))
> >   {
> > xtensa_split_DI_reg_imm (operands);   // out-of-bounds!
> > emit_move_insn (operands[0], operands[1]);
> > emit_move_insn (operands[2], operands[3]);// out-of-bounds!
> > DONE;
> >   }
>
> The latter is not a problem as the array is large enough (up to 
> MAX_RECOG_OPERANDS-1).
>
> ===
>
> gcc/ChangeLog:
>
> * config/xtensa/xtensa.md (movdi):
> Copy operands[0...1] to ops[0...3] and then use the latter before
> calling xtensa_split_DI_reg_imm() and emitting insns.
> ---
>  gcc/config/xtensa/xtensa.md | 7 ---
>  1 file changed, 4 insertions(+), 3 deletions(-)

Committed to master as obvious after cleaning up
the commit message.

-- 
Thanks.
-- Max


Re: [PATCH] c++: Fix excess precision related ICE on invalid binop [PR107382, PR107383]

2022-10-26 Thread Jason Merrill via Gcc-patches

On 10/26/22 04:23, Jakub Jelinek wrote:

Hi!

The following tests ICE in the gcc_assert (common); in cp_build_binary_op.
I've missed that while for * common is set always, while for +, - and /
it is in some cases not.
If it is not, then
   if (!result_type
   && arithmetic_types_p
   && (shorten || common || short_compare))
condition is false, then the following
   if (may_need_excess_precision
   && (orig_type0 != type0 || orig_type1 != type1)
   && build_type == NULL_TREE)
would fail the assertion there and if there wouldn't be excess precision,
   if (code == SPACESHIP_EXPR)
would be false (for SPACESHIP_EXPR we always have build_type set like for
other comparisons) and then trigger
   if (!result_type)
 {
   if (complain & tf_error)
 {
   binary_op_rich_location richloc (location,
orig_op0, orig_op1, true);
   error_at (,
 "invalid operands of types %qT and %qT to binary %qO",
 TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
 }
   return error_mark_node;
 }
So, if result_type is NULL, we don't really need to compute
semantic_result_type because nothing will use it anyway and can get
fall through into the error/return error_mark_node; case.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


OK.


2022-10-26  Jakub Jelinek  

PR c++/107382
PR c++/107383
* typeck.cc (cp_build_binary_op): Don't compute semantic_result_type
if result_type is NULL.

* g++.dg/diagnostic/bad-binary-ops2.C: New test.

--- gcc/cp/typeck.cc.jj 2022-10-25 10:37:28.008533040 +0200
+++ gcc/cp/typeck.cc2022-10-25 19:18:20.951846806 +0200
@@ -6179,7 +6179,8 @@ cp_build_binary_op (const op_location_t
  }
if (may_need_excess_precision
&& (orig_type0 != type0 || orig_type1 != type1)
-  && build_type == NULL_TREE)
+  && build_type == NULL_TREE
+  && result_type)
  {
gcc_assert (common);
semantic_result_type = cp_common_type (orig_type0, orig_type1);
--- gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C.jj2022-10-25 
19:49:49.190198057 +0200
+++ gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C   2022-10-25 
20:10:35.266264891 +0200
@@ -0,0 +1,26 @@
+// PR c++/107382
+// PR c++/107383
+// { dg-do compile }
+// { dg-options "-O2 -fexcess-precision=standard" }
+
+void
+foo ()
+{
+  float t[2] = { 1, 2 };
+  int const *s = 0;
+  t[1] / s;// { dg-error "invalid operands of types 'float' and 'const int\\\*' 
to binary 'operator/'" }
+}
+
+void
+bar ()
+{
+  float t[2] = { 1, 2 };
+  int const *s[2] = { 0, 0 };
+  t[1] / s[0]; // { dg-error "invalid operands of types 'float' and 'const int\\\*' 
to binary 'operator/'" }
+}
+
+void
+baz (float a, int* b)
+{
+  a -= b;  // { dg-error "invalid operands of types 'float' and 'int\\\*' to 
binary 'operator-'" }
+}

Jakub





Re: [PATCH v3] c++: Implement -Wdangling-reference [PR106393]

2022-10-26 Thread Jason Merrill via Gcc-patches

On 10/26/22 12:10, Marek Polacek wrote:

On Tue, Oct 25, 2022 at 11:53:51AM -0400, Jason Merrill via Gcc-patches wrote:

On 10/25/22 11:21, Marek Polacek wrote:

On Mon, Oct 24, 2022 at 01:30:42PM -0400, Jason Merrill wrote:

On 10/21/22 19:28, Marek Polacek wrote:

It doesn't warn when the function in question is a member function, otherwise
it'd emit loads of warnings for valid code like obj.emplace({0}, 0).


We had discussed warning if the object argument is a temporary (and for the
above check, the function returns *this)?


Presumably you mean detecting something like this:

struct S {
const S& self () { return *this; }
};
const S& s = S().self();


Yes.  Or

struct S {
   int ar[4];
   int& operator[](int i) { return ar[i]; }
};
const int  = S()[2];


Ok, I've extended the warning to check if the object argument is a temporary
as well, so we get a warning here now.
  

I don't currently have a way to detect it, can I steal a METHOD_TYPE flag
that says "this member function returns *this"?  Alternatively, walk its
DECL_SAVED_TREE and look for RETURN_EXPR?


Like you limited the above check to TREE_STATIC, let's also forget about
checking for return *this.


I don't follow, but it looks like I don't need to change anything and just
keep the TREE_STATIC check?
  

It warns in member initializer lists as well:

 const int& f(const int& i) { return i; }
 struct S {
   const int  // { dg-warning "dangling reference" }
   S() : r(f(10)) { } // { dg-message "destroyed" }
 };

I've run the testsuite/bootstrap with the warning enabled by default.
There were just a few FAILs:
* g++.dg/warn/Wdangling-pointer-2.C
* 20_util/any/misc/any_cast.cc
* 20_util/forward/c_neg.cc
* 20_util/forward/f_neg.cc
* experimental/any/misc/any_cast.cc
all of these look like genuine bugs.  A bootstrap with the warning
enabled by default passed.

When testing a previous version of the patch, there were many FAILs in
libstdc++'s 22_locale/; all of them because the warning triggered on

 const test_type& obj = std::use_facet(std::locale());

but this code looks valid -- std::use_facet doesn't return a reference
to its parameter.  Therefore I added code to suppress the warning when
the call is std::use_facet.  Now 22_locale/* pass even with the warning
on.  We could exclude more std:: functions like this if desirable.


Instead of adding special cases in the compiler, let's disable the warning
around the definition of use_facet (and adjust the compiler as needed so
that avoids the warning).


As I said in

I don't think it's possible without inventing an attribute (?).


Replied.


Fixed.
  

+  tree fndecl = cp_get_callee_fndecl_nofold (call);
+  if (!fndecl
+  || warning_suppressed_p (fndecl, OPT_Wdangling_reference)
+  /* Don't warn about member functions; the warning would trigger in
+valid code like
+  std::any a(...);
+  S& s = a.emplace({0}, 0);
+which constructs a new object and returns a reference to it.  */
+  || DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+  /* It seems unreasonable to warn about operator functions.  */
+  || DECL_OVERLOADED_OPERATOR_P (fndecl)


I guess I'd expect false positives on << and >> because of iostreams, do you
see false positives with other operators?


This was just a guess.  The warning triggered in g++.dg/overload/operator6.C.


That looks like a true positive.


Ok, then...


I suppose this could be limited to << and >>?  I'm not sure.


I'm not sure either.  Another possibility would be to only consider the LHS
of binary operators, since returning a reference to the RHS is very unusual.


...I've removed the DECL_OVERLOADED_OPERATOR_P check altogether and don't
really see any false positives.  It's probably better to start with a more
general warning and then tweak it based on empirical evidence.
  

+// Invalid, but we don't warn here yet.
+// r12 = f (f ((const int &) _EXPR ))
+const int& r12 = f(f(1));


This should be a simple recursion?


Hmm, the inner call is just a sub-expression of the full-expression so
there you can still use the returned temporary.  But in this case the
temporary is used beyond the full-expression so it's invalid.  I've added

   if (tree r = find_initializing_call_expr (arg))
 if (cp_tree_equal (CALL_EXPR_FN (r), CALL_EXPR_FN (expr)))
   return expr;

so that we detect f(f(1)) but I'm dubious that this is actually useful.


Indeed, but why limit it to checking for the same function rather than also
warning for

f(g(1))

or

A().f().g()

?


OK, I've made the warning even more recursive so that now we detect
both of these, see Wdangling-reference3.C.  While at it, I've renamed
the functions.

As before, I've tested this patch twice, once with -Wdangling-reference
enabled by default, once with -Wdangling-reference enabled by -Wextra.
The couple of FAILs I saw were true positives (e.g., 

Re: [PATCH v3] c++: parser - Support for target address spaces in C++

2022-10-26 Thread Jason Merrill via Gcc-patches

On 10/26/22 03:18, Paul Iannetta wrote:

On Wed, Oct 19, 2022 at 02:55:21PM -0400, Jason Merrill wrote:

On 10/18/22 13:01, Paul Iannetta wrote:

Thank you very much for the detailed review.

On Tue, Oct 18, 2022 at 10:24:23AM -0400, Jason Merrill wrote:

On 10/18/22 03:37, Paul Iannetta wrote:

On Fri, Oct 14, 2022 at 11:19:50AM -0400, Jason Merrill wrote:

On 10/13/22 17:57, Paul Iannetta wrote:

On Thu, Oct 13, 2022 at 03:41:16PM -0400, Jason Merrill wrote:

On 10/13/22 12:02, Paul Iannetta wrote:

On Thu, Oct 13, 2022 at 11:47:42AM -0400, Jason Merrill wrote:

On 10/13/22 11:23, Paul Iannetta wrote:

On Thu, Oct 13, 2022 at 11:02:24AM -0400, Jason Merrill wrote:

On 10/12/22 20:52, Paul Iannetta wrote:

There are quite a few things I would like to clarify concerning some
implementation details.
 - A variable with automatic storage (which is neither a pointer nor
   a reference) cannot be qualified with an address space.  I detect
   this by the combination of `sc_none' and `! toplevel_bindings_p ()',
   but I've also seen the use of `at_function_scope' at other places.
   And I'm unsure which one is appropriate here.
   This detection happens at the very end of grokdeclarator because I
   need to know that the type is a pointer, which is not know until
   very late in the function.


At that point you have the decl, and you can ask directly what its storage
duration is, perhaps using decl_storage_duration.

But why do you need to know whether the type is a pointer?  The attribute
applies to the target type of the pointer, not the pointer type.  I think
the problem is that you're looking at declspecs when you ought to be looking
at type_quals.


I need to know that the base type is a pointer to reject invalid
declarations such as:

  int f (__seg_fs int a) { } or int f () { __seg_fs int a; }

because parameters and auto variables can have an address space
qualifier only if they are pointer or reference type, which I can't
tell only from type_quals.


But "int *__seg_fs a" is just as invalid as the above; the difference is not
whether a is a pointer, but whether the address-space-qualified is the type
of a itself or some sub-type.


I agree that "int * __seg_fs a" is invalid but it is accepted by the C
front-end, and by clang (both C and C++), the behavior is that the
address-name is silently ignored.


Hmm, that sounds like a bug; in that case, presumably the user meant to
qualify the pointed-to type, and silently ignoring seems unlikely to give
the effect they want.



Well, actually, I'm re-reading the draft and "int * __seg_fs a" is
valid.  It means "pointer in address space __seg_fs pointing to an
object in the generic address space", whereas "__seg_fs int * a" means
"pointer in the generic address space pointing to an object in the
__seg_fs address-space".

Oddities such as, "__seg_fs int * __seg_gs a" are also perfectly
valid.


If a has static storage duration, sure; I was still thinking about
declarations with automatic storage duration such as in your example above.



Thanks, I only use type_quals now. I also took into account the style
recommendations from Jakub, and included the other template tests.
I rebased over trunk, bootstrapped the compiler and run the "make
check-gcc" with no regressions on x86.

Paul

#  >8 
Add support for custom address spaces in C++

gcc/
   * tree.h (ENCODE_QUAL_ADDR_SPACE): Missing parentheses.

gcc/c/
   * c-decl.cc: Remove c_register_addr_space.

gcc/c-family/
   * c-common.cc (c_register_addr_space): Imported from c-decl.cc
   (addr_space_superset): Imported from gcc/c/c-typecheck.cc
   * c-common.h: Remove the FIXME.
   (addr_space_superset): New declaration.

gcc/cp/
   * cp-tree.h (enum cp_decl_spec): Add addr_space support.
   (struct cp_decl_specifier_seq): Likewise.
   * decl.cc (get_type_quals): Likewise.
   (check_tag_decl): Likewise.
(grokdeclarator): Likewise.
   * parser.cc (cp_parser_type_specifier): Likewise.
   (cp_parser_cv_qualifier_seq_opt): Likewise.
   (cp_parser_postfix_expression): Likewise.
   (cp_parser_type_specifier): Likewise.
   (set_and_check_decl_spec_loc): Likewise.
   * typeck.cc (composite_pointer_type): Likewise
   (comp_ptr_ttypes_real): Likewise.
(same_type_ignoring_top_level_qualifiers_p): Likewise.
   * pt.cc (check_cv_quals_for_unify): Likewise.
   (unify): Likewise.
   * tree.cc: Remove c_register_addr_space stub.
   * mangle.cc (write_CV_qualifiers_for_type): Mangle address spaces
 using the extended qualifier notation.

gcc/doc
   * extend.texi (Named Address Spaces): add a mention about C++
 support.

gcc/testsuite/
   * g++.dg/abi/mangle-addr-space1.C: New test.
   

[PATCH v3] c++: Implement -Wdangling-reference [PR106393]

2022-10-26 Thread Marek Polacek via Gcc-patches
On Tue, Oct 25, 2022 at 11:53:51AM -0400, Jason Merrill via Gcc-patches wrote:
> On 10/25/22 11:21, Marek Polacek wrote:
> > On Mon, Oct 24, 2022 at 01:30:42PM -0400, Jason Merrill wrote:
> > > On 10/21/22 19:28, Marek Polacek wrote:
> > > > It doesn't warn when the function in question is a member function, 
> > > > otherwise
> > > > it'd emit loads of warnings for valid code like obj.emplace({0}, 0).
> > > 
> > > We had discussed warning if the object argument is a temporary (and for 
> > > the
> > > above check, the function returns *this)?
> > 
> > Presumably you mean detecting something like this:
> > 
> > struct S {
> >const S& self () { return *this; }
> > };
> > const S& s = S().self();
> 
> Yes.  Or
> 
> struct S {
>   int ar[4];
>   int& operator[](int i) { return ar[i]; }
> };
> const int  = S()[2];

Ok, I've extended the warning to check if the object argument is a temporary
as well, so we get a warning here now.
 
> > I don't currently have a way to detect it, can I steal a METHOD_TYPE flag
> > that says "this member function returns *this"?  Alternatively, walk its
> > DECL_SAVED_TREE and look for RETURN_EXPR?
> 
> Like you limited the above check to TREE_STATIC, let's also forget about
> checking for return *this.

I don't follow, but it looks like I don't need to change anything and just
keep the TREE_STATIC check?
 
> > > > It warns in member initializer lists as well:
> > > > 
> > > > const int& f(const int& i) { return i; }
> > > > struct S {
> > > >   const int  // { dg-warning "dangling reference" }
> > > >   S() : r(f(10)) { } // { dg-message "destroyed" }
> > > > };
> > > > 
> > > > I've run the testsuite/bootstrap with the warning enabled by default.
> > > > There were just a few FAILs:
> > > > * g++.dg/warn/Wdangling-pointer-2.C
> > > > * 20_util/any/misc/any_cast.cc
> > > > * 20_util/forward/c_neg.cc
> > > > * 20_util/forward/f_neg.cc
> > > > * experimental/any/misc/any_cast.cc
> > > > all of these look like genuine bugs.  A bootstrap with the warning
> > > > enabled by default passed.
> > > > 
> > > > When testing a previous version of the patch, there were many FAILs in
> > > > libstdc++'s 22_locale/; all of them because the warning triggered on
> > > > 
> > > > const test_type& obj = std::use_facet(std::locale());
> > > > 
> > > > but this code looks valid -- std::use_facet doesn't return a reference
> > > > to its parameter.  Therefore I added code to suppress the warning when
> > > > the call is std::use_facet.  Now 22_locale/* pass even with the warning
> > > > on.  We could exclude more std:: functions like this if desirable.
> > > 
> > > Instead of adding special cases in the compiler, let's disable the warning
> > > around the definition of use_facet (and adjust the compiler as needed so
> > > that avoids the warning).
> > 
> > As I said in
> > 
> > I don't think it's possible without inventing an attribute (?).
> 
> Replied.

Fixed.
 
> > > > +  tree fndecl = cp_get_callee_fndecl_nofold (call);
> > > > +  if (!fndecl
> > > > +  || warning_suppressed_p (fndecl, OPT_Wdangling_reference)
> > > > +  /* Don't warn about member functions; the warning would trigger 
> > > > in
> > > > +valid code like
> > > > +  std::any a(...);
> > > > +  S& s = a.emplace({0}, 0);
> > > > +which constructs a new object and returns a reference to it.  
> > > > */
> > > > +  || DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
> > > > +  /* It seems unreasonable to warn about operator functions.  */
> > > > +  || DECL_OVERLOADED_OPERATOR_P (fndecl)
> > > 
> > > I guess I'd expect false positives on << and >> because of iostreams, do 
> > > you
> > > see false positives with other operators?
> > 
> > This was just a guess.  The warning triggered in 
> > g++.dg/overload/operator6.C.
> 
> That looks like a true positive.

Ok, then...

> > I suppose this could be limited to << and >>?  I'm not sure.
> 
> I'm not sure either.  Another possibility would be to only consider the LHS
> of binary operators, since returning a reference to the RHS is very unusual.

...I've removed the DECL_OVERLOADED_OPERATOR_P check altogether and don't
really see any false positives.  It's probably better to start with a more
general warning and then tweak it based on empirical evidence.
 
> > > > +// Invalid, but we don't warn here yet.
> > > > +// r12 = f (f ((const int &) _EXPR ))
> > > > +const int& r12 = f(f(1));
> > > 
> > > This should be a simple recursion?
> > 
> > Hmm, the inner call is just a sub-expression of the full-expression so
> > there you can still use the returned temporary.  But in this case the
> > temporary is used beyond the full-expression so it's invalid.  I've added
> > 
> >   if (tree r = find_initializing_call_expr (arg))
> > if (cp_tree_equal (CALL_EXPR_FN (r), CALL_EXPR_FN (expr)))
> >   return expr;
> > 
> > so that we 

Re: [PATCH] ipa-visibility: remove assert in TLS optimization [PR107353]

2022-10-26 Thread Martin Jambor
Hi,

On Wed, Oct 26 2022, Alexander Monakov wrote:
> When upgrading TLS access model based on optimized symbol visibility
> status, we attempted to assert that recomputing the model would not
> weaken it. It turns out that C, C++, and Fortran front-ends all can
> (unintentionally) assign a stronger model than what can be derived
> from the declaration.

If you believe that FEs assign a wrong model sometimes (that is my
impression after reading your bugzilla comments), please open bugs for
those cases.

>
> Let's act conservatively instead of asserting, at least as long as
> such pre-existing issues remain.
>
> gcc/ChangeLog:
>
>   PR other/107353
>   * ipa-visibility.cc (function_and_variable_visibility):
>   Conditionally upgrade TLS model instead of asserting.

The patch is OK (assuming it passes bootstrap).

Thanks,

Martin


> ---
>  gcc/ipa-visibility.cc | 8 ++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/ipa-visibility.cc b/gcc/ipa-visibility.cc
> index 3ed2b7cf6..238f7eb84 100644
> --- a/gcc/ipa-visibility.cc
> +++ b/gcc/ipa-visibility.cc
> @@ -886,8 +886,12 @@ function_and_variable_visibility (bool whole_program)
> && vnode->ref_list.referring.length ())
>   {
> enum tls_model new_model = decl_default_tls_model (decl);
> -   gcc_checking_assert (new_model >= decl_tls_model (decl));
> -   set_decl_tls_model (decl, new_model);
> +   STATIC_ASSERT (TLS_MODEL_GLOBAL_DYNAMIC < 
> TLS_MODEL_LOCAL_DYNAMIC);
> +   STATIC_ASSERT (TLS_MODEL_INITIAL_EXEC < TLS_MODEL_LOCAL_EXEC);
> +   /* We'd prefer to assert that recomputed model is not weaker than
> +  what the front-end assigned, but cannot: see PR 107353.  */
> +   if (new_model >= decl_tls_model (decl))
> + set_decl_tls_model (decl, new_model);
>   }
>   }
>  }
> -- 
> 2.37.2


Re: [PATCH 10/15 V2] arm: Implement cortex-M return signing address codegen

2022-10-26 Thread Andrea Corallo via Gcc-patches
Richard Earnshaw  writes:

> On 14/09/2022 15:20, Andrea Corallo via Gcc-patches wrote:
>> Hi all,
>> 
>> this patch enables address return signature and verification based on
>> Armv8.1-M Pointer Authentication [1].
>> 
>> To sign the return address, we use the PAC R12, LR, SP instruction
>> upon function entry.  This is signing LR using SP and storing the
>> result in R12.  R12 will be pushed into the stack.
>> 
>> During function epilogue R12 will be popped and AUT R12, LR, SP will
>> be used to verify that the content of LR is still valid before return.
>> 
>> Here an example of PAC instrumented function prologue and epilogue:
>> 
>> void foo (void);
>> 
>> int main()
>> {
>>foo ();
>>return 0;
>> }
>> 
>> Compiled with '-march=armv8.1-m.main -mbranch-protection=pac-ret
>> -mthumb' translates into:
>> 
>> main:
>>  pac ip, lr, sp
>>  push{r3, r7, ip, lr}
>>  add r7, sp, #0
>>  bl  foo
>>  movsr3, #0
>>  mov r0, r3
>>  pop {r3, r7, ip, lr}
>>  aut ip, lr, sp
>>  bx  lr
>> 
>> The patch also takes care of generating a PACBTI instruction in place
>> of the sequence BTI+PAC when Branch Target Identification is enabled
>> contextually.
>> 
>> Ex. the previous example compiled with '-march=armv8.1-m.main
>> -mbranch-protection=pac-ret+bti -mthumb' translates into:
>> 
>> main:
>>  pacbti  ip, lr, sp
>>  push{r3, r7, ip, lr}
>>  add r7, sp, #0
>>  bl  foo
>>  movsr3, #0
>>  mov r0, r3
>>  pop {r3, r7, ip, lr}
>>  aut ip, lr, sp
>>  bx  lr
>> 
>> As part of previous upstream suggestions a test for varargs has been
>> added and '-mtpcs-frame' is deemed being incompatible with this return
>> signing address feature being introduced.
>> 
>> [1] 
>> 
>> 
>> gcc/Changelog
>> 
>> 2021-11-03  Andrea Corallo  
>> 
>>  * config/arm/arm.c: (arm_compute_frame_layout)
>>  (arm_expand_prologue, thumb2_expand_return, arm_expand_epilogue)
>>  (arm_conditional_register_usage): Update for pac codegen.
>>  (arm_current_function_pac_enabled_p): New function.
>>  * config/arm/arm.md (pac_ip_lr_sp, pacbti_ip_lr_sp, aut_ip_lr_sp):
>>  Add new patterns.
>>  * config/arm/unspecs.md (UNSPEC_PAC_IP_LR_SP)
>>  (UNSPEC_PACBTI_IP_LR_SP, UNSPEC_AUT_IP_LR_SP): Add unspecs.
>> 
>> gcc/testsuite/Changelog
>> 
>> 2021-11-03  Andrea Corallo  
>> 
>>  * gcc.target/arm/pac.h : New file.
>>  * gcc.target/arm/pac-1.c : New test case.
>>  * gcc.target/arm/pac-2.c : Likewise.
>>  * gcc.target/arm/pac-3.c : Likewise.
>>  * gcc.target/arm/pac-4.c : Likewise.
>>  * gcc.target/arm/pac-5.c : Likewise.
>>  * gcc.target/arm/pac-6.c : Likewise.
>>  * gcc.target/arm/pac-7.c : Likewise.
>>  * gcc.target/arm/pac-8.c : Likewise.
>> 
>
> +  if (arm_current_function_pac_enabled_p () && !(arm_arch7 && 
> arm_arch_cmse))
> +error ("This architecture does not support branch protection 
> instructions");
>
> This test feels wrong.  What does having cmse give us?  I suspect you 
> want a test that ensures we have at least v8-m.main so that the NOP 
> instructions are correctly defined as NOPs (or, in this case, PACBTI 
> instructions) rather than unpredictable; but if that's the case then I 
> think you really want to write the test that way here (perhaps in a 
> macro) and then move this test into that so that it becomes 
> self-documenting - but don't we have a v8-m.main test anyway?

Yep

> +   if (arm_current_function_pac_enabled_p ())
> + {
> +  gcc_assert (!(saved_regs_mask & (1 << PC_REGNUM)));
> +   arm_emit_multi_reg_pop (saved_regs_mask);
> +   emit_insn (gen_aut_nop ());
> +   emit_jump_insn (simple_return_rtx);
> + }
>
> The assert is using indents that are just spaces, but the other lines 
> use tabs.  Please use tabs everywhere rather than mixing like this.

Ack.

> +/* Return TRUE if return address signing mechanism is enabled.  */
> +bool
> +arm_current_function_pac_enabled_p (void)
> +{
> +  return aarch_ra_sign_scope == AARCH_FUNCTION_ALL
> +|| (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
> + && !crtl->is_leaf);
> +}
>
> This is a case where you should use parenthesis around the expression so 
> that the continuation lines are correctly indented.

Ack.

> @@ -11518,7 +11518,7 @@ (define_expand "prologue"
>arm_expand_prologue ();
>  else
>thumb1_expand_prologue ();
> -  DONE;
> +   DONE;
> "
>   )
>
> Although this is a trivial cleanup, it has nothing to do with this 
> patch.  Please remove.

Okay.

> +  "arm_arch7 && arm_arch_cmse"
>
> See my comments earlier about this test; the same applies here.
>
> + (unspec:SI [(reg:SI SP_REGNUM) (reg:SI LR_REGNUM)]
> +   

Re: Extend fold_vec_perm to fold VEC_PERM_EXPR in VLA manner

2022-10-26 Thread Richard Sandiford via Gcc-patches
Sorry for the slow response.  I wanted to find some time to think
about this a bit more.

Prathamesh Kulkarni  writes:
> On Fri, 30 Sept 2022 at 21:38, Richard Sandiford
>  wrote:
>>
>> Richard Sandiford via Gcc-patches  writes:
>> > Prathamesh Kulkarni  writes:
>> >> Sorry to ask a silly question but in which case shall we select 2nd 
>> >> vector ?
>> >> For num_poly_int_coeffs == 2,
>> >> a1 /trunc n1 == (a1 + 0x) / (n1.coeffs[0] + n1.coeffs[1]*x)
>> >> If a1/trunc n1 succeeds,
>> >> 0 / n1.coeffs[1] == a1/n1.coeffs[0] == 0.
>> >> So, a1 has to be < n1.coeffs[0] ?
>> >
>> > Remember that a1 is itself a poly_int.  It's not necessarily a constant.
>> >
>> > E.g. the TRN1 .D instruction maps to a VEC_PERM_EXPR with the selector:
>> >
>> >   { 0, 2 + 2x, 1, 4 + 2x, 2, 6 + 2x, ... }
>>
>> Sorry, should have been:
>>
>>   { 0, 2 + 2x, 2, 4 + 2x, 4, 6 + 2x, ... }
> Hi Richard,
> Thanks for the clarifications, and sorry for late reply.
> I have attached POC patch that tries to implement the above approach.
> Passes bootstrap+test on x86_64-linux-gnu and aarch64-linux-gnu for VLS 
> vectors.
>
> For VLA vectors, I have only done limited testing so far.
> It seems to pass couple of tests written in the patch for
> nelts_per_pattern == 3,
> and folds the following svld1rq test:
> int32x4_t v = {1, 2, 3, 4};
> return svld1rq_s32 (svptrue_b8 (), [0])
> into:
> return {1, 2, 3, 4, ...};
> I will try to bootstrap+test it on SVE machine to test further for VLA 
> folding.
>
> I have a couple of questions:
> 1] When mask selects elements from same vector but from different patterns:
> For eg:
> arg0 = {1, 11, 2, 12, 3, 13, ...},
> arg1 = {21, 31, 22, 32, 23, 33, ...},
> mask = {0, 0, 0, 1, 0, 2, ... },
> All have npatterns = 2, nelts_per_pattern = 3.
>
> With above mask,
> Pattern {0, ...} selects arg0[0], ie {1, ...}
> Pattern {0, 1, 2, ...} selects arg0[0], arg0[1], arg0[2], ie {1, 11, 2, ...}
> While arg0[0] and arg0[2] belong to same pattern, arg0[1] belongs to different
> pattern in arg0.
> The result is:
> res = {1, 1, 1, 11, 1, 2, ...}
> In this case, res's 2nd pattern {1, 11, 2, ...} is encoded with:
> with a0 = 1, a1 = 11, S = -9.
> Is that expected tho ? It seems to create a new encoding which
> wasn't present in the input vector. For instance, the next elem in
> sequence would be -7,
> which is not present originally in arg0.

Yeah, you're right, sorry.  Going back to:

(2) The explicit encoding can be used to produce a sequence of N*Ex*Px
elements for any integer N.  This extended sequence can be reencoded
as having N*Px patterns, with Ex staying the same.

I guess we need to pick an N for the selector such that each new
selector pattern (each one out of the N*Px patterns) selects from
the *same pattern* of the same data input.

So if a particular pattern in the selector has a step S, and the data
input it selects from has Pi patterns, N*S must be a multiple of Pi.
N must be a multiple of least_common_multiple(S,Pi)/S.

I think that means that the total number of patterns in the result
(Pr from previous messages) can safely be:

  Ps * least_common_multiple(
least_common_multiple(S[1], P[input(1)]) / S[1],
...
least_common_multiple(S[Ps], P[input(Ps)]) / S[Ps]
  )

where:

  Ps = the number of patterns in the selector
  S[I] = the step for selector pattern I (I being 1-based)
  input(I) = the data input selected by selector pattern I (I being 1-based)
  P[I] = the number of patterns in data input I

That's getting quite complicated :-)  If we allow arbitrary P[...]
and S[...] then it could also get large.  Perhaps we should finally
give up on the general case and limit this to power-of-2 patterns and
power-of-2 steps, so that least_common_multiple becomes MAX.  Maybe that
simplifies other things as well.

What do you think?

> I suppose it's fine since if the user defines mask to have pattern {0,
> 1, 2, ...}
> they intended result to have pattern with above encoding.
> Just wanted to confirm if this is correct ?
>
> 2] Could you please suggest a test-case for S < 0 ?
> I am not able to come up with one :/

svrev is one way of creating negative steps.

Thanks,
Richard

>
> Thanks,
> Prathamesh
>>
>> > which is an interleaving of the two patterns:
>> >
>> >   { 0, 2, 4, ... }  a0 = 0, a1 = 2, S = 2
>> >   { 2 + 2x, 4 + 2x, 6 + 2x }a0 = 2 + 2x, a1 = 4 + 2x, S = 2


Re: RFC - VRP1 default mode

2022-10-26 Thread Jeff Law via Gcc-patches



On 10/26/22 08:24, Andrew MacLeod wrote:
Figured I would ask what you guys think of making ranger the default 
for the VRP1 pass now.


With partial equivalences and the other bits I checked in the past few 
weeks I'm not aware of much that the legacy VRP pass gets that ranger 
doesn't.  The only exception to that which I am aware of is the trick 
played with the unreachable edges to set global ranges, but that is 
done in the DOM passes now anyway... so it just happens slightly later 
in the optimization cycle. There is one test case that needs 
adjustment for that which was just checking for a mask in DOM2 
(gcc.dg/tree-ssa/pr107009.c).   At this point I have not aware of 
anything that Id be concerned about, and the testsuite seems to run 
cleanly.


We could change the default now and see if any issues show up, giving 
us a chance to address them. The code base has been well exercised for 
a while so risk should be low.  We could also reduce code size by 
stripping out unneeded code if we so desired.


Or we could leave things as they are for one more cycle.  My 
preference would be to make the switch now and let it play out. Thoughts?


I'd rather switch now than wait another cycle.  We've got mass rebuilds 
coming  up in a few months which should give us a good indicator if 
there's any notable issues that need to get resolved.



Jeff



RFC - VRP1 default mode

2022-10-26 Thread Andrew MacLeod via Gcc-patches
Figured I would ask what you guys think of making ranger the default for 
the VRP1 pass now.


With partial equivalences and the other bits I checked in the past few 
weeks I'm not aware of much that the legacy VRP pass gets that ranger 
doesn't.  The only exception to that which I am aware of is the trick 
played with the unreachable edges to set global ranges, but that is done 
in the DOM passes now anyway... so it just happens slightly later in the 
optimization cycle. There is one test case that needs adjustment for 
that which was just checking for a mask in DOM2 
(gcc.dg/tree-ssa/pr107009.c).   At this point I have not aware of 
anything that Id be concerned about, and the testsuite seems to run 
cleanly.


We could change the default now and see if any issues show up, giving us 
a chance to address them. The code base has been well exercised for a 
while so risk should be low.  We could also reduce code size by 
stripping out unneeded code if we so desired.


Or we could leave things as they are for one more cycle.  My preference 
would be to make the switch now and let it play out. Thoughts?


Andrew






[PATCH] ipa-visibility: remove assert in TLS optimization [PR107353]

2022-10-26 Thread Alexander Monakov
When upgrading TLS access model based on optimized symbol visibility
status, we attempted to assert that recomputing the model would not
weaken it. It turns out that C, C++, and Fortran front-ends all can
(unintentionally) assign a stronger model than what can be derived
from the declaration.

Let's act conservatively instead of asserting, at least as long as
such pre-existing issues remain.

gcc/ChangeLog:

PR other/107353
* ipa-visibility.cc (function_and_variable_visibility):
Conditionally upgrade TLS model instead of asserting.
---
 gcc/ipa-visibility.cc | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/ipa-visibility.cc b/gcc/ipa-visibility.cc
index 3ed2b7cf6..238f7eb84 100644
--- a/gcc/ipa-visibility.cc
+++ b/gcc/ipa-visibility.cc
@@ -886,8 +886,12 @@ function_and_variable_visibility (bool whole_program)
  && vnode->ref_list.referring.length ())
{
  enum tls_model new_model = decl_default_tls_model (decl);
- gcc_checking_assert (new_model >= decl_tls_model (decl));
- set_decl_tls_model (decl, new_model);
+ STATIC_ASSERT (TLS_MODEL_GLOBAL_DYNAMIC < 
TLS_MODEL_LOCAL_DYNAMIC);
+ STATIC_ASSERT (TLS_MODEL_INITIAL_EXEC < TLS_MODEL_LOCAL_EXEC);
+ /* We'd prefer to assert that recomputed model is not weaker than
+what the front-end assigned, but cannot: see PR 107353.  */
+ if (new_model >= decl_tls_model (decl))
+   set_decl_tls_model (decl, new_model);
}
}
 }
-- 
2.37.2



[COMMITTED] Check if varying may also be non-negative.

2022-10-26 Thread Andrew MacLeod via Gcc-patches
When strict enums are in use, we don't always get ranges reduced 
sufficiently thru casts and such.  Ranger vrp has been missing the odd 
case because I didn't notice that gimple_stmt_nonnegative_warnv_p() use 
to be called on all integral results that were varying, not just calls 
like it was doing. this corrects that.


Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.

Andrew
commit a87819b8f1b890d36a3f05bd9de80be20e9525dd
Author: Andrew MacLeod 
Date:   Tue Oct 25 15:16:47 2022 -0400

Check if varying may also be non-negative.

When using strict enums, we can sometimes turn varying into a better
range.

* gimple-range-fold.cc (fold_using_range::fold_stmt): Check if
stmt is non-negative and adjust the range.

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index f91923782dc..a899d8260b3 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -494,6 +494,14 @@ fold_using_range::fold_stmt (vrange , gimple *s, 
fur_source , tree name)
   else if (is_a (s) && gimple_assign_rhs_code (s) == COND_EXPR)
 res = range_of_cond_expr (r, as_a (s), src);
 
+  // If the result is varying, check for basic nonnegativeness.
+  // Specifically this helps for now with strict enum in cases like
+  // g++.dg/warn/pr33738.C.
+  bool so_p;
+  if (res && r.varying_p () && INTEGRAL_TYPE_P (r.type ())
+  && gimple_stmt_nonnegative_warnv_p (s, _p))
+r.set_nonnegative (r.type ());
+
   if (!res)
 {
   // If no name specified or range is unsupported, bail.


[PING] options: Clarify 'Init' option property usage for streaming optimization (was: [PATCH] options, lto: Optimize streaming of optimization nodes)

2022-10-26 Thread Thomas Schwinge
Hi!

Ping.  For convenience, I've re-attached
"options: Clarify 'Init' option property usage for streaming optimization".
(I've re-verified: "No functional change; no change in generated files.")


Grüße
 Thomas


On 2022-03-31T15:22:59+0200, I wrote:
> Hi!
>
> On 2020-11-18T10:36:35+0100, Jakub Jelinek via Gcc-patches 
>  wrote:
>> Honza mentioned that especially for the new param machinery, most of
>> streamed values are probably going to be the default values.  Perhaps
>> somehow we could stream them more effectively.
>>
>> This patch implements it and brings further savings, the size
>> goes down from 574 bytes to 273 bytes, i.e. less than half.
>
> Neat idea about the XOR-encoding!
>
>> Not trying to handle enums because the code doesn't know if (enum ...) 10
>> is even valid, similarly non-parameters because those really generally
>> don't have large initializers, and params without Init (those are 0
>> initialized and thus don't need to be handled).
>
> Given this only looks at 'Init', I understand this may actually
> mis-optimize in the case that there is an 'Init' present, but that value
> is then "by default" overridden via 'LANG_HOOKS_INIT_OPTIONS_STRUCT', or
> 'TARGET_OPTION_OVERRIDE', for example.  (I'm however not claiming that's
> an actual problem to be worried about -- just for my understanding.)
>
> Either way:
>
>>  * optc-save-gen.awk: Initialize var_opt_init.  In
>>  cl_optimization_stream_out for params with default values larger than
>>  10, xor the default value with the actual parameter value.  In
>>  cl_optimization_stream_in repeat the above xor.
>
>> --- gcc/optc-save-gen.awk.jj 2020-09-14 10:51:54.493740942 +0200
>> +++ gcc/optc-save-gen.awk2020-09-14 11:39:39.441602594 +0200
>> @@ -1186,6 +1186,7 @@ for (i = 0; i < n_opts; i++) {
>>  var_opt_val_type[n_opt_val] = otype;
>>  var_opt_val[n_opt_val] = "x_" name;
>>  var_opt_hash[n_opt_val] = flag_set_p("Optimization", flags[i]);
>> +var_opt_init[n_opt_val] = opt_args("Init", flags[i]);
>>  n_opt_val++;
>>  }
>>  }
>
> Reading through the options handling, I was confused why 'Init' needs to
> be handled in 'gcc/optc-save-gen.awk'.  To help the next person -- like,
> me in a few weeks ;-) -- wondering about this, OK to push the attached
> "options: Clarify 'Init' option property usage for streaming
> optimization"?
>
>
> Grüße
>  Thomas
>
>
>> @@ -1257,10 +1258,21 @@ for (i = 0; i < n_opt_val; i++) {
>>  otype = var_opt_val_type[i];
>>  if (otype ~ "^const char \\**$")
>>  print "  bp_pack_string (ob, bp, ptr->" name", true);";
>> -else if (otype ~ "^unsigned")
>> -print "  bp_pack_var_len_unsigned (bp, ptr->" name");";
>> -else
>> -print "  bp_pack_var_len_int (bp, ptr->" name");";
>> +else {
>> +if (otype ~ "^unsigned") {
>> +sgn = "unsigned";
>> +} else {
>> +sgn = "int";
>> +}
>> +if (name ~ "^x_param" && !(otype ~ "^enum ") && 
>> var_opt_init[i]) {
>> +print "  if (" var_opt_init[i] " > (" 
>> var_opt_val_type[i] ") 10)";
>> +print "bp_pack_var_len_" sgn " (bp, ptr->" name" ^ 
>> " var_opt_init[i] ");";
>> +print "  else";
>> +print "bp_pack_var_len_" sgn " (bp, ptr->" name");";
>> +} else {
>> +print "  bp_pack_var_len_" sgn " (bp, ptr->" name");";
>> +}
>> +}
>>  }
>>  print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof 
>> (ptr->explicit_mask[0]); i++)";
>>  print "bp_pack_value (bp, ptr->explicit_mask[i], 64);";
>> @@ -1281,10 +1293,18 @@ for (i = 0; i < n_opt_val; i++) {
>>  print "  if (ptr->" name")";
>>  print "ptr->" name" = xstrdup (ptr->" name");";
>>  }
>> -else if (otype ~ "^unsigned")
>> -print "  ptr->" name" = (" var_opt_val_type[i] ") 
>> bp_unpack_var_len_unsigned (bp);";
>> -else
>> -print "  ptr->" name" = (" var_opt_val_type[i] ") 
>> bp_unpack_var_len_int (bp);";
>> +else {
>> +if (otype ~ "^unsigned") {
>> +sgn = "unsigned";
>> +} else {
>> +sgn = "int";
>> +}
>> +print "  ptr->" name" = (" var_opt_val_type[i] ") 
>> bp_unpack_var_len_" sgn " (bp);";
>> +if (name ~ "^x_param" && !(otype ~ "^enum ") && 
>> var_opt_init[i]) {
>> +print "  if (" var_opt_init[i] " > (" 
>> var_opt_val_type[i] ") 10)";
>> +print "ptr->" name" ^= " var_opt_init[i] ";";
>> +}
>> +}
>>  }
>>  print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof 
>> (ptr->explicit_mask[0]); i++)";
>>  print "ptr->explicit_mask[i] = bp_unpack_value (bp, 64);";


-
Siemens Electronic Design Automation GmbH; 

Document 'distclean-stage[N]'

2022-10-26 Thread Thomas Schwinge
Hi!

OK to push the attached patch to "Document 'distclean-stage[N]'"?


Grüße
 Thomas


-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
>From c20771b2fc13bdb24f3ad538c1806eeccbedfd3c Mon Sep 17 00:00:00 2001
From: Thomas Schwinge 
Date: Wed, 26 Oct 2022 13:07:27 +0200
Subject: [PATCH] Document 'distclean-stage[N]'

Refer to 'Makefile.tpl':

# Rules to wipe a stage and all the following ones, also used for cleanstrap
[+ IF prev +]distclean-stage[+prev+]:: distclean-stage[+id+] [+ ENDIF prev +]
.PHONY: distclean-stage[+id+]
distclean-stage[+id+]::
	@: $(MAKE); $(stage)
	@test "`cat stage_last`" != stage[+id+] || rm -f stage_last
	rm -rf stage[+id+]-* [+
	  IF compare-target +][+compare-target+] [+ ENDIF compare-target +]

	gcc/
	* doc/makefile.texi (Makefile Targets): Document
	'distclean-stage[N]'.
---
 gcc/doc/makefile.texi | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/gcc/doc/makefile.texi b/gcc/doc/makefile.texi
index fe0bbcd2ed1..5186c1cd9d5 100644
--- a/gcc/doc/makefile.texi
+++ b/gcc/doc/makefile.texi
@@ -135,6 +135,16 @@ Compares the results of stages 2 and 3.  This ensures that the compiler
 is running properly, since it should produce the same object files
 regardless of how it itself was compiled.
 
+@item distclean-stage@var{N} (@var{N} = 1@dots{}4, profile, feedback)
+Wipe stage @var{N} and all the following ones.
+
+For example,
+@samp{make distclean-stage3} wipes stage 3 and all the following ones,
+so that another @command{make} then rebuilds them from scratch.
+This can be useful if you're doing changes where
+``bubbling'' the changes as described above is not sufficient,
+but a full @command{make restrap} isn't necessary either.
+
 @item profiledbootstrap
 Builds a compiler with profiling feedback information.  In this case,
 the second and third stages are named @samp{profile} and @samp{feedback},
-- 
2.35.1



[PATCH V2] rs6000: Support to build constants by li/lis+oris/xoris

2022-10-26 Thread Jiufu Guo via Gcc-patches
Hi,

PR106708 constaint some constants which can be support by li/lis + oris/xoris.

For constant C:
if '(c & 0x80008000ULL) == 0x8000ULL' or say:
32(0) || 1(1) || 15(x) || 1(0) || 15(x), we could use li+oris to
build constant 'C'.
Here N(M) means N continuous bit M, x for M means it is ok for either
1 or 0; '||' means concatenation.

if '(c & 0x8000ULL) == 0x8000ULL' or say:
32(1) || 16(x) || 1(1) || 15(x), using li+xoris would be ok.

if '(c & 0xULL) == 0x' or say:
32(1) || 1(0) || 15(x) || 16(0), using lis+xoris would be ok.

This patch update rs6000_emit_set_long_const to support these forms.
Bootstrap and regtest pass on ppc64 and ppc64le.

Is this ok for trunk?

BR,
Jeff(Jiufu)


PR target/106708

gcc/ChangeLog:

* config/rs6000/rs6000.cc (rs6000_emit_set_long_const): Support
constants which can be built with li + oris or li/lis + xoris.

gcc/testsuite/ChangeLog:

* gcc.target/powerpc/pr106708-run.c: New test.
* gcc.target/powerpc/pr106708.c: New test.
* gcc.target/powerpc/pr106708.h: New file.

---
 gcc/config/rs6000/rs6000.cc   | 41 ++-
 .../gcc.target/powerpc/pr106708-run.c | 17 
 gcc/testsuite/gcc.target/powerpc/pr106708.c   | 12 ++
 gcc/testsuite/gcc.target/powerpc/pr106708.h   |  9 
 4 files changed, 69 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr106708-run.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr106708.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr106708.h

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index d2743f7bce6..9b7a51f052d 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -10228,6 +10228,7 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c)
 {
   rtx temp;
   HOST_WIDE_INT ud1, ud2, ud3, ud4;
+  HOST_WIDE_INT orig_c = c;
 
   ud1 = c & 0x;
   c = c >> 16;
@@ -10253,21 +10254,41 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c)
gen_rtx_IOR (DImode, copy_rtx (temp),
 GEN_INT (ud1)));
 }
+  else if ((ud4 == 0x && ud3 == 0x)
+  && ((ud1 & 0x8000) || (ud1 == 0 && !(ud2 & 0x8000
+{
+  temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
+
+  HOST_WIDE_INT imm = (ud1 & 0x8000) ? ((ud1 ^ 0x8000) - 0x8000)
+: ((ud2 << 16) - 0x8000);
+  /* li/lis + xoris */
+  emit_move_insn (temp, GEN_INT (imm));
+  emit_move_insn (dest, gen_rtx_XOR (DImode, temp,
+GEN_INT (orig_c ^ imm)));
+}
   else if (ud3 == 0 && ud4 == 0)
 {
   temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
 
   gcc_assert (ud2 & 0x8000);
-  emit_move_insn (copy_rtx (temp),
- GEN_INT (((ud2 << 16) ^ 0x8000) - 0x8000));
-  if (ud1 != 0)
-   emit_move_insn (copy_rtx (temp),
-   gen_rtx_IOR (DImode, copy_rtx (temp),
-GEN_INT (ud1)));
-  emit_move_insn (dest,
- gen_rtx_ZERO_EXTEND (DImode,
-  gen_lowpart (SImode,
-   copy_rtx (temp;
+
+  if (!(ud1 & 0x8000))
+   {
+ /* li+oris */
+ emit_move_insn (temp, GEN_INT (ud1));
+ emit_move_insn (dest,
+ gen_rtx_IOR (DImode, temp, GEN_INT (ud2 << 16)));
+   }
+  else
+   {
+ emit_move_insn (temp,
+ GEN_INT (((ud2 << 16) ^ 0x8000) - 0x8000));
+ if (ud1 != 0)
+   emit_move_insn (temp, gen_rtx_IOR (DImode, temp, GEN_INT (ud1)));
+ emit_move_insn (dest,
+ gen_rtx_ZERO_EXTEND (DImode,
+  gen_lowpart (SImode, temp)));
+   }
 }
   else if (ud1 == ud3 && ud2 == ud4)
 {
diff --git a/gcc/testsuite/gcc.target/powerpc/pr106708-run.c 
b/gcc/testsuite/gcc.target/powerpc/pr106708-run.c
new file mode 100644
index 000..df65c321f6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr106708-run.c
@@ -0,0 +1,17 @@
+/* PR target/106708 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "pr106708.h"
+
+long long arr[] = {0x98765432ULL, 0x7cdeab55ULL, 
0x6543ULL};
+int
+main ()
+{
+  long long a[3];
+
+  foo (a);
+  if (__builtin_memcmp (a, arr, sizeof (arr)) != 0)
+__builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr106708.c 
b/gcc/testsuite/gcc.target/powerpc/pr106708.c
new file mode 100644
index 000..ebd9ea88993
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr106708.c
@@ -0,0 +1,12 @@
+/* PR target/106708 */
+/* { dg-do compile } } */
+/* { dg-options "-O2 

RE: [PATCH] ix86: Suggest unroll factor for loop vectorization

2022-10-26 Thread Cui, Lili via Gcc-patches
Hi Richard,

> +@item x86-vect-unroll-min-ldst-threshold
> +The vectorizer will check with target information to determine whether
> +unroll it. This parameter is used to limit the mininum of loads and
> +stores in the main loop.
> 
> It's odd to "limit" the minimum number of something.  I think this warrants
> clarification that for some (unknow to me ;)) reason we think that when we
> have many loads and (or?) stores it is beneficial to unroll to get even more
> loads and stores in a single iteration.  Btw, does the parameter limit the
> number of loads and stores _after_ unrolling or before?
> 
When the number of loads/stores exceeds the threshold, the loads/stores are 
more likely to conflict with loop itself in the L1 cache(Assuming that address 
of loads are scattered).
Unroll + software scheduling will make 2 or 4 address contiguous loads/stores 
closer together, it will reduce cache miss rate.

> +@item x86-vect-unroll-max-loop-size
> +The vectorizer will check with target information to determine whether
> +unroll it. This threshold is used to limit the max size of loop body after
> unrolling.
> +The default value is 200.
> 
> it should probably say not "size" but "number of instructions".  Note that 200
> is quite large given we are talking about vector instructions here which have
> larger encodings than scalar instructions.  Optimistically assuming
> 4 byte encoding (quite optimistic give we're looking at loops with many
> loads/stores) that would be an 800 byte loop body which would be 25 cache
> lines.
> ISTR that at least the loop discovery is limited to a lot smaller cases (but 
> we
> are likely not targeting that).  The limit probably still works to fit the 
> loop
> body in the u-op caches though.
> 
Agree with you, it should be "x86-vect-unroll-max-loop-insns". Thanks for the 
reminder about larger encodings, I checked the skylake uop cache, it can hold 
1.5k uOPs, 200 * 2 (1~3 uops/instruction) = 400 uops. I think 200 still work.

> That said, the heuristic made me think "what the heck".  Can we explain in u-
> arch terms why the unrolling is beneficial instead of just defering to SPEC
> CPU 2017 fotonik?
> 
Regarding the benefits,  I explained in the first answer, I checked 5 hottest 
functions in the 549, they all benefit from it, it improves the cache hit ratio.

Thanks,
Lili.

> > On Mon, Oct 24, 2022 at 10:46 AM Cui,Lili via Gcc-patches
> >  wrote:
> > >
> > > Hi Hongtao,
> > >
> > > This patch introduces function finish_cost and
> > > determine_suggested_unroll_factor for x86 backend, to make it be
> > > able to suggest the unroll factor for a given loop being vectorized.
> > > Referring to aarch64, RS6000 backends and basing on the analysis on
> > > SPEC2017 performance evaluation results.
> > >
> > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
> > >
> > > OK for trunk?
> > >
> > >
> > >
> > > With this patch, SPEC2017 performance evaluation results on
> > > ICX/CLX/ADL/Znver3 are listed below:
> > >
> > > For single copy:
> > >   - ICX: 549.fotonik3d_r +6.2%, the others are neutral
> > >   - CLX: 549.fotonik3d_r +1.9%, the others are neutral
> > >   - ADL: 549.fotonik3d_r +4.5%, the others are neutral
> > >   - Znver3: 549.fotonik3d_r +4.8%, the others are neutral
> > >
> > > For multi-copy:
> > >   - ADL: 549.fotonik3d_r +2.7%, the others are neutral
> > >
> > > gcc/ChangeLog:
> > >
> > > * config/i386/i386.cc (class ix86_vector_costs): Add new members
> > >  m_nstmts, m_nloads m_nstores and
> determine_suggested_unroll_factor.
> > > (ix86_vector_costs::add_stmt_cost): Update for m_nstores,
> m_nloads
> > > and m_nstores.
> > > (ix86_vector_costs::determine_suggested_unroll_factor): New
> function.
> > > (ix86_vector_costs::finish_cost): Diito.
> > > * config/i386/i386.opt:(x86-vect-unroll-limit): New parameter.
> > > (x86-vect-unroll-min-ldst-threshold): Likewise.
> > > (x86-vect-unroll-max-loop-size): Likewise.
> > > * doc/invoke.texi: Document new parameter.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > * gcc.target/i386/cond_op_maxmin_b-1.c: Add -fno-unroll-loops.
> > > * gcc.target/i386/cond_op_maxmin_ub-1.c: Ditto.
> > > * gcc.target/i386/vect-alignment-peeling-1.c: Ditto.
> > > * gcc.target/i386/vect-alignment-peeling-2.c: Ditto.
> > > * gcc.target/i386/vect-reduc-1.c: Ditto.
> > > ---
> > >  gcc/config/i386/i386.cc   | 106 ++
> > >  gcc/config/i386/i386.opt  |  15 +++
> > >  gcc/doc/invoke.texi   |  17 +++
> > >  .../gcc.target/i386/cond_op_maxmin_b-1.c  |   2 +-
> > >  .../gcc.target/i386/cond_op_maxmin_ub-1.c |   2 +-
> > >  .../i386/vect-alignment-peeling-1.c   |   2 +-
> > >  .../i386/vect-alignment-peeling-2.c   |   2 +-
> > >  gcc/testsuite/gcc.target/i386/vect-reduc-1.c  |   2 +-
> > >  8 files changed, 143 

Re: [PATCH] Aarch64: Do not define DONT_USE_BUILTIN_SETJMP

2022-10-26 Thread Richard Sandiford via Gcc-patches
Eric Botcazou via Gcc-patches  writes:
> Hi,
>
> we have been using an Ada compiler for the Aarch64 architecture configured 
> with SJLJ exceptions as for the other architectures for some time, and have 
> not run into any problems so far so the setting looks obsolete now.
>
> OK for the mainline?

OK, thanks.  Sorry for the slow reply on this.  I think you posted
the same (or a related) patch a while back and it wasn't reviewed.

I was a bit reluctant to say anything because it sounds like this
was defined for a reason, perhaps to avoid treating the current
expansion as ABI without further testing.  But if it has been used
for some time in Ada (and works) then it's already de facto ABI.
And it seems very unlikely that anyone would spend time trying
to tweak the expansion for other languages.

Richard

>
>
> 2022-10-24  Eric Botcazou  
>
>   * config/aarch64/aarch64.h (DONT_USE_BUILTIN_SETJMP): Delete.


[PATCH] docs: document sanitizers can trigger warnings

2022-10-26 Thread Martin Liška
PR sanitizer/107298

gcc/ChangeLog:

* doc/invoke.texi: Document sanitizers can trigger warnings.
---
 gcc/doc/invoke.texi | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 64f77e8367a..1ffbba16a72 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -16460,6 +16460,10 @@ by this option.
 
 @end table
 
+Note the enabled sanitizer options tend to increase a false-positive rate
+of selected warnings, most notably @option{-Wmaybe-uninitialized}.
+And thus we recommend to disable @option{-Werror}.
+
 While @option{-ftrapv} causes traps for signed overflows to be emitted,
 @option{-fsanitize=undefined} gives a diagnostic message.
 This currently works only for the C family of languages.
-- 
2.38.0



Re: [PATCH] [x86_64] Zhaoxin lujiazui enablement

2022-10-26 Thread Martin Liška
On 10/26/22 11:06, Mayshao-oc wrote:
> 
> Hi Martin:
>     Thanks for your patch,  I comment the questions below.

Hi.

:)

> 
>> Hello.
> 
>> I noticed this patch set which is kind of related to 
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107364.
> 
>> And I have a couple of questions:
> 
>>1) I noticed you drop AVX and F16C features for the newly added "lujiazui". 
>>Why do you need it?
>>  I would expect these features would be properly detected by cpuid?
> 
> Yes, these features could be detected by cpuid, and in respect of 
> functionality, these features are ok, but in respect of performance, these 
> features need further improvement, so we decide to drop it now, and add these 
> features back when performance meet our expectation.

I see. So theoretically you can increase costs of the corresponding insns and 
that could be dropped now?
But I'm not a costing expert.

> 
>> 2) If you really need it, can you please test for me the attached patch? It 
>> should come up
>>  with a new function.
> 
> I have tested the patch, It's ok. 

Good, I'm going to install it.

> 
>> 3) Have question about:
> 
>> else if (vendor == signature_CENTAUR_ebx && family < 0x07)
>>    cpu_model->__cpu_vendor = VENDOR_CENTAUR;
>> else if (vendor == signature_SHANGHAI_ebx
>>               || vendor == signature_CENTAUR_ebx)
> 
>> Are there any signature_CENTAUR_ebx models with family == 0x7 ?
>> Similarly, are there any signature_SHANGHAI_ebx modes with family < 0x7 ?
> 
> Yes, both cases exist in our products.

Good. Then we miss a CPU features detection for (vendor == 
signature_CENTAUR_ebx && family < 0x07)
aka https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107364. But it's not worth it 
as it's a legacy hardware,
right?

Cheers,
Martin

> 
>> Thanks,
>> Martin
> 
> BR 
> Mayshao



Re: [PATCH] OpenMP: Duplicate checking for map clauses in Fortran (PR107214)

2022-10-26 Thread Tobias Burnus

Hi Julian,

I had a first quick lock at this patch, I should have a closer look
later. However, I stumbled over the following:

On 20.10.22 18:14, Julian Brown wrote:

typedef struct gfc_symbol
{
...
   struct gfc_symbol *old_symbol;

   unsigned mark:1, comp_mark:1, data_mark:1, dev_mark:1, gen_mark:1;
   unsigned reduc_mark:1, gfc_new:1;

   struct gfc_symbol *tlink;

   unsigned equiv_built:1;
   ...

I know that this was the case before, but can you move the mark:1 etc.
after 'tlink'? In that case all bitfields are grouped together. If I
have not miscounted, we have currently 7 bits before and 9 bits after
'tlink' and grouping them together reduced pointless padding.

* * *

+  else if (n->sym->mark)
+ gfc_error ("Symbol %qs present on both data and map clauses "
+"at %L", n->sym->name, >where);


I wonder whether that also rejects the following – which seems to be
valid. The 'map' goes to 'target' and the 'firstprivate' to 'parallel',
cf. OpenMP 5.2, "17.2 Clauses on Combined and Composite Constructs",
[340:3-4 & 12-14]. (BTW: While some fixes went into 5.1 regarding this section,
a likewise wording is already in 5.0.)

(Testing showed: it give an ICE without the patch and an error with.)

module m
  integer :: a = 1
end module m

module m2
contains
subroutine bar()
  use m
  !$omp declare target
  a = a + 5
end subroutine bar
end

program p
  use m
  !$omp target parallel do map(a) firstprivate(a)
do i = 1, 1
   a = 7
  call bar()
   if (a /= 7) error stop 1
   a = a + 8

   end do
  if (a /= 6) error stop
end

 * * *

The ICE seems to be because gcc/fortran/trans-openmp.cc's gfc_split_omp_clauses
mishandles this as the dump shows the following:

  #pragma omp target firstprivate(a) map(tofrom:a)
#pragma omp parallel firstprivate(a)

 * * *

In contrast, for the C testcase:

void foo(int x) {
#pragma omp target parallel for simd map(x) firstprivate(x)
for (int k = 0; k < 1; ++k)
  x = 1;
}

the dump is as follows, which seems to be sensible:

  #pragma omp target map(tofrom:x)
#pragma omp parallel firstprivate(x)
  #pragma omp for nowait
#pragma omp simd

Tobias

-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955


[OG12][committed] Handle operator new with alignment in USM transform

2022-10-26 Thread Hafiz Abid Qadeer
This patch fixes an issue where alignment argument for new operator was being 
ignored in the unified
shared memory transform.

Thanks,
-- 
Hafiz Abid Qadeer
Siemens/CodeSourceryFrom af4162aac4086eb953139f7796bbb2ad232c8975 Mon Sep 17 00:00:00 2001
From: Hafiz Abid Qadeer 
Date: Tue, 25 Oct 2022 15:23:46 +0100
Subject: [PATCH] Handle operator new with alignment in usm transform.

Since C++17, the is a variant of operator new with alignment. This
patch converts it to omp_aligned_alloc when unified shared memory is
being used.

gcc/ChangeLog:

	* omp-low.cc (usm_transform): Handle operator new with alignment.

libgomp/ChangeLog:

	* testsuite/libgomp.c++/usm-2.C: New test.

gcc/testsuite/ChangeLog:

	* g++.dg/gomp/usm-4.C: New test.
	* g++.dg/gomp/usm-5.C: New test.
---
 gcc/ChangeLog.omp |  4 
 gcc/omp-low.cc| 16 +
 gcc/testsuite/ChangeLog.omp   |  5 
 gcc/testsuite/g++.dg/gomp/usm-4.C | 32 ++
 gcc/testsuite/g++.dg/gomp/usm-5.C | 30 
 libgomp/ChangeLog.omp |  4 
 libgomp/testsuite/libgomp.c++/usm-2.C | 33 +++
 7 files changed, 120 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/gomp/usm-4.C
 create mode 100644 gcc/testsuite/g++.dg/gomp/usm-5.C
 create mode 100644 libgomp/testsuite/libgomp.c++/usm-2.C

diff --git a/gcc/ChangeLog.omp b/gcc/ChangeLog.omp
index 68d5eea01a7..de92af2244f 100644
--- a/gcc/ChangeLog.omp
+++ b/gcc/ChangeLog.omp
@@ -1,3 +1,7 @@
+2022-10-25  Abid Qadeer  
+
+	* omp-low.cc (usm_transform): Handle operator new with alignment.
+
 2022-10-24  Andrew Stubbs  
 
 	* tree-vect-data-refs.cc (vect_analyze_data_refs): Workaround an
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index f171181e2c4..b5b2681b654 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -16339,6 +16339,7 @@ usm_transform (gimple_stmt_iterator *gsi_p, bool *,
   {
 	gcall *gs = as_a  (stmt);
 	tree fndecl = gimple_call_fndecl (gs);
+	unsigned int args = gimple_call_num_args (gs);
 	if (fndecl)
 	  {
 	tree allocator = build_int_cst (pointer_sized_int_node,
@@ -16347,7 +16348,8 @@ usm_transform (gimple_stmt_iterator *gsi_p, bool *,
 	if ((strcmp (name, "malloc") == 0)
 		 || (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
 		 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MALLOC)
-		 || DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl)
+		 || (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl)
+		 && args == 1)
 		 || strcmp (name, "omp_target_alloc") == 0)
 	  {
 		  tree omp_alloc_type
@@ -16361,7 +16363,9 @@ usm_transform (gimple_stmt_iterator *gsi_p, bool *,
 		gimple_set_location (g, gimple_location (stmt));
 		gsi_replace (gsi_p, g, true);
 	  }
-	else if (strcmp (name, "aligned_alloc") == 0)
+	else if ((strcmp (name, "aligned_alloc") == 0)
+		  || (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl)
+			  && args == 2))
 	  {
 		/*  May be we can also use this for new operator with
 		std::align_val_t parameter.  */
@@ -16372,8 +16376,12 @@ usm_transform (gimple_stmt_iterator *gsi_p, bool *,
 	  NULL_TREE);
 		tree repl = build_fn_decl ("omp_aligned_alloc",
 	   omp_alloc_type);
-		tree align = gimple_call_arg (gs, 0);
-		tree size = gimple_call_arg (gs, 1);
+		int align_arg
+		  = DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl) ? 1: 0;
+		int size_arg
+		  = DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl) ? 0: 1;
+		tree align = gimple_call_arg (gs, align_arg);
+		tree size = gimple_call_arg (gs, size_arg);
 		gimple *g = gimple_build_call (repl, 3, align, size,
 	   allocator);
 		gimple_call_set_lhs (g, gimple_call_lhs (gs));
diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp
index 677a4c6ee12..d5548ebff3b 100644
--- a/gcc/testsuite/ChangeLog.omp
+++ b/gcc/testsuite/ChangeLog.omp
@@ -1,3 +1,8 @@
+2022-10-25  Abid Qadeer  
+
+	* g++.dg/gomp/usm-4.C: New test.
+	* g++.dg/gomp/usm-5.C: New test.
+
 2022-10-24  Tobias Burnus  
 
 	* g++.dg/ext/unroll-1.C: Change 'cunrolli' to 'cunrolli1' in
diff --git a/gcc/testsuite/g++.dg/gomp/usm-4.C b/gcc/testsuite/g++.dg/gomp/usm-4.C
new file mode 100644
index 000..9096c445363
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/usm-4.C
@@ -0,0 +1,32 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fopenmp -fdump-tree-usm_transform" }
+
+#pragma omp requires unified_shared_memory
+
+struct t1
+{
+  int a;
+  int b;
+};
+
+typedef unsigned char uint8_t;
+
+void
+foo (__SIZE_TYPE__ x, __SIZE_TYPE__ y)
+{
+  uint8_t *p1 = new (std::align_val_t(128)) uint8_t;
+  uint8_t *p2 = new (std::align_val_t(128)) uint8_t[40];
+  t1 *p3 = new (std::align_val_t(128)) t1;
+  t1 *p4 = new (std::align_val_t(128)) t1[y];
+  delete p1;
+  delete p3;
+  delete [] p2;
+  delete [] p4;
+}
+
+/* { dg-final { scan-tree-dump-times "omp_aligned_alloc \\(128, 1, 10\\)" 1 "usm_transform"  } } */
+/* { dg-final { scan-tree-dump-times "omp_aligned_alloc 

Re: [PATCH 1/2] Allow subtarget customization of CC1_SPEC

2022-10-26 Thread Sebastian Huber

On 04/10/2022 11:47, Sebastian Huber wrote:

On 08/09/2022 07:33, Sebastian Huber wrote:

On 04/08/2022 15:02, Sebastian Huber wrote:

On 22/07/2022 15:02, Sebastian Huber wrote:

gcc/ChangeLog:

* gcc.cc (SUBTARGET_CC1_SPEC): Define if not defined.
(CC1_SPEC): Define to SUBTARGET_CC1_SPEC.
* config/arm/arm.h (CC1_SPEC): Remove.
* config/arc/arc.h (CC1_SPEC): Append SUBTARGET_CC1_SPEC.
* config/cris/cris.h (CC1_SPEC): Likewise.
* config/frv/frv.h (CC1_SPEC): Likewise.
* config/i386/i386.h (CC1_SPEC): Likewise.
* config/ia64/ia64.h (CC1_SPEC): Likewise.
* config/lm32/lm32.h (CC1_SPEC): Likewise.
* config/m32r/m32r.h (CC1_SPEC): Likewise.
* config/mcore/mcore.h (CC1_SPEC): Likewise.
* config/microblaze/microblaze.h: Likewise.
* config/nds32/nds32.h (CC1_SPEC): Likewise.
* config/nios2/nios2.h (CC1_SPEC): Likewise.
* config/pa/pa.h (CC1_SPEC): Likewise.
* config/rs6000/sysv4.h (CC1_SPEC): Likewise.
* config/rx/rx.h (CC1_SPEC): Likewise.
* config/sparc/sparc.h (CC1_SPEC): Likewise.


Could someone please have a look at this patch set?


Ping.


Would someone mind having a look at this patch set? If there is a better 
approach to customize the default TLS model, then please let me know.


It would be nice if someone could review the patch before the Stage 1 
ends at November 13th.


--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/


Re: [PATCH] [x86_64] Zhaoxin lujiazui enablement

2022-10-26 Thread Mayshao-oc


Hi Martin:
Thanks for your patch,  I comment the questions below.

> Hello.

> I noticed this patch set which is kind of related to 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107364.

> And I have a couple of questions:

>1) I noticed you drop AVX and F16C features for the newly added "lujiazui". 
>Why do you need it?
>  I would expect these features would be properly detected by cpuid?

Yes, these features could be detected by cpuid, and in respect of 
functionality, these features are ok, but in respect of performance, these 
features need further improvement, so we decide to drop it now, and add these 
features back when performance meet our expectation.

> 2) If you really need it, can you please test for me the attached patch? It 
> should come up
>  with a new function.

I have tested the patch, It's ok.

> 3) Have question about:

> else if (vendor == signature_CENTAUR_ebx && family < 0x07)
>cpu_model->__cpu_vendor = VENDOR_CENTAUR;
> else if (vendor == signature_SHANGHAI_ebx
>   || vendor == signature_CENTAUR_ebx)

> Are there any signature_CENTAUR_ebx models with family == 0x7 ?
> Similarly, are there any signature_SHANGHAI_ebx modes with family < 0x7 ?

Yes, both cases exist in our products.

> Thanks,
> Martin

BR
Mayshao


Re: [PATCH] RISC-V: Fix a mistake in previous patch.

2022-10-26 Thread Kito Cheng via Gcc-patches
Committed with title tweak, thanks

On Tue, Oct 25, 2022 at 9:53 PM  wrote:
>
> From: Ju-Zhe Zhong 
>
>  I noticed that I have made a mistake in previous patch:
>  
> https://patchwork.sourceware.org/project/gcc/patch/20220817071950.271762-1-juzhe.zh...@rivai.ai/
>
>  The previous statement before this patch:
>  bool need_barrier_p = (get_frame_size () + 
> cfun->machine->frame.arg_pointer_offset) != 0;
>
>  However, I changed it in the previous patch:
>  bool need_barrier_p = known_ne (get_frame_size (), 
> cfun->machine->frame.arg_pointer_offset);
>  This is incorrect.
>
>  Now, I correct this statement in this patch.
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.cc (riscv_expand_epilogue): Fix statement.
>
> ---
>  gcc/config/riscv/riscv.cc | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 08354a19c05..50ef38438a2 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -5028,8 +5028,8 @@ riscv_expand_epilogue (int style)
>rtx insn;
>
>/* We need to add memory barrier to prevent read from deallocated stack.  
> */
> -  bool need_barrier_p
> -= known_ne (get_frame_size (), cfun->machine->frame.arg_pointer_offset);
> +  bool need_barrier_p = known_ne (get_frame_size ()
> +  + cfun->machine->frame.arg_pointer_offset, 
> 0);
>
>if (cfun->machine->naked_p)
>  {
> --
> 2.36.1
>


Re: [PATCH] RISC-V: Support load/store in mov pattern for RVV modes.

2022-10-26 Thread Kito Cheng via Gcc-patches
Verified and committed to trunk, thanks!
And don't forgot changelog next time :P

On Mon, Oct 24, 2022 at 10:09 AM  wrote:
>
> From: Ju-Zhe Zhong 
>
> ---
>  gcc/config.gcc|   2 +-
>  gcc/config/riscv/constraints.md   |  22 +
>  gcc/config/riscv/predicates.md|  23 ++
>  gcc/config/riscv/riscv-protos.h   |  14 +
>  gcc/config/riscv/riscv-v.cc   | 180 
>  .../riscv/riscv-vector-builtins-bases.cc  |  14 +-
>  gcc/config/riscv/riscv.cc |  67 ++-
>  gcc/config/riscv/riscv.h  |   2 +
>  gcc/config/riscv/riscv.md |   9 +-
>  gcc/config/riscv/t-riscv  |   4 +
>  gcc/config/riscv/vector-iterators.md  |  58 +++
>  gcc/config/riscv/vector.md| 279 -
>  .../gcc.target/riscv/rvv/base/mov-1.c | 179 
>  .../gcc.target/riscv/rvv/base/mov-10.c| 385 ++
>  .../gcc.target/riscv/rvv/base/mov-11.c| 385 ++
>  .../gcc.target/riscv/rvv/base/mov-12.c| 159 
>  .../gcc.target/riscv/rvv/base/mov-13.c|  14 +
>  .../gcc.target/riscv/rvv/base/mov-2.c | 153 +++
>  .../gcc.target/riscv/rvv/base/mov-3.c | 127 ++
>  .../gcc.target/riscv/rvv/base/mov-4.c | 101 +
>  .../gcc.target/riscv/rvv/base/mov-5.c |  66 +++
>  .../gcc.target/riscv/rvv/base/mov-6.c |  53 +++
>  .../gcc.target/riscv/rvv/base/mov-7.c |  13 +
>  .../gcc.target/riscv/rvv/base/mov-8.c |  96 +
>  .../gcc.target/riscv/rvv/base/mov-9.c |  44 ++
>  25 files changed, 2421 insertions(+), 28 deletions(-)
>  create mode 100644 gcc/config/riscv/riscv-v.cc
>  create mode 100644 gcc/config/riscv/vector-iterators.md
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-10.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-11.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-12.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-13.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-3.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-4.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-5.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-6.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-7.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-8.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/mov-9.c
>
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 3826ae42803..0232e572a99 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -515,7 +515,7 @@ pru-*-*)
> ;;
>  riscv*)
> cpu_type=riscv
> -   extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o 
> riscv-shorten-memrefs.o riscv-selftests.o"
> +   extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o 
> riscv-shorten-memrefs.o riscv-selftests.o riscv-v.o"
> extra_objs="${extra_objs} riscv-vector-builtins.o 
> riscv-vector-builtins-shapes.o riscv-vector-builtins-bases.o"
> d_target_objs="riscv-d.o"
> extra_headers="riscv_vector.h"
> diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
> index 8997284f32e..951dcc52d6b 100644
> --- a/gcc/config/riscv/constraints.md
> +++ b/gcc/config/riscv/constraints.md
> @@ -128,3 +128,25 @@
>"POLY_INT"
>(and (match_code "const_poly_int")
> (match_test "known_eq (rtx_to_poly_int64 (op), 
> BYTES_PER_RISCV_VECTOR)")))
> +
> +(define_constraint "vu"
> +  "A undefined vector value."
> +  (and (match_code "unspec")
> +   (match_test "XINT (op, 1) == UNSPEC_VUNDEF")))
> +
> +(define_constraint "vi"
> +  "A vector 5-bit signed immediate."
> +  (and (match_code "const_vector")
> +   (match_test "riscv_vector::const_vec_all_same_in_range_p (op, -16, 
> 15)")))
> +
> +(define_constraint "Wc0"
> +  "@internal
> + A constraint that matches a vector of immediate all zeros."
> + (and (match_code "const_vector")
> +  (match_test "op == CONST0_RTX (GET_MODE (op))")))
> +
> +(define_constraint "Wc1"
> +  "@internal
> + A constraint that matches a vector of immediate all ones."
> + (and (match_code "const_vector")
> +  (match_test "op == CONSTM1_RTX (GET_MODE (op))")))
> diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
> index 5e149b3a95f..e2bfafe8150 100644
> --- a/gcc/config/riscv/predicates.md
> +++ b/gcc/config/riscv/predicates.md
> @@ -262,3 +262,26 @@
>
> return true;
>  })
> +
> +;; Predicates for the V extension.
> +(define_special_predicate "vector_length_operand"
> +  (ior (match_operand 0 "pmode_register_operand")
> +   (match_operand 0 "const_csr_operand")))
> +
> 

Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when popping if necessary

2022-10-26 Thread Andrea Corallo via Gcc-patches
Richard Earnshaw  writes:

> On 27/09/2022 16:24, Kyrylo Tkachov via Gcc-patches wrote:
>> 
>>> -Original Message-
>>> From: Andrea Corallo 
>>> Sent: Tuesday, September 27, 2022 11:06 AM
>>> To: Kyrylo Tkachov 
>>> Cc: Andrea Corallo via Gcc-patches ; Richard
>>> Earnshaw ; nd 
>>> Subject: Re: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>> popping if necessary
>>>
>>> Kyrylo Tkachov  writes:
>>>
 Hi Andrea,

> -Original Message-
> From: Gcc-patches  bounces+kyrylo.tkachov=arm@gcc.gnu.org> On Behalf Of Andrea
> Corallo via Gcc-patches
> Sent: Friday, August 12, 2022 4:34 PM
> To: Andrea Corallo via Gcc-patches 
> Cc: Richard Earnshaw ; nd 
> Subject: [PATCH 9/15] arm: Set again stack pointer as CFA reg when
>>> popping
> if necessary
>
> Hi all,
>
> this patch enables 'arm_emit_multi_reg_pop' to set again the stack
> pointer as CFA reg when popping if this is necessary.
>

  From what I can tell from similar functions this is correct, but could you
>>> elaborate on why this change is needed for my understanding please?
 Thanks,
 Kyrill
>>>
>>> Hi Kyrill,
>>>
>>> sure, if the frame pointer was set, than it is the current CFA register.
>>> If we request to adjust the current CFA register offset indicating it
>>> being SP (while it's actually FP) that is indeed not correct and the
>>> incoherence we will be detected by an assertion in the dwarf emission
>>> machinery.
>> Thanks,  the patch is ok
>> Kyrill
>> 
>>>
>>> Best Regards
>>>
>>>Andrea
>
> Hmm, wait.  Why would a multi-reg pop be updating the stack pointer?

Hi Richard,

not sure I understand, isn't any pop updating SP by definition?

BR

  Andrea


Re: [PATCH] RISC-V: Fix typo.

2022-10-26 Thread Kito Cheng via Gcc-patches
Committed with title tweak , thanks

On Mon, Oct 24, 2022 at 10:24 PM  wrote:
>
> From: Ju-Zhe Zhong 
>
> gcc/ChangeLog:
>
> * config/riscv/riscv-modes.def (ADJUST_BYTESIZE): Fix typo.
>
> ---
>  gcc/config/riscv/riscv-modes.def | 46 
>  1 file changed, 23 insertions(+), 23 deletions(-)
>
> diff --git a/gcc/config/riscv/riscv-modes.def 
> b/gcc/config/riscv/riscv-modes.def
> index 95f69e87e23..ea88442e117 100644
> --- a/gcc/config/riscv/riscv-modes.def
> +++ b/gcc/config/riscv/riscv-modes.def
> @@ -71,29 +71,29 @@ ADJUST_BYTESIZE (VNx64BI, riscv_vector_chunks * 
> riscv_bytes_per_vector_chunk);
>
>  /*
> | Mode| MIN_VLEN=32 | MIN_VLEN=32 | MIN_VLEN=64 | MIN_VLEN=64 |
> -   | | LMUL|  SEW/LMUL   | LMUL| SEW/LMUL|
> -   | VNx1QI  | MF4 |  32 | MF8 | 64  |
> -   | VNx2QI  | MF2 |  16 | MF4 | 32  |
> -   | VNx4QI  | M1  |  8  | MF2 | 16  |
> -   | VNx8QI  | M2  |  4  | M1  | 8   |
> -   | VNx16QI | M4  |  2  | M2  | 4   |
> -   | VNx32QI | M8  |  1  | M4  | 2   |
> -   | VNx64QI | N/A |  N/A| M8  | 1   |
> -   | VNx1(HI|HF) | MF2 |  32 | MF4 | 64  |
> -   | VNx2(HI|HF) | M1  |  16 | MF2 | 32  |
> -   | VNx4(HI|HF) | M2  |  8  | M1  | 16  |
> -   | VNx8(HI|HF) | M4  |  4  | M2  | 8   |
> -   | VNx16(HI|HF)| M8  |  2  | M4  | 4   |
> -   | VNx32(HI|HF)| N/A |  N/A| M8  | 2   |
> -   | VNx1(SI|SF) | M1  |  32 | MF2 | 64  |
> -   | VNx2(SI|SF) | M2  |  16 | M1  | 32  |
> -   | VNx4(SI|SF) | M4  |  8  | M2  | 16  |
> -   | VNx8(SI|SF) | M8  |  4  | M4  | 8   |
> -   | VNx16(SI|SF)| N/A |  N/A| M8  | 4   |
> -   | VNx1(DI|DF) | N/A |  N/A| M1  | 64  |
> -   | VNx2(DI|DF) | N/A |  N/A| M2  | 32  |
> -   | VNx4(DI|DF) | N/A |  N/A| M4  | 16  |
> -   | VNx8(DI|DF) | N/A |  N/A| M8  | 8   |
> +   | | LMUL| SEW/LMUL| LMUL| SEW/LMUL|
> +   | VNx1QI  | MF4 | 32  | MF8 | 64  |
> +   | VNx2QI  | MF2 | 16  | MF4 | 32  |
> +   | VNx4QI  | M1  | 8   | MF2 | 16  |
> +   | VNx8QI  | M2  | 4   | M1  | 8   |
> +   | VNx16QI | M4  | 2   | M2  | 4   |
> +   | VNx32QI | M8  | 1   | M4  | 2   |
> +   | VNx64QI | N/A | N/A | M8  | 1   |
> +   | VNx1(HI|HF) | MF2 | 32  | MF4 | 64  |
> +   | VNx2(HI|HF) | M1  | 16  | MF2 | 32  |
> +   | VNx4(HI|HF) | M2  | 8   | M1  | 16  |
> +   | VNx8(HI|HF) | M4  | 4   | M2  | 8   |
> +   | VNx16(HI|HF)| M8  | 2   | M4  | 4   |
> +   | VNx32(HI|HF)| N/A | N/A | M8  | 2   |
> +   | VNx1(SI|SF) | M1  | 32  | MF2 | 64  |
> +   | VNx2(SI|SF) | M2  | 16  | M1  | 32  |
> +   | VNx4(SI|SF) | M4  | 8   | M2  | 16  |
> +   | VNx8(SI|SF) | M8  | 4   | M4  | 8   |
> +   | VNx16(SI|SF)| N/A | N/A | M8  | 4   |
> +   | VNx1(DI|DF) | N/A | N/A | M1  | 64  |
> +   | VNx2(DI|DF) | N/A | N/A | M2  | 32  |
> +   | VNx4(DI|DF) | N/A | N/A | M4  | 16  |
> +   | VNx8(DI|DF) | N/A | N/A | M8  | 8   |
>  */
>
>  /* Define RVV modes whose sizes are multiples of 64-bit chunks.  */
> --
> 2.36.1
>


[PATCH] c++: Fix excess precision related ICE on invalid binop [PR107382, PR107383]

2022-10-26 Thread Jakub Jelinek via Gcc-patches
Hi!

The following tests ICE in the gcc_assert (common); in cp_build_binary_op.
I've missed that while for * common is set always, while for +, - and /
it is in some cases not.
If it is not, then
  if (!result_type
  && arithmetic_types_p
  && (shorten || common || short_compare))
condition is false, then the following
  if (may_need_excess_precision
  && (orig_type0 != type0 || orig_type1 != type1)
  && build_type == NULL_TREE)
would fail the assertion there and if there wouldn't be excess precision,
  if (code == SPACESHIP_EXPR)
would be false (for SPACESHIP_EXPR we always have build_type set like for
other comparisons) and then trigger
  if (!result_type)
{
  if (complain & tf_error)
{
  binary_op_rich_location richloc (location,
   orig_op0, orig_op1, true);
  error_at (,
"invalid operands of types %qT and %qT to binary %qO",
TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code);
}
  return error_mark_node;
}
So, if result_type is NULL, we don't really need to compute
semantic_result_type because nothing will use it anyway and can get
fall through into the error/return error_mark_node; case.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2022-10-26  Jakub Jelinek  

PR c++/107382
PR c++/107383
* typeck.cc (cp_build_binary_op): Don't compute semantic_result_type
if result_type is NULL.

* g++.dg/diagnostic/bad-binary-ops2.C: New test.

--- gcc/cp/typeck.cc.jj 2022-10-25 10:37:28.008533040 +0200
+++ gcc/cp/typeck.cc2022-10-25 19:18:20.951846806 +0200
@@ -6179,7 +6179,8 @@ cp_build_binary_op (const op_location_t
 }
   if (may_need_excess_precision
   && (orig_type0 != type0 || orig_type1 != type1)
-  && build_type == NULL_TREE)
+  && build_type == NULL_TREE
+  && result_type)
 {
   gcc_assert (common);
   semantic_result_type = cp_common_type (orig_type0, orig_type1);
--- gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C.jj2022-10-25 
19:49:49.190198057 +0200
+++ gcc/testsuite/g++.dg/diagnostic/bad-binary-ops2.C   2022-10-25 
20:10:35.266264891 +0200
@@ -0,0 +1,26 @@
+// PR c++/107382
+// PR c++/107383
+// { dg-do compile }
+// { dg-options "-O2 -fexcess-precision=standard" }
+
+void
+foo ()
+{
+  float t[2] = { 1, 2 };
+  int const *s = 0;
+  t[1] / s;// { dg-error "invalid operands of types 'float' and 'const 
int\\\*' to binary 'operator/'" }
+}
+
+void
+bar ()
+{
+  float t[2] = { 1, 2 };
+  int const *s[2] = { 0, 0 };
+  t[1] / s[0]; // { dg-error "invalid operands of types 'float' and 'const 
int\\\*' to binary 'operator/'" }
+}
+
+void
+baz (float a, int* b)
+{
+  a -= b;  // { dg-error "invalid operands of types 'float' and 'int\\\*' 
to binary 'operator-'" }
+}

Jakub



Re: [PATCH Rust front-end v3 01/46] Use DW_ATE_UTF for the Rust 'char' type

2022-10-26 Thread Jakub Jelinek via Gcc-patches
On Wed, Oct 26, 2022 at 10:17:26AM +0200, arthur.co...@embecosm.com wrote:
> @@ -25201,6 +25215,13 @@ gen_compile_unit_die (const char *filename)
>  }
>else if (strcmp (language_string, "GNU F77") == 0)
>  language = DW_LANG_Fortran77;
> +  else if (strcmp (language_string, "GNU Rust") == 0)
> +{
> +  if (dwarf_version >= 5 || !dwarf_strict)
> + language = DW_LANG_Rust;
> +  else
> + language = DW_LANG_Rust_old;
> +}

I must say I don't understand nor like this DW_LANG_Rust_old stuff at all.
Other languages don't do similar dances.
Look for D, or Go.  Neither of them has any non-standard lang code as
fallback, they use the DWARF assigned DW_LANG_* code, and DW_LANG_C as
fallback.  On most arches, DWARF 5 is the default anyway, or non-strict
DWARF at least.  Where neither is enabled because of prehistoric or buggy
DWARF consumers, it is unlikely they'd handle Rust sanely anyway.
Just follow what Go does in the same function.

Jakub



[PATCH Rust front-end v3 46/46] gccrs: Add README, CONTRIBUTING and compiler logo

2022-10-26 Thread arthur . cohen
From: Philip Herron 

We still need to write out documentation section but these README's will
help in the mean time.
---
 gcc/rust/CONTRIBUTING.md | 130 +++
 gcc/rust/README.md   | 264 +++
 gcc/rust/logo.png| Bin 0 -> 70864 bytes
 3 files changed, 394 insertions(+)
 create mode 100644 gcc/rust/CONTRIBUTING.md
 create mode 100644 gcc/rust/README.md
 create mode 100644 gcc/rust/logo.png

diff --git a/gcc/rust/CONTRIBUTING.md b/gcc/rust/CONTRIBUTING.md
new file mode 100644
index 000..20e499c29e1
--- /dev/null
+++ b/gcc/rust/CONTRIBUTING.md
@@ -0,0 +1,130 @@
+## How to contribute to GCC Rust
+
+ **Did you find a bug?**
+
+* **Ensure the bug was not already reported** by searching on GitHub under 
[Issues](https://github.com/Rust-GCC/gccrs/issues).
+
+* If you're unable to find an open issue addressing the problem, [open a new 
one](https://github.com/Rust-GCC/gccrs/issues/new). 
+  Be sure to include a **title and clear description**, as much relevant 
information as possible, and a **code sample** 
+  or an **executable test case** demonstrating the expected behavior that is 
not occurring.
+
+ **Do you want to submit a patch?**
+
+* Open a new GitHub pull request with the patch.
+
+* Ensure the PR description clearly describes the problem and solution. 
Include the relevant issue number if applicable.
+
+* Before submitting, GCC development requires copyright assignment or the 
Developer's Certificate of Origin sign-off.
+   Please see the [Contributing to GCC](https://gcc.gnu.org/contribute.html) 
guide or [Developer's Certificate of Origin (DCO) 
Sign-off](https://gcc.gnu.org/dco.html) guide.
+
+* Patches sent to the [`gcc-rust` mailing 
list](https://gcc.gnu.org/mailman/listinfo/gcc-rust) are likewise welcome.
+These will be imported into a GitHub PR to follow the normal review process, 
+and the link to the GitHub PR sent to the submitter.
+
+ **Do you intend to add a new feature or change an existing one?**
+
+* Suggest your change in the [Zulip](https://gcc-rust.zulipchat.com/) and 
start writing code.
+
+* Do not open an issue on GitHub until you have collected positive feedback 
about the change. 
+  GitHub issues are primarily intended for bug reports and fixes.
+
+ **Do you have questions about the source code?**
+
+* Ask any question about how to use GCCRS in 
[Zulip](https://gcc-rust.zulipchat.com/).
+
+### **PR Policy**
+
+* The PR policy: Everything has to go through a PR
+  - An exception to this rule will be the merge commits of updating the repo 
against upstream GCC
+
+* Reviewers/Maintainers of the project (aka people who have bors rights) 
should be pinged for reviews/questions.
+
+* A PR can have one or several commits (split should have a technical/logical 
reason, ie. no fixup-ish commit)
+
+* Avoid PR's with merge commit unless there's a good reason
+
+* Where possible please add test cases to `gcc/testsuite/rust/` for all PRs. 
+  Some issues may not be testable via dejagnu/automation such as debug dump 
changes.
+
+* Follow the [GCC coding style](https://gcc.gnu.org/codingconventions.html) 
(see `clang-format` below).
+
+* PRs won't be merged until the build and tests pass.
+
+* Please take the time to create good git commit messages. 
+  See the existing format of them in the git log or refer to something like: 
https://chris.beams.io/posts/git-commit/
+
+ Running `clang-format` locally
+
+* on all files using python scripts
+... corresponding to what the _Clang Format Lint_ 
(`.github/workflows/clang-format.yml`) 
+is doing, with `clang-format-10` being available locally, and avoiding the 
Docker overhead.
+
+```shell
+$ wget 
'https://github.com/DoozyX/clang-format-lint-action/raw/v0.11/run-clang-format.py'
+$ cp contrib/clang-format .clang-format
+$ python3 run-clang-format.py --clang-format-executable clang-format-10 
--recursive --extensions h,cc gcc/rust/
+```
+
+* on a given patch using python scripts
+See the [clang-format 
documentation](https://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting)
 :
+
+$ git diff -U0 --no-color HEAD^ | clang-format-diff.py -i -p1
+
+* using `git` interface
+
+At least on Debian and its derivative, each `clang-format` packages also comes
+with `git-clang-format` command that can be used easily. It applies on staged
+changes, and any modification can be seen as unstaged changes:
+
+```diff
+$ git diff --cached
+diff --git a/gcc/rust/rust-abi.h b/gcc/rust/rust-abi.h
+index bd3043295ce..9559374ce60 100644
+--- a/gcc/rust/rust-abi.h
 b/gcc/rust/rust-abi.h
+@@ -22,10 +22,10 @@ namespace Rust {
+ enum ABI
+ {
+   UNKNOWN,
+-  RUST,
++ RUST,
+   INTRINSIC,
+   C,
+-  CDECL,
++ CDECL,
+   STDCALL,
+   FASTCALL,
+ };
+ 
+gccrs/gcc/rust on  dkm/clang_format [$!+?]
+❯ git clang-format
+changed files:
+gcc/rust/rust-abi.h
+ 
+gccrs/gcc/rust on  dkm/clang_format [$!+?]
+$ git diff rust-abi.h
+diff --git 

[PATCH Rust front-end v3 44/46] gccrs: Add compiler driver

2022-10-26 Thread arthur . cohen
From: Philip Herron 

Our compiler driver is pretty simple so far, the key piece to enforce is
that a compilation unit in Rust is the whole crate so the process for
compiling rust means pointing the compiler at the main entry point such as
src/lib.rs or src/main.rs where the expansion pass takes over loading the
other source files to include them in the crate.
---
 gcc/rust/rustspec.cc | 191 +++
 1 file changed, 191 insertions(+)
 create mode 100644 gcc/rust/rustspec.cc

diff --git a/gcc/rust/rustspec.cc b/gcc/rust/rustspec.cc
new file mode 100644
index 000..b05f8ae5454
--- /dev/null
+++ b/gcc/rust/rustspec.cc
@@ -0,0 +1,191 @@
+/* rustspec.c -- Specific flags and argument handling of the gcc Rust front 
end.
+   Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "opts.h"
+
+// satisfy intellisense
+#include "options.h"
+
+/* This bit is set if we saw a `-xfoo' language specification.  */
+#define LANGSPEC (1 << 1)
+/* This bit is set if they did `-lc'.  */
+#define WITHLIBC (1 << 2)
+/* Skip this option.  */
+#define SKIPOPT (1 << 3)
+
+void
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+ unsigned int *in_decoded_options_count,
+ int *in_added_libraries)
+{
+  unsigned int i, j;
+
+  /* The new argument list will be contained in this.  */
+  struct cl_decoded_option *new_decoded_options;
+
+  /* "-lc" if it appears on the command line.  */
+  const struct cl_decoded_option *saw_libc = 0;
+
+  /* An array used to flag each argument that needs a bit set for
+ LANGSPEC or WITHLIBC.  */
+  int *args;
+
+  /* True if we saw -static.  */
+  int static_link = 0;
+
+  /* True if we should add -shared-libgcc to the command-line.  */
+  int shared_libgcc = 1;
+
+  /* The total number of arguments with the new stuff.  */
+  unsigned int argc;
+
+  /* The argument list.  */
+  struct cl_decoded_option *decoded_options;
+
+  /* The number of libraries added in.  */
+  int added_libraries;
+
+  /* The total number of arguments with the new stuff.  */
+  int num_args = 1;
+
+  /* Whether the -o option was used.  */
+  bool saw_opt_o = false;
+
+  /* The first input file with an extension of .rs.  */
+  const char *first_rust_file = NULL;
+
+  argc = *in_decoded_options_count;
+  decoded_options = *in_decoded_options;
+  added_libraries = *in_added_libraries;
+
+  args = XCNEWVEC (int, argc);
+
+  for (i = 1; i < argc; i++)
+{
+  const char *arg = decoded_options[i].arg;
+
+  switch (decoded_options[i].opt_index)
+   {
+   case OPT_l:
+ if (strcmp (arg, "c") == 0)
+   args[i] |= WITHLIBC;
+ break;
+
+   case OPT_o:
+ saw_opt_o = true;
+ break;
+
+   case OPT_static:
+ static_link = 1;
+ break;
+
+   case OPT_static_libgcc:
+ shared_libgcc = 0;
+ break;
+
+   case OPT_SPECIAL_input_file:
+ if (first_rust_file == NULL)
+   {
+ int len;
+
+ len = strlen (arg);
+ if (len > 3 && strcmp (arg + len - 3, ".rs") == 0)
+   first_rust_file = arg;
+   }
+ else
+   {
+ // FIXME: ARTHUR: Do we want to error here? If there's already one
+ // file?
+ // How do we error here? Do we want to instead just handle that in
+ // the session manager?
+   }
+
+ break;
+   }
+}
+
+/* There's no point adding -shared-libgcc if we don't have a shared
+   libgcc.  */
+#ifndef ENABLE_SHARED_LIBGCC
+  shared_libgcc = 0;
+#endif
+
+  /* Make sure to have room for the trailing NULL argument.  */
+  num_args = argc + shared_libgcc * 5 + 10;
+  new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
+
+  i = 0;
+  j = 0;
+
+  /* Copy the 0th argument, i.e., the name of the program itself.  */
+  new_decoded_options[j++] = decoded_options[i++];
+
+  /* NOTE: We start at 1 now, not 0.  */
+  while (i < argc)
+{
+  new_decoded_options[j] = decoded_options[i];
+
+  if (!saw_libc && (args[i] & WITHLIBC))
+   {
+ --j;
+ saw_libc = _options[i];
+   }
+
+  if ((args[i] & SKIPOPT) != 0)
+   --j;
+
+   

[PATCH Rust front-end v3 43/46] gccrs: Add lang.opt

2022-10-26 Thread arthur . cohen
From: Philip Herron 

We have some rust specific langugage options note -fwrapv is enabled by
default in the code. We are trying to respect options such as
-Wunused-result which we get by porting over c++ no-discard for rust's
must-use attribute, so we have enabled these by default directly here.
---
 gcc/rust/lang.opt | 118 ++
 1 file changed, 118 insertions(+)
 create mode 100644 gcc/rust/lang.opt

diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
new file mode 100644
index 000..1130999d277
--- /dev/null
+++ b/gcc/rust/lang.opt
@@ -0,0 +1,118 @@
+; Options for the Rust front end.
+; Copyright (C) 2003-2022 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+; 
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+; for more details.
+; 
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; .
+
+; See the GCC internals manual for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+; Describes command-line options used by this frontend
+
+Language
+Rust
+
+I
+Rust Joined Separate
+; Documented in c.opt
+
+L
+Rust Joined Separate
+; Not documented
+
+Wall
+Rust
+; Documented in c.opt
+
+Wunused-variable
+Rust Var(warn_unused_variable) Warning
+; documented in common.opt
+
+Wunused-const-variable
+Rust Warning Alias(Wunused-const-variable=, 2, 0)
+Warn when a const variable is unused.
+
+Wunused-const-variable=
+Rust Joined RejectNegative UInteger Var(warn_unused_const_variable) Warning 
LangEnabledBy(Rust,Wunused-variable, 1, 0) IntegerRange(0, 2)
+Warn when a const variable is unused.
+
+Wunused-result
+Rust Var(warn_unused_result) Warning
+Warn if a caller of a function, marked with attribute warn_unused_result, does 
not use its return value.
+
+frust-crate=
+Rust Joined RejectNegative
+-frust-crate= Set the crate name for the compilation
+
+frust-debug
+Rust Var(flag_rust_debug)
+Dump various Rust front end internals.
+
+frust-dump-
+Rust Joined RejectNegative
+-frust-dump- Dump Rust frontend internal information.
+
+frust-max-recursion-depth=
+Rust RejectNegative Type(int) Var(rust_max_recursion_depth) Init(64)
+-frust-max-recursion-depth=integer
+
+frust-mangling=
+Rust Joined RejectNegative Enum(frust_mangling) Var(flag_rust_mangling)
+-frust-mangling=[legacy|v0] Choose which version to use for name mangling
+
+Enum
+Name(frust_mangling) Type(int) UnknownError(unknown rust mangling option %qs)
+
+EnumValue
+Enum(frust_mangling) String(legacy) Value(0)
+
+EnumValue
+Enum(frust_mangling) String(v0) Value(1)
+
+frust-cfg=
+Rust Joined RejectNegative
+-frust-cfg= Set a config expansion option
+
+frust-edition=
+Rust Joined RejectNegative Enum(frust_edition) Var(flag_rust_edition)
+-frust-edition=[2015|2018|2021] Choose which edition to use when 
compiling rust code
+
+Enum
+Name(frust_edition) Type(int) UnknownError(unknown rust edition %qs)
+
+EnumValue
+Enum(frust_edition) String(2015) Value(0)
+
+EnumValue
+Enum(frust_edition) String(2018) Value(1)
+
+EnumValue
+Enum(frust_edition) String(2021) Value(2)
+
+frust-embed-metadata
+Rust Var(flag_rust_embed_metadata)
+Flag to enable embeding metadata directly into object files
+
+frust-metadata-output=
+Rust Joined RejectNegative
+-frust-metadata-output=  Path to output crate metadata
+
+o
+Rust Joined Separate
+; Documented in common.opt
+
+; This comment is to ensure we retain the blank line above.
-- 
2.37.2



[PATCH Rust front-end v3 42/46] gccrs: Add lang-spec.h

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This specifies the extensions of the Rust language.
---
 gcc/rust/lang-specs.h | 26 ++
 1 file changed, 26 insertions(+)
 create mode 100644 gcc/rust/lang-specs.h

diff --git a/gcc/rust/lang-specs.h b/gcc/rust/lang-specs.h
new file mode 100644
index 000..eed28b1eb06
--- /dev/null
+++ b/gcc/rust/lang-specs.h
@@ -0,0 +1,26 @@
+/* lang-specs.h -- gcc driver specs for Rust frontend.
+   Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   .  */
+
+/* This is the contribution to the `default_compilers' array in gcc.cc
+   for the Rust language.  */
+
+{".rs", "@rust", 0, 1, 0},
+  {"@rust",
+   "rust1 %i %(cc1_options) %{I*} %{L*} %D %{!fsyntax-only:%(invoke_as)}", 0, 
1,
+   0},
-- 
2.37.2



[PATCH Rust front-end v3 39/46] gccrs: These are wrappers ported from reusing gccgo

2022-10-26 Thread arthur . cohen
From: Philip Herron 

The wrappers over linemap and location will eventually disappear here but
served as a useful starting point for us. We have wrappers over the
diagnostics system which we might be able to get rid of as well.
---
 gcc/rust/rust-diagnostics.cc | 244 +++
 gcc/rust/rust-diagnostics.h  | 154 +++
 gcc/rust/rust-gcc-diagnostics.cc |  84 +++
 gcc/rust/rust-linemap.cc | 229 +
 gcc/rust/rust-linemap.h  | 163 +
 gcc/rust/rust-location.h | 105 +
 gcc/rust/rust-system.h   |  86 +++
 7 files changed, 1065 insertions(+)
 create mode 100644 gcc/rust/rust-diagnostics.cc
 create mode 100644 gcc/rust/rust-diagnostics.h
 create mode 100644 gcc/rust/rust-gcc-diagnostics.cc
 create mode 100644 gcc/rust/rust-linemap.cc
 create mode 100644 gcc/rust/rust-linemap.h
 create mode 100644 gcc/rust/rust-location.h
 create mode 100644 gcc/rust/rust-system.h

diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc
new file mode 100644
index 000..c2d3e4ee8be
--- /dev/null
+++ b/gcc/rust/rust-diagnostics.cc
@@ -0,0 +1,244 @@
+// rust-diagnostics.cc -- GCC implementation of rust diagnostics interface.
+// Copyright (C) 2016-2022 Free Software Foundation, Inc.
+// Contributed by Than McIntosh, Google.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-system.h"
+#include "rust-diagnostics.h"
+
+static std::string
+mformat_value ()
+{
+  return std::string (xstrerror (errno));
+}
+
+// Rewrite a format string to expand any extensions not
+// supported by sprintf(). See comments in rust-diagnostics.h
+// for list of supported format specifiers.
+
+static std::string
+expand_format (const char *fmt)
+{
+  std::stringstream ss;
+  for (const char *c = fmt; *c; ++c)
+{
+  if (*c != '%')
+   {
+ ss << *c;
+ continue;
+   }
+  c++;
+  switch (*c)
+   {
+ case '\0': {
+   // malformed format string
+   rust_unreachable ();
+ }
+ case '%': {
+   ss << "%";
+   break;
+ }
+ case 'm': {
+   ss << mformat_value ();
+   break;
+ }
+ case '<': {
+   ss << rust_open_quote ();
+   break;
+ }
+ case '>': {
+   ss << rust_close_quote ();
+   break;
+ }
+ case 'q': {
+   ss << rust_open_quote ();
+   c++;
+   if (*c == 'm')
+ {
+   ss << mformat_value ();
+ }
+   else
+ {
+   ss << "%" << *c;
+ }
+   ss << rust_close_quote ();
+   break;
+ }
+ default: {
+   ss << "%" << *c;
+ }
+   }
+}
+  return ss.str ();
+}
+
+// Expand message format specifiers, using a combination of
+// expand_format above to handle extensions (ex: %m, %q) and vasprintf()
+// to handle regular printf-style formatting. A pragma is being used here to
+// suppress this warning:
+//
+//   warning: function ‘std::__cxx11::string expand_message(const char*,
+//   __va_list_tag*)’ might be a candidate for ‘gnu_printf’ format attribute
+//   [-Wsuggest-attribute=format]
+//
+// What appears to be happening here is that the checker is deciding that
+// because of the call to vasprintf() (which has attribute gnu_printf), the
+// calling function must need to have attribute gnu_printf as well, even
+// though there is already an attribute declaration for it.
+
+static std::string
+expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0);
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
+
+static std::string
+expand_message (const char *fmt, va_list ap)
+{
+  char *mbuf = 0;
+  std::string expanded_fmt = expand_format (fmt);
+  int nwr = vasprintf (, expanded_fmt.c_str (), ap);
+  if (nwr == -1)
+{
+  // memory allocation failed
+  rust_be_error_at (Linemap::unknown_location (),
+   "memory allocation failed in vasprintf");
+  rust_assert (0);
+}
+  std::string rval = std::string (mbuf);
+  free (mbuf);
+  return rval;
+}
+
+#pragma GCC diagnostic pop
+
+static const char *cached_open_quote = NULL;

Re: [PATCH] RISC-V: Recognized Svinval and Svnapot extensions

2022-10-26 Thread Kito Cheng via Gcc-patches
verified and committed

On Tue, Oct 25, 2022 at 2:18 PM Monk Chiang  wrote:
>
> gcc/ChangeLog:
>
> * common/config/riscv/riscv-common.cc (riscv_ext_version_table):
> Add svinval and svnapot extension.
> (riscv_ext_flag_table): Ditto.
> * config/riscv/riscv-opts.h (MASK_SVINVAL): New.
> (MASK_SVNAPOT): Ditto.
> (TARGET_SVINVAL): Ditto.
> (TARGET_SVNAPOT): Ditto.
> * config/riscv/riscv.opt (riscv_sv_subext): New.
>
> gcc/testsuite/ChangeLog:
> * gcc.target/riscv/predef-23.c:New.
> * gcc.target/riscv/predef-24.c:Ditto.
> ---
>  gcc/common/config/riscv/riscv-common.cc|  6 +++
>  gcc/config/riscv/riscv-opts.h  |  6 +++
>  gcc/config/riscv/riscv.opt |  3 ++
>  gcc/testsuite/gcc.target/riscv/predef-23.c | 47 ++
>  gcc/testsuite/gcc.target/riscv/predef-24.c | 47 ++
>  5 files changed, 109 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/predef-23.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/predef-24.c
>
> diff --git a/gcc/common/config/riscv/riscv-common.cc 
> b/gcc/common/config/riscv/riscv-common.cc
> index dead3802f83..a5fe782bb61 100644
> --- a/gcc/common/config/riscv/riscv-common.cc
> +++ b/gcc/common/config/riscv/riscv-common.cc
> @@ -202,6 +202,9 @@ static const struct riscv_ext_version 
> riscv_ext_version_table[] =
>
>{"zmmul", ISA_SPEC_CLASS_NONE, 1, 0},
>
> +  {"svinval", ISA_SPEC_CLASS_NONE, 1, 0},
> +  {"svnapot", ISA_SPEC_CLASS_NONE, 1, 0},
> +
>/* Terminate the list.  */
>{NULL, ISA_SPEC_CLASS_NONE, 0, 0}
>  };
> @@ -1226,6 +1229,9 @@ static const riscv_ext_flag_table_t 
> riscv_ext_flag_table[] =
>
>{"zmmul", _options::x_riscv_zm_subext, MASK_ZMMUL},
>
> +  {"svinval", _options::x_riscv_sv_subext, MASK_SVINVAL},
> +  {"svnapot", _options::x_riscv_sv_subext, MASK_SVNAPOT},
> +
>{NULL, NULL, 0}
>  };
>
> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> index 55e0bc0a0e9..63ac56a8ca0 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -162,6 +162,12 @@ enum stack_protector_guard {
>  #define MASK_ZMMUL  (1 << 0)
>  #define TARGET_ZMMUL((riscv_zm_subext & MASK_ZMMUL) != 0)
>
> +#define MASK_SVINVAL (1 << 0)
> +#define MASK_SVNAPOT (1 << 1)
> +
> +#define TARGET_SVINVAL ((riscv_sv_subext & MASK_SVINVAL) != 0)
> +#define TARGET_SVNAPOT ((riscv_sv_subext & MASK_SVNAPOT) != 0)
> +
>  /* Bit of riscv_zvl_flags will set contintuly, N-1 bit will set if N-bit is
> set, e.g. MASK_ZVL64B has set then MASK_ZVL32B is set, so we can use
> popcount to caclulate the minimal VLEN.  */
> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> index 8923a11a97d..949311775c1 100644
> --- a/gcc/config/riscv/riscv.opt
> +++ b/gcc/config/riscv/riscv.opt
> @@ -224,6 +224,9 @@ int riscv_zf_subext
>  TargetVariable
>  int riscv_zm_subext
>
> +TargetVariable
> +int riscv_sv_subext
> +
>  Enum
>  Name(isa_spec_class) Type(enum riscv_isa_spec_class)
>  Supported ISA specs (for use with the -misa-spec= option):
> diff --git a/gcc/testsuite/gcc.target/riscv/predef-23.c 
> b/gcc/testsuite/gcc.target/riscv/predef-23.c
> new file mode 100644
> index 000..64bde17efa9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/predef-23.c
> @@ -0,0 +1,47 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gc_svinval -mabi=lp64 -mcmodel=medlow 
> -misa-spec=20191213" } */
> +
> +int main () {
> +
> +#ifndef __riscv_arch_test
> +#error "__riscv_arch_test"
> +#endif
> +
> +#if __riscv_xlen != 64
> +#error "__riscv_xlen"
> +#endif
> +
> +#if !defined(__riscv_i) || (__riscv_i != (2 * 1000 * 1000 + 1 * 1000))
> +#error "__riscv_i"
> +#endif
> +
> +#if !defined(__riscv_c) || (__riscv_c != (2 * 1000 * 1000))
> +#error "__riscv_c"
> +#endif
> +
> +#if defined(__riscv_e)
> +#error "__riscv_e"
> +#endif
> +
> +#if !defined(__riscv_a) || (__riscv_a != (2 * 1000 * 1000 + 1 * 1000))
> +#error "__riscv_a"
> +#endif
> +
> +#if !defined(__riscv_m) || (__riscv_m != (2 * 1000 * 1000))
> +#error "__riscv_m"
> +#endif
> +
> +#if !defined(__riscv_f) || (__riscv_f != (2 * 1000 * 1000 + 2 * 1000))
> +#error "__riscv_f"
> +#endif
> +
> +#if !defined(__riscv_d) || (__riscv_d != (2 * 1000 * 1000 + 2 * 1000))
> +#error "__riscv_d"
> +#endif
> +
> +#if !defined(__riscv_svinval)
> +#error "__riscv_svinval"
> +#endif
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/predef-24.c 
> b/gcc/testsuite/gcc.target/riscv/predef-24.c
> new file mode 100644
> index 000..2b51a19eacd
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/predef-24.c
> @@ -0,0 +1,47 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gc_svnapot -mabi=lp64 -mcmodel=medlow 
> -misa-spec=20191213" } */
> +
> +int main () {
> +
> +#ifndef __riscv_arch_test
> +#error "__riscv_arch_test"
> +#endif
> +
> +#if __riscv_xlen != 64
> +#error "__riscv_xlen"
> +#endif
> 

[PATCH Rust front-end v3 40/46] gccrs: Add GCC Rust front-end Make-lang.in

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This is the Makefile for our front-end.
---
 gcc/rust/Make-lang.in | 399 ++
 1 file changed, 399 insertions(+)
 create mode 100644 gcc/rust/Make-lang.in

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
new file mode 100644
index 000..a62e793a29d
--- /dev/null
+++ b/gcc/rust/Make-lang.in
@@ -0,0 +1,399 @@
+# Make-lang.in -- Top level -*- makefile -*- fragment for GCC Rust frontend.
+
+# Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+# This file provides the language dependent support in the main Makefile.
+
+#RUST_EXES = rust
+
+# Use strict warnings for this front end.
+rust-warn = $(STRICT_WARN)
+
+# Installation name. Useful for cross compilers and used during install.
+GCCRS_INSTALL_NAME := $(shell echo gccrs|sed '$(program_transform_name)')
+GCCRS_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccrs|sed 
'$(program_transform_name)')
+
+# Define the names for selecting rust in LANGUAGES.
+rust: rust1$(exeext)
+
+# Tell GNU make to ignore files by these names if they exist.
+.PHONY: rust
+
+# removed GRS_CFLAGS from here
+
+CFLAGS-rust/rustspec.o += $(DRIVER_DEFINES)
+
+# Create the compiler driver gccrs.
+# A compiler driver is the program that interprets command argument and can be 
called from the command
+# line - e.g. gcc or g++, and not cc1, which is the actual compiler
+
+# Create driver objects
+GCCRS_D_OBJS = \
+   $(GCC_OBJS) \
+   rust/rustspec.o \
+   $(END)
+
+gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
+   +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+ $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
+ $(EXTRA_GCC_LIBS) $(LIBS)
+
+# List of host object files used by the rust language - files for translation 
from the parse tree
+# to GENERIC
+# The compiler proper, not driver
+GRS_OBJS = \
+rust/rust-lang.o \
+rust/rust-object-export.o \
+rust/rust-linemap.o \
+rust/rust-gcc-diagnostics.o \
+rust/rust-diagnostics.o \
+rust/rust-gcc.o \
+rust/rust-token.o \
+rust/rust-lex.o \
+rust/rust-cfg-parser.o \
+rust/rust-parse.o \
+rust/rust-ast-full-test.o \
+rust/rust-ast-dump.o \
+rust/rust-hir-dump.o \
+rust/rust-session-manager.o \
+rust/rust-compile.o \
+rust/rust-mangle.o \
+rust/rust-compile-resolve-path.o \
+rust/rust-macro-expand.o \
+rust/rust-attribute-visitor.o \
+rust/rust-macro-invoc-lexer.o \
+rust/rust-macro-substitute-ctx.o \
+rust/rust-macro-builtins.o \
+rust/rust-hir-full-test.o \
+rust/rust-hir-map.o \
+rust/rust-attributes.o \
+rust/rust-abi.o \
+rust/rust-ast-lower.o \
+rust/rust-ast-lower-base.o \
+rust/rust-ast-lower-pattern.o \
+rust/rust-ast-lower-item.o \
+rust/rust-name-resolver.o \
+rust/rust-ast-resolve.o \
+rust/rust-ast-resolve-base.o \
+rust/rust-ast-resolve-item.o \
+rust/rust-ast-resolve-pattern.o \
+rust/rust-ast-resolve-expr.o \
+rust/rust-ast-resolve-type.o \
+rust/rust-ast-resolve-path.o \
+rust/rust-ast-resolve-stmt.o \
+rust/rust-ast-resolve-struct-expr-field.o \
+rust/rust-hir-type-check.o \
+rust/rust-privacy-check.o \
+rust/rust-privacy-ctx.o \
+rust/rust-reachability.o \
+rust/rust-visibility-resolver.o \
+rust/rust-pub-restricted-visitor.o \
+rust/rust-privacy-reporter.o \
+rust/rust-tyty.o \
+rust/rust-tyty-call.o \
+rust/rust-tyctx.o \
+rust/rust-tyty-bounds.o \
+rust/rust-hir-type-check-util.o \
+rust/rust-hir-trait-resolve.o \
+rust/rust-hir-type-check-toplevel.o \
+rust/rust-hir-type-check-item.o \
+rust/rust-hir-type-check-type.o \
+rust/rust-hir-type-check-struct.o \
+rust/rust-hir-type-check-pattern.o \
+rust/rust-hir-type-check-expr.o \
+rust/rust-hir-type-check-stmt.o \
+rust/rust-hir-type-check-enumitem.o \
+rust/rust-hir-type-check-implitem.o \
+rust/rust-hir-dot-operator.o \
+rust/rust-coercion.o \
+rust/rust-casts.o \
+rust/rust-hir-type-check-base.o \
+rust/rust-autoderef.o \
+rust/rust-substitution-mapper.o \
+rust/rust-const-checker.o \
+rust/rust-lint-marklive.o \
+rust/rust-lint-unused-var.o \
+rust/rust-hir-type-check-path.o \
+

[PATCH Rust front-end v3 35/46] gccrs: Add metadata ouptput pass

2022-10-26 Thread arthur . cohen
From: Philip Herron 

Extern crates statements to tell the front-end to look for another library.
The mechanism here is heavily inspired from gccgo, so when we compile a
library for example we invoke:

  gccrs -g -O2 -frust-crate=mylib -c src/lib.rs -o src/mylib.o

All going well this object file will now contain extra data inside
.rust-export section inside the object file which will be preserved inside
archives and shared objects. When we have another application which uses
this library 'mylib'.

  extern crate mylib;
  use mylib::foo;

  fn main() {
foo();
  }

We compile using:

  gcc -g -O2 -frust-crate=test -c src/main.rs -o src/main.o

When the extern crate line is hit the front-end will look for mylib.o,
libmylib.a, mylib.rox. If it finds a raw object file it will read the
.rust-export section directly from the object for the public metadata
such as public functions, types constants etc. If it fails to find an
object it might find .rox which is the objdump of the .rust-export to a
raw file, it might even find libmylib.a and read the export directly out
of the archive file reusing code from gccgo to do so.

The full compiler pipeline is reused here, so the metatadata is actually
just real rust code. The benifit here is that Rust supports exporting,
macros and generics so this requires the name-resolution and type info
all to be generated and inserted into the apropriate context classes. Since
the metadata is real rust code it means we can reuse the full pipeline to
generate the code as nessecary. So for the simple case of a public struct
we simply emit the AST dump of this struct directly into the metadata. If
its a non-generic public function we emit and extern rust abi block for
that function. If its a trait we can simply emit the trait with the public
memebers. Generics are more complicated since we need to emit the function
fully for it to be compiled correctly this still needs tests to be added.
The hardest part is non generic impl blocks which is still a WIP.

To finally link the two crates together you run:

  gcc -g -O2 -o rust-program.exe src/main.o src/mylib.o
---
 gcc/rust/metadata/rust-export-metadata.cc | 385 ++
 gcc/rust/metadata/rust-export-metadata.h  |  85 +++
 gcc/rust/metadata/rust-extern-crate.cc| 173 +
 gcc/rust/metadata/rust-extern-crate.h |  55 ++
 gcc/rust/metadata/rust-import-archive.cc  | 885 ++
 gcc/rust/metadata/rust-imports.cc | 441 +++
 gcc/rust/metadata/rust-imports.h  | 257 +++
 gcc/rust/rust-object-export.cc| 176 +
 gcc/rust/rust-object-export.h |  33 +
 9 files changed, 2490 insertions(+)
 create mode 100644 gcc/rust/metadata/rust-export-metadata.cc
 create mode 100644 gcc/rust/metadata/rust-export-metadata.h
 create mode 100644 gcc/rust/metadata/rust-extern-crate.cc
 create mode 100644 gcc/rust/metadata/rust-extern-crate.h
 create mode 100644 gcc/rust/metadata/rust-import-archive.cc
 create mode 100644 gcc/rust/metadata/rust-imports.cc
 create mode 100644 gcc/rust/metadata/rust-imports.h
 create mode 100644 gcc/rust/rust-object-export.cc
 create mode 100644 gcc/rust/rust-object-export.h

diff --git a/gcc/rust/metadata/rust-export-metadata.cc 
b/gcc/rust/metadata/rust-export-metadata.cc
new file mode 100644
index 000..4856bc26149
--- /dev/null
+++ b/gcc/rust/metadata/rust-export-metadata.cc
@@ -0,0 +1,385 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-export-metadata.h"
+#include "rust-hir-visitor.h"
+#include "rust-hir-full.h"
+#include "rust-hir-map.h"
+#include "rust-ast-dump.h"
+#include "rust-abi.h"
+#include "rust-object-export.h"
+
+#include "md5.h"
+
+namespace Rust {
+namespace Metadata {
+
+static const std::string extension_path = ".rox";
+
+ExportContext::ExportContext () : mappings (Analysis::Mappings::get ()) {}
+
+ExportContext::~ExportContext () {}
+
+void
+ExportContext::push_module_scope (const HIR::Module )
+{
+  module_stack.push_back (module);
+}
+
+const HIR::Module &
+ExportContext::pop_module_scope ()
+{
+  rust_assert (!module_stack.empty ());
+  const HIR::Module  = module_stack.back ();
+  module_stack.pop_back ();
+  return poped;
+}
+
+void
+ExportContext::emit_trait (const HIR::Trait )
+{
+  // lookup the AST node for this
+  AST::Item 

Re: [PATCH] RISC-V: Add h extension support

2022-10-26 Thread Kito Cheng via Gcc-patches
Thanks for the review, committed :)

On Mon, Oct 24, 2022 at 11:05 PM Jeff Law via Gcc-patches
 wrote:
>
>
> On 10/24/22 03:55, Kito Cheng wrote:
> > `h` was the prefix of multi-letter extension name, but it become a
> > extension in later RISC-V isa spec.
> >
> > Fortunately we don't have any extension really defined is prefixed
> > with `h`, so we can just change that.
> >
> > gcc/ChangeLog:
> >
> >   * common/config/riscv/riscv-common.cc (riscv_ext_version_table):
> >   Add `h`.
> >   (riscv_supported_std_ext): Ditto.
> >   (multi_letter_subset_rank): Remove `h`.
> >   (riscv_subset_list::parse_std_ext): Handle `h` as single letter
> >   extension.
> >   (riscv_subset_list::parse): Ditto.
> >
> > gcc/testsuite/ChangeLog:
> >
> >   * testsuite/gcc.target/riscv/arch-18.c: New.
> >   * testsuite/gcc.target/riscv/arch-5.c: Remove test for prefixed
> >   with `h`.
> >   * testsuite/gcc.target/riscv/predef-23.c: New.
>
> OK.
>
>
> Jeff
>
>


Re: [PATCH] i386: Enable small loop unrolling for O2

2022-10-26 Thread Hongyu Wang via Gcc-patches
> Does this setting benefit all targets?  IIRC, in the past all
> benchmarks also enabled -funroll-loops, so it looks to me that
> unrolling small loops by default is a good compromise.

The idea to unroll small loops can be explained from the x86
micro-architecture. Modern x86 processors has multiple way instruction
decoder (5uops for icelake/zen3). So for small loop with <= 4
instructions (usually has 3 uops with a cmp/jmp pair that can be
macro-fused), the decoder would have 2 uops bubble for each iteration
and the pipeline could not be fully utilized. Therefore we decide to
unroll the 4 insn loop once to at least to full-fill the decoder and
enhance the pipeline utilization.
We are not familiar with micro architecture of other targets, we don't
know whether the unrolling could benefit the instruction decoder, so
the decision could be different.

Uros Bizjak via Gcc-patches  于2022年10月26日周三 14:57写道:

>
> On Wed, Oct 26, 2022 at 7:53 AM Hongyu Wang  wrote:
> >
> > Hi,
> >
> > Inspired by rs6000 and s390 port changes, this patch
> > enables loop unrolling for small size loop at O2 by default.
> > The default behavior is to unroll loop with unknown trip-count and
> > less than 4 insns by 1 time.
> >
> > This improves 548.exchange2 by 3.5% on icelake and 6% on zen3 with
> > 1.2% codesize increment. For other benchmarks the variants are minor
> > and overall codesize increased by 0.2%.
> >
> > The kernel image size increased by 0.06%, and no impact on eembc.
>
> Does this setting benefit all targets?  IIRC, in the past all
> benchmarks also enabled -funroll-loops, so it looks to me that
> unrolling small loops by default is a good compromise.
>
> The patch is technically OK, but as a tuning default, I would leave
> the final approval to HJ.
>
> Thanks,
> Uros.
>
> >
> > Bootstrapped & regrtested on x86_64-pc-linux-gnu.
> >
> > Ok for trunk?
> >
> > gcc/ChangeLog:
> >
> > * common/config/i386/i386-common.cc (ix86_optimization_table):
> > Enable loop unroll and small loop unroll at O2 by default.
> > * config/i386/i386-options.cc
> > (ix86_override_options_after_change):
> > Disable small loop unroll when funroll-loops enabled, reset
> > cunroll_grow_size when it is not explicitly enabled.
> > (ix86_option_override_internal): Call
> > ix86_override_options_after_change instead of calling
> > ix86_recompute_optlev_based_flags and ix86_default_align
> > separately.
> > * config/i386/i386.cc (ix86_loop_unroll_adjust): Adjust unroll
> > factor if -munroll-only-small-loops enabled.
> > * config/i386/i386.opt: Add -munroll-only-small-loops,
> > -param=x86-small-unroll-ninsns= for loop insn limit,
> > -param=x86-small-unroll-factor= for unroll factor.
> > * doc/invoke.texi: Document -munroll-only-small-loops,
> > x86-small-unroll-ninsns and x86-small-unroll-factor.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.target/i386/pr86270.c: Add -mno-unroll-only-small-loops.
> > * gcc.target/i386/pr93002.c: Likewise.
> > ---
> >  gcc/common/config/i386/i386-common.cc   |  6 
> >  gcc/config/i386/i386-options.cc | 40 ++---
> >  gcc/config/i386/i386.cc | 13 
> >  gcc/config/i386/i386.opt| 13 
> >  gcc/doc/invoke.texi | 14 +
> >  gcc/testsuite/gcc.target/i386/pr86270.c |  2 +-
> >  gcc/testsuite/gcc.target/i386/pr93002.c |  2 +-
> >  7 files changed, 84 insertions(+), 6 deletions(-)
> >
> > diff --git a/gcc/common/config/i386/i386-common.cc 
> > b/gcc/common/config/i386/i386-common.cc
> > index d6a68dc9b1d..0e580b39d14 100644
> > --- a/gcc/common/config/i386/i386-common.cc
> > +++ b/gcc/common/config/i386/i386-common.cc
> > @@ -1686,6 +1686,12 @@ static const struct default_options 
> > ix86_option_optimization_table[] =
> >  /* The STC algorithm produces the smallest code at -Os, for x86.  */
> >  { OPT_LEVELS_2_PLUS, OPT_freorder_blocks_algorithm_, NULL,
> >REORDER_BLOCKS_ALGORITHM_STC },
> > +{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_funroll_loops, NULL, 1 },
> > +{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_munroll_only_small_loops, NULL, 1 
> > },
> > +/* Turns off -frename-registers and -fweb which are enabled by
> > +   funroll-loops.  */
> > +{ OPT_LEVELS_ALL, OPT_frename_registers, NULL, 0 },
> > +{ OPT_LEVELS_ALL, OPT_fweb, NULL, 0 },
> >  /* Turn off -fschedule-insns by default.  It tends to make the
> > problem with not enough registers even worse.  */
> >  { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 },
> > diff --git a/gcc/config/i386/i386-options.cc 
> > b/gcc/config/i386/i386-options.cc
> > index acb2291e70f..6ea347c32e1 100644
> > --- a/gcc/config/i386/i386-options.cc
> > +++ b/gcc/config/i386/i386-options.cc
> > @@ -1819,8 +1819,43 @@ ix86_recompute_optlev_based_flags (struct 
> > gcc_options *opts,
> >  void
> > 

[PATCH Rust front-end v3 32/46] gccrs: Add privacy checks

2022-10-26 Thread arthur . cohen
From: Arthur Cohen 

This pass is responsible for resolving the privacy of items and verifying
that access to these items is performed within the limits of that privacy.
By default, items in Rust are private and only public to the current
module and its submodules. However, the user can annotate an item with
various qualifiers such as `pub` to publicly expose an item. Furthermore,
a module path can be given to `pub` to restrict an item's privacy to a
certain module: These paths need to be resolved and later on checked by
the privacy error reporter.
---
 .../errors/privacy/rust-privacy-check.cc  |  63 ++
 .../errors/privacy/rust-privacy-check.h   |  44 +
 .../errors/privacy/rust-privacy-common.h  |  67 ++
 .../checks/errors/privacy/rust-privacy-ctx.cc |  93 +++
 .../checks/errors/privacy/rust-privacy-ctx.h  |  79 ++
 .../errors/privacy/rust-privacy-reporter.cc   | 771 ++
 .../errors/privacy/rust-privacy-reporter.h| 173 
 .../privacy/rust-pub-restricted-visitor.cc| 182 +
 .../privacy/rust-pub-restricted-visitor.h | 120 +++
 .../errors/privacy/rust-reachability.cc   | 236 ++
 .../checks/errors/privacy/rust-reachability.h |  87 ++
 .../privacy/rust-visibility-resolver.cc   | 245 ++
 .../errors/privacy/rust-visibility-resolver.h | 103 +++
 13 files changed, 2263 insertions(+)
 create mode 100644 gcc/rust/checks/errors/privacy/rust-privacy-check.cc
 create mode 100644 gcc/rust/checks/errors/privacy/rust-privacy-check.h
 create mode 100644 gcc/rust/checks/errors/privacy/rust-privacy-common.h
 create mode 100644 gcc/rust/checks/errors/privacy/rust-privacy-ctx.cc
 create mode 100644 gcc/rust/checks/errors/privacy/rust-privacy-ctx.h
 create mode 100644 gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
 create mode 100644 gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
 create mode 100644 
gcc/rust/checks/errors/privacy/rust-pub-restricted-visitor.cc
 create mode 100644 gcc/rust/checks/errors/privacy/rust-pub-restricted-visitor.h
 create mode 100644 gcc/rust/checks/errors/privacy/rust-reachability.cc
 create mode 100644 gcc/rust/checks/errors/privacy/rust-reachability.h
 create mode 100644 gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
 create mode 100644 gcc/rust/checks/errors/privacy/rust-visibility-resolver.h

diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc 
b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
new file mode 100644
index 000..9664d62f65c
--- /dev/null
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
@@ -0,0 +1,63 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-privacy-check.h"
+#include "rust-reachability.h"
+#include "rust-hir-type-check.h"
+#include "rust-hir-map.h"
+#include "rust-name-resolver.h"
+#include "rust-visibility-resolver.h"
+#include "rust-pub-restricted-visitor.h"
+#include "rust-privacy-reporter.h"
+
+extern bool
+saw_errors (void);
+
+namespace Rust {
+namespace Privacy {
+
+void
+Resolver::resolve (HIR::Crate )
+{
+  PrivacyContext ctx;
+  auto mappings = Analysis::Mappings::get ();
+  auto resolver = Rust::Resolver::Resolver::get ();
+  auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get ();
+
+  VisibilityResolver (*mappings, *resolver).go (crate);
+  PubRestrictedVisitor (*mappings).go (crate);
+  PrivacyReporter (*mappings, *resolver, *ty_ctx).go (crate);
+
+  auto visitor = ReachabilityVisitor (ctx, *ty_ctx);
+
+  const auto  = crate.items;
+
+  for (auto  : items)
+{
+  if (item->get_hir_kind () == HIR::Node::VIS_ITEM)
+   {
+ auto vis_item = static_cast (item.get ());
+ vis_item->accept_vis (visitor);
+   }
+}
+
+  if (saw_errors ())
+return;
+}
+} // namespace Privacy
+} // namespace Rust
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.h 
b/gcc/rust/checks/errors/privacy/rust-privacy-check.h
new file mode 100644
index 000..290b5eacb6c
--- /dev/null
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.h
@@ -0,0 +1,44 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either 

[PATCH Rust front-end v3 45/46] gccrs: Compiler proper interface kicks off the pipeline

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This is a wrapper to get out of C land in the rust-lang.cc and into our
class hierarchy for the rust front-end. We expect that the front-end only
support one source file input as the expansion pass will attempt to resolve
that relative pass and parse accordingly.

The main missing piece here is that we are using saw_errors() to return
early which is unnecessary but as our error handling has been improving
over time we will start to take advantage of error node in our type system
as well as error_mark_node from GCC. The caveat being that our lints/checks
expect no errors and will throw an assertion.
---
 gcc/rust/rust-lang.cc|  456 
 gcc/rust/rust-session-manager.cc | 1189 ++
 gcc/rust/rust-session-manager.h  |  358 +
 3 files changed, 2003 insertions(+)
 create mode 100644 gcc/rust/rust-lang.cc
 create mode 100644 gcc/rust/rust-session-manager.cc
 create mode 100644 gcc/rust/rust-session-manager.h

diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
new file mode 100644
index 000..f6557474c8c
--- /dev/null
+++ b/gcc/rust/rust-lang.cc
@@ -0,0 +1,456 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-system.h"
+#include "rust-diagnostics.h"
+#include "coretypes.h"
+#include "target.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "diagnostic.h"
+#include "opts.h"
+#include "fold-const.h"
+#include "gimplify.h"
+#include "stor-layout.h"
+#include "debug.h"
+#include "convert.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "selftest.h"
+#include "rust-cfg-parser.h"
+#include "rust-privacy-ctx.h"
+#include "rust-ast-resolve-item.h"
+#include "rust-optional.h"
+
+#include 
+// note: header files must be in this order or else forward declarations don't
+// work properly. Kinda dumb system, but have to live with it. clang-format
+// seems to mess it up
+/* Order: config, system, coretypes, target, tree, gimple-expr, diagnostic,
+ * opts, fold-const, gimplify, stor-layout, debug, convert, langhooks,
+ * langhooks-def */
+
+// FIXME: test saving intellisense
+#include "options.h"
+
+// version check to stop compiling if c++ isn't c++11 or higher
+#if __cplusplus < 201103
+#error 
\
+  "GCC Rust frontend requires C++11 or higher. You can compile the g++ 
frontend first and then compile the Rust frontend using that."
+#endif
+// TODO: is this best way to do it? Is it allowed? (should be)
+
+/* General TODOs:
+ *  - convert all copies of expensive-to-copy (deep copy) AST objects into
+ * moves, if possible. Don't remove clone functionality - it may be required 
for
+ * e.g. HIR conversion.
+ */
+
+#include "rust-session-manager.h"
+
+// Language-dependent contents of a type. GTY() mark used for garbage 
collector.
+struct GTY (()) lang_type
+{
+};
+
+// Language-dependent contents of a decl.
+struct GTY (()) lang_decl
+{
+};
+
+// Language-dependent contents of an identifier.  This must include a
+// tree_identifier.
+struct GTY (()) lang_identifier
+{
+  struct tree_identifier common;
+};
+
+// The resulting tree type.
+union GTY ((
+  desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+  chain_next (
+"CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), "
+"TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : 
NULL")))
+  lang_tree_node
+{
+  union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) 
generic;
+  struct lang_identifier GTY ((tag ("1"))) identifier;
+};
+
+// We don't use language_function.
+struct GTY (()) language_function
+{
+};
+
+// has to be in same compilation unit as session, so here for now
+void
+rust_add_target_info (const char *key, const char *value)
+{
+  sorry ("TODO");
+
+  Rust::Session::get_instance ().options.target_data.insert_key_value_pair (
+key, value);
+}
+
+/* Language hooks.  */
+
+/* Initial lang hook called (possibly), used for initialisation.
+ * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2,
+ * and build_common_builtin_nodes, as well as set global variable
+ * void_list_node. Apparently called after option handling? */
+static bool
+grs_langhook_init (void)
+{
+  /* Something to do with this:
+   This allows the code in 

[PATCH Rust front-end v3 33/46] gccrs: Add dead code scan on HIR

2022-10-26 Thread arthur . cohen
From: Thomas Young 

In order to find dead code we use a depth first search and keep liveness
variables, after type resolution. In this case, if a function is unused
and it calls another function the 2nd function is now unused since the
caller is not used etc. The algorithm is a depth first search.
---
 .../checks/lints/rust-lint-marklive-base.h|  45 +++
 gcc/rust/checks/lints/rust-lint-marklive.cc   | 282 
 gcc/rust/checks/lints/rust-lint-marklive.h| 308 ++
 .../checks/lints/rust-lint-scan-deadcode.h| 154 +
 4 files changed, 789 insertions(+)
 create mode 100644 gcc/rust/checks/lints/rust-lint-marklive-base.h
 create mode 100644 gcc/rust/checks/lints/rust-lint-marklive.cc
 create mode 100644 gcc/rust/checks/lints/rust-lint-marklive.h
 create mode 100644 gcc/rust/checks/lints/rust-lint-scan-deadcode.h

diff --git a/gcc/rust/checks/lints/rust-lint-marklive-base.h 
b/gcc/rust/checks/lints/rust-lint-marklive-base.h
new file mode 100644
index 000..97c068188b1
--- /dev/null
+++ b/gcc/rust/checks/lints/rust-lint-marklive-base.h
@@ -0,0 +1,45 @@
+// Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_HIR_LIVENESS_BASE
+#define RUST_HIR_LIVENESS_BASE
+
+#include "rust-diagnostics.h"
+#include "rust-lint-marklive.h"
+#include "rust-lint-marklive-base.h"
+#include "rust-hir-visitor.h"
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace Analysis {
+
+class MarkLiveBase : public HIR::HIRFullVisitorBase
+{
+public:
+  virtual ~MarkLiveBase () {}
+
+protected:
+  MarkLiveBase () : mappings (Analysis::Mappings::get ()) {}
+
+  Analysis::Mappings *mappings;
+};
+
+} // namespace Analysis
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/checks/lints/rust-lint-marklive.cc 
b/gcc/rust/checks/lints/rust-lint-marklive.cc
new file mode 100644
index 000..245632b4b4c
--- /dev/null
+++ b/gcc/rust/checks/lints/rust-lint-marklive.cc
@@ -0,0 +1,282 @@
+// Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+// The idea is that all reachable symbols are live, codes called
+// from live codes are live, and everything else is dead.
+
+#include "rust-lint-marklive.h"
+#include "rust-hir-full.h"
+#include "rust-name-resolver.h"
+
+namespace Rust {
+namespace Analysis {
+
+// This class trys to find the live symbols which can be used as
+// seeds in MarkLive
+//
+// 1. TODO: explicit live
+//- Attribute like #[allow(dead_code)]
+//- Attribute like #[lang=".."], it's not a intra-crate item.
+// 2. TODO: foreign item
+class FindEntryPoint : public MarkLiveBase
+{
+  using Rust::Analysis::MarkLiveBase::visit;
+
+public:
+  static std::vector find (HIR::Crate )
+  {
+FindEntryPoint findEntryPoint;
+for (auto it = crate.items.begin (); it != crate.items.end (); it++)
+  {
+   it->get ()->accept_vis (findEntryPoint);
+  }
+return findEntryPoint.getEntryPoint ();
+  }
+
+  // TODO not only fn main can be a entry point.
+  void visit (HIR::Function ) override
+  {
+if (function.get_function_name () == "main")
+  {
+   entryPoints.push_back (function.get_mappings ().get_hirid ());
+  }
+  }
+
+private:
+  FindEntryPoint () : MarkLiveBase () {}
+  std::vector entryPoints;
+  std::vector getEntryPoint () { return entryPoints; }
+};
+
+std::set
+MarkLive::Analysis (HIR::Crate )
+{
+  MarkLive marklive (FindEntryPoint::find (crate));
+  marklive.go (crate);
+
+  return marklive.liveSymbols;
+}
+
+// pop a live symbol from worklist every iteration,
+// if it's a function then walk the function body, and
+// 1. save all the live symbols in worklist which is
+//visited first time
+// 

[PATCH Rust front-end v3 34/46] gccrs: Add unused variable scan

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This is a simple walk_tree which acts on the monomorphized code. By walking
the compiled translation unit of functions.
---
 gcc/rust/checks/lints/rust-lint-unused-var.cc | 98 +++
 gcc/rust/checks/lints/rust-lint-unused-var.h  | 36 +++
 2 files changed, 134 insertions(+)
 create mode 100644 gcc/rust/checks/lints/rust-lint-unused-var.cc
 create mode 100644 gcc/rust/checks/lints/rust-lint-unused-var.h

diff --git a/gcc/rust/checks/lints/rust-lint-unused-var.cc 
b/gcc/rust/checks/lints/rust-lint-unused-var.cc
new file mode 100644
index 000..d4317e53280
--- /dev/null
+++ b/gcc/rust/checks/lints/rust-lint-unused-var.cc
@@ -0,0 +1,98 @@
+// Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-lint-unused-var.h"
+#include "print-tree.h"
+
+namespace Rust {
+namespace Analysis {
+
+static void
+check_decl (tree *t)
+{
+  rust_assert (TREE_CODE (*t) == VAR_DECL || TREE_CODE (*t) == PARM_DECL
+  || TREE_CODE (*t) == CONST_DECL);
+
+  tree var_name = DECL_NAME (*t);
+  const char *var_name_ptr = IDENTIFIER_POINTER (var_name);
+  bool starts_with_under_score = strncmp (var_name_ptr, "_", 1) == 0;
+
+  bool is_constant = TREE_CODE (*t) == CONST_DECL;
+  // if (!is_constant)
+  //   {
+  // debug_tree (*t);
+  // rust_debug ("found var-decl: used %s artifical %s underscore %s name
+  // %s",
+  // TREE_USED (*t) ? "true" : "false",
+  // DECL_ARTIFICIAL (*t) ? "true" : "false",
+  // starts_with_under_score ? "true" : "false", var_name_ptr);
+  //   }
+
+  if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score)
+{
+  warning_at (DECL_SOURCE_LOCATION (*t),
+ is_constant ? OPT_Wunused_const_variable_
+ : OPT_Wunused_variable,
+ "unused name %qE", *t);
+}
+}
+
+static tree
+unused_var_walk_fn (tree *t, int *walk_subtrees, void *closure)
+{
+  switch (TREE_CODE (*t))
+{
+case VAR_DECL:
+case CONST_DECL:
+  check_decl (t);
+  break;
+
+default:
+  break;
+}
+  return NULL_TREE;
+}
+
+void
+UnusedVariables::Lint (Compile::Context )
+{
+  for (auto  : ctx.get_func_decls ())
+{
+  for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN 
(p))
+   {
+ check_decl ();
+   }
+
+  walk_tree_without_duplicates (_SAVED_TREE (fndecl),
+   _var_walk_fn, );
+}
+
+  for (auto  : ctx.get_var_decls ())
+{
+  tree t = ctx.get_backend ()->var_expression (var, Location ());
+  check_decl ();
+}
+
+  for (auto _decl : ctx.get_const_decls ())
+{
+  check_decl (_decl);
+}
+}
+
+} // namespace Analysis
+} // namespace Rust
diff --git a/gcc/rust/checks/lints/rust-lint-unused-var.h 
b/gcc/rust/checks/lints/rust-lint-unused-var.h
new file mode 100644
index 000..6fabfeff01b
--- /dev/null
+++ b/gcc/rust/checks/lints/rust-lint-unused-var.h
@@ -0,0 +1,36 @@
+// Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_LINT_UNUSED_VAR
+#define RUST_LINT_UNUSED_VAR
+
+#include "rust-compile-context.h"
+
+namespace Rust {
+namespace Analysis {
+
+class UnusedVariables
+{
+public:
+  static void Lint (Compile::Context );
+};
+
+} // namespace Analysis
+} // namespace Rust
+
+#endif // RUST_LINT_UNUSED_VAR
-- 
2.37.2



[PATCH Rust front-end v3 41/46] gccrs: Add config-lang.in

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This was a copy paste from gccgo front-end, we do not use any of the
target_libs yet but we will need these when we support the libpanic crate.
---
 gcc/rust/config-lang.in | 34 ++
 1 file changed, 34 insertions(+)
 create mode 100644 gcc/rust/config-lang.in

diff --git a/gcc/rust/config-lang.in b/gcc/rust/config-lang.in
new file mode 100644
index 000..d2ff376032a
--- /dev/null
+++ b/gcc/rust/config-lang.in
@@ -0,0 +1,34 @@
+# config-lang.in -- Top level configure fragment for gcc Rust frontend.
+
+# Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+# Configure looks for the existence of this file to auto-config each language.
+# We define several parameters used by configure:
+#
+# language - name of language as it would appear in $(LANGUAGES)
+# compilers- value to add to $(COMPILERS)
+
+language="rust"
+compilers="rust1\$(exeext)"
+
+build_by_default="no"
+
+target_libs="target-libffi target-libbacktrace"
+
+gtfiles="\$(srcdir)/rust/rust-lang.cc"
-- 
2.37.2



[PATCH Rust front-end v3 30/46] gccrs: Add unsafe checks for Rust

2022-10-26 Thread arthur . cohen
From: Arthur Cohen 

The UnsafeChecker visitor verifies that unsafe actions are only performed
in unsafe contexts. Otherwise, an error should be reported to the user and
the compilation pipeline should be halted. These contexts, which include
unsafe blocks or unsafe functions, are allowed to perform more actions
than regular safe Rust code. These actions currently include:

- Dereferencing raw pointers
- Calls to unsafe functions
- Use of inline assembly
- Use of mutable static
- Use of extern static
- Access to a union's field
- Call to functions with #[target(feature)] attribute
- Initializing type with rustc_layout_scalar_valid_range attribute
- Mutation of layout constrained field
- Borrow of layout constrained field
---
 gcc/rust/checks/errors/rust-unsafe-checker.cc | 963 ++
 gcc/rust/checks/errors/rust-unsafe-checker.h  | 191 
 2 files changed, 1154 insertions(+)
 create mode 100644 gcc/rust/checks/errors/rust-unsafe-checker.cc
 create mode 100644 gcc/rust/checks/errors/rust-unsafe-checker.h

diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc 
b/gcc/rust/checks/errors/rust-unsafe-checker.cc
new file mode 100644
index 000..e3f32539562
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -0,0 +1,963 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-unsafe-checker.h"
+#include "rust-hir.h"
+#include "rust-hir-expr.h"
+#include "rust-hir-stmt.h"
+#include "rust-hir-item.h"
+
+namespace Rust {
+namespace HIR {
+
+UnsafeChecker::UnsafeChecker ()
+  : context (*Resolver::TypeCheckContext::get ()),
+resolver (*Resolver::Resolver::get ()),
+mappings (*Analysis::Mappings::get ())
+{}
+
+void
+UnsafeChecker::go (HIR::Crate )
+{
+  for (auto  : crate.items)
+item->accept_vis (*this);
+}
+
+static void
+check_static_mut (HIR::Item *maybe_static, Location locus)
+{
+  if (maybe_static->get_hir_kind () == Node::BaseKind::VIS_ITEM)
+{
+  auto item = static_cast (maybe_static);
+  if (item->get_item_kind () == Item::ItemKind::Static)
+   {
+ auto static_item = static_cast (item);
+ if (static_item->is_mut ())
+   rust_error_at (
+ locus, "use of mutable static requires unsafe function or block");
+   }
+}
+}
+
+static void
+check_extern_static (HIR::ExternalItem *maybe_static, Location locus)
+{
+  if (maybe_static->get_extern_kind () == ExternalItem::ExternKind::Static)
+rust_error_at (locus,
+  "use of extern static requires unsafe function or block");
+}
+
+void
+UnsafeChecker::check_use_of_static (HirId node_id, Location locus)
+{
+  if (unsafe_context.is_in_context ())
+return;
+
+  auto maybe_static_mut = mappings.lookup_hir_item (node_id);
+
+  HirId extern_block;
+  auto maybe_extern_static
+= mappings.lookup_hir_extern_item (node_id, _block);
+
+  if (maybe_static_mut)
+check_static_mut (maybe_static_mut, locus);
+
+  if (maybe_extern_static)
+check_extern_static (static_cast (maybe_extern_static),
+locus);
+}
+
+static void
+check_unsafe_call (HIR::Function *fn, Location locus, const std::string )
+{
+  if (fn->get_qualifiers ().is_unsafe ())
+rust_error_at (locus, "call to unsafe %s requires unsafe function or 
block",
+  kind.c_str ());
+}
+
+static bool
+is_safe_intrinsic (const std::string _name)
+{
+  static const std::unordered_set safe_intrinsics = {
+"abort",
+"size_of",
+"min_align_of",
+"needs_drop",
+"caller_location",
+"add_with_overflow",
+"sub_with_overflow",
+"mul_with_overflow",
+"wrapping_add",
+"wrapping_sub",
+"wrapping_mul",
+"saturating_add",
+"saturating_sub",
+"rotate_left",
+"rotate_right",
+"ctpop",
+"ctlz",
+"cttz",
+"bswap",
+"bitreverse",
+"discriminant_value",
+"type_id",
+"likely",
+"unlikely",
+"ptr_guaranteed_eq",
+"ptr_guaranteed_ne",
+"minnumf32",
+"minnumf64",
+"maxnumf32",
+"rustc_peek",
+"maxnumf64",
+"type_name",
+"forget",
+"black_box",
+"variant_count",
+  };
+
+  return safe_intrinsics.find (fn_name) != safe_intrinsics.end ();
+}
+
+static void
+check_extern_call (HIR::ExternalItem *maybe_fn, HIR::ExternBlock *parent_block,
+

[PATCH Rust front-end v3 21/46] gccrs: Add port of FNV hash used during legacy symbol mangling

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This hash was ported from the go runime as we needed a hash for the legacy
symbol mangling system. Which means all symbols in Rust contain a hash of
some metadata for uniqueness on generic functions.
---
 gcc/rust/util/fnv-hash.h | 95 
 1 file changed, 95 insertions(+)
 create mode 100644 gcc/rust/util/fnv-hash.h

diff --git a/gcc/rust/util/fnv-hash.h b/gcc/rust/util/fnv-hash.h
new file mode 100644
index 000..78e54c99411
--- /dev/null
+++ b/gcc/rust/util/fnv-hash.h
@@ -0,0 +1,95 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_FNV_HASH_H
+#define RUST_FNV_HASH_H
+
+namespace Rust {
+namespace Hash {
+
+const uint64_t offset128Lower = 0x62b821756295c58d;
+const uint64_t offset128Higher = 0x6c62272e07bb0142;
+const uint64_t prime128Lower = 0x13b;
+const uint64_t prime128Shift = 24;
+
+// ported from https://github.com/golang/go/blob/master/src/hash/fnv/fnv.go
+class FNV128
+{
+public:
+  FNV128 () { reset (); }
+
+  void reset ()
+  {
+buf[0] = offset128Higher;
+buf[1] = offset128Lower;
+  }
+
+  void write (const unsigned char *in, size_t len)
+  {
+for (size_t i = 0; i < len; i++)
+  {
+   unsigned char c = in[i];
+
+   // 
https://stackoverflow.com/questions/28868367/getting-the-high-part-of-64-bit-integer-multiplication
+   uint64_t a = prime128Lower;
+   uint64_t b = buf[1];
+
+   uint64_t a_lo = (uint32_t) a;
+   uint64_t a_hi = a >> 32;
+   uint64_t b_lo = (uint32_t) b;
+   uint64_t b_hi = b >> 32;
+
+   uint64_t a_x_b_hi = a_hi * b_hi;
+   uint64_t a_x_b_mid = a_hi * b_lo;
+   uint64_t b_x_a_mid = b_hi * a_lo;
+   uint64_t a_x_b_lo = a_lo * b_lo;
+
+   uint64_t carry_bit
+ = ((uint64_t) (uint32_t) a_x_b_mid + (uint64_t) (uint32_t) b_x_a_mid
++ (a_x_b_lo >> 32))
+   >> 32;
+
+   uint64_t multhi
+ = a_x_b_hi + (a_x_b_mid >> 32) + (b_x_a_mid >> 32) + carry_bit;
+
+   uint64_t s0 = multhi; // high
+   uint64_t s1 = prime128Lower * buf[1]; // low
+
+   s0 += buf[1] << (prime128Shift + prime128Lower * buf[0]);
+
+   // Update the values
+   buf[1] = s1;
+   buf[0] = s0;
+   buf[1] ^= (uint64_t) c;
+  }
+  }
+
+  void sum (uint64_t *hi, uint64_t *lo) const
+  {
+*hi = buf[0];
+*lo = buf[1];
+  }
+
+private:
+  uint64_t buf[2];
+};
+
+} // namespace Hash
+} // namespace Rust
+
+#endif // RUST_FNV_HASH_H
-- 
2.37.2



[PATCH Rust front-end v3 28/46] gccrs: Add Rust type information

2022-10-26 Thread arthur . cohen
From: Philip Herron 

Contains abstractions over Rust's types, used when performing the
HIR's type-resolution.
---
 gcc/rust/typecheck/rust-tyty.cc | 2885 +++
 gcc/rust/typecheck/rust-tyty.h  | 2533 +++
 2 files changed, 5418 insertions(+)
 create mode 100644 gcc/rust/typecheck/rust-tyty.cc
 create mode 100644 gcc/rust/typecheck/rust-tyty.h

diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
new file mode 100644
index 000..3c2c6786940
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -0,0 +1,2885 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-tyty.h"
+#include "rust-tyty-visitor.h"
+#include "rust-tyty-call.h"
+#include "rust-hir-type-check-expr.h"
+#include "rust-hir-type-check-type.h"
+#include "rust-tyty-rules.h"
+#include "rust-tyty-cmp.h"
+#include "rust-hir-map.h"
+#include "rust-substitution-mapper.h"
+#include "rust-hir-trait-ref.h"
+#include "rust-hir-type-bounds.h"
+
+namespace Rust {
+namespace TyTy {
+
+std::string
+TypeKindFormat::to_string (TypeKind kind)
+{
+  switch (kind)
+{
+case TypeKind::INFER:
+  return "Infer";
+
+case TypeKind::ADT:
+  return "ADT";
+
+case TypeKind::STR:
+  return "STR";
+
+case TypeKind::REF:
+  return "REF";
+
+case TypeKind::POINTER:
+  return "POINTER";
+
+case TypeKind::PARAM:
+  return "PARAM";
+
+case TypeKind::ARRAY:
+  return "ARRAY";
+
+case TypeKind::SLICE:
+  return "SLICE";
+
+case TypeKind::FNDEF:
+  return "FnDef";
+
+case TypeKind::FNPTR:
+  return "FnPtr";
+
+case TypeKind::TUPLE:
+  return "Tuple";
+
+case TypeKind::BOOL:
+  return "Bool";
+
+case TypeKind::CHAR:
+  return "Char";
+
+case TypeKind::INT:
+  return "Int";
+
+case TypeKind::UINT:
+  return "Uint";
+
+case TypeKind::FLOAT:
+  return "Float";
+
+case TypeKind::USIZE:
+  return "Usize";
+
+case TypeKind::ISIZE:
+  return "Isize";
+
+case TypeKind::NEVER:
+  return "Never";
+
+case TypeKind::PLACEHOLDER:
+  return "Placeholder";
+
+case TypeKind::PROJECTION:
+  return "Projection";
+
+case TypeKind::DYNAMIC:
+  return "Dynamic";
+
+case TypeKind::CLOSURE:
+  return "Closure";
+
+case TypeKind::ERROR:
+  return "ERROR";
+}
+  gcc_unreachable ();
+}
+
+bool
+is_primitive_type_kind (TypeKind kind)
+{
+  switch (kind)
+{
+case TypeKind::BOOL:
+case TypeKind::CHAR:
+case TypeKind::INT:
+case TypeKind::UINT:
+case TypeKind::ISIZE:
+case TypeKind::USIZE:
+case TypeKind::FLOAT:
+case TypeKind::NEVER:
+case TypeKind::STR:
+  return true;
+default:
+  return false;
+}
+}
+
+bool
+BaseType::satisfies_bound (const TypeBoundPredicate ) const
+{
+  const Resolver::TraitReference *query = predicate.get ();
+  for (auto  : specified_bounds)
+{
+  const Resolver::TraitReference *item = bound.get ();
+  bool found = item->get_mappings ().get_defid ()
+  == query->get_mappings ().get_defid ();
+  if (found)
+   return true;
+}
+
+  auto probed = Resolver::TypeBoundsProbe::Probe (this);
+  for (auto  : probed)
+{
+  const Resolver::TraitReference *bound = b.first;
+  bool found = bound->get_mappings ().get_defid ()
+  == query->get_mappings ().get_defid ();
+  if (found)
+   return true;
+}
+
+  return false;
+}
+
+bool
+BaseType::bounds_compatible (const BaseType , Location locus,
+bool emit_error) const
+{
+  std::vector>
+unsatisfied_bounds;
+  for (auto  : get_specified_bounds ())
+{
+  if (!other.satisfies_bound (bound))
+   unsatisfied_bounds.push_back (bound);
+}
+
+  // lets emit a single error for this
+  if (unsatisfied_bounds.size () > 0)
+{
+  RichLocation r (locus);
+  std::string missing_preds;
+  for (size_t i = 0; i < unsatisfied_bounds.size (); i++)
+   {
+ const TypeBoundPredicate  = unsatisfied_bounds.at (i);
+ r.add_range (pred.get_locus ());
+ missing_preds += pred.get_name ();
+
+ bool have_next = (i + 1) < unsatisfied_bounds.size ();
+ if (have_next)
+   

[PATCH Rust front-end v3 38/46] gccrs: Add HIR to GCC GENERIC lowering entry point

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This patch contains the entry point and utilities used for the lowering
of HIR nodes to `tree`s. It also contains a constant evaluator, ported
over from the C++ frontend.

Co-authored-by: David Faust 
Co-authored-by: Faisal Abbas <90.abbasfai...@gmail.com>
---
 gcc/rust/backend/rust-compile-context.cc | 146 
 gcc/rust/backend/rust-compile-context.h  | 343 ++
 gcc/rust/backend/rust-compile.cc | 414 +
 gcc/rust/backend/rust-compile.h  |  47 +++
 gcc/rust/backend/rust-constexpr.cc   | 441 +++
 gcc/rust/backend/rust-constexpr.h|  31 ++
 6 files changed, 1422 insertions(+)
 create mode 100644 gcc/rust/backend/rust-compile-context.cc
 create mode 100644 gcc/rust/backend/rust-compile-context.h
 create mode 100644 gcc/rust/backend/rust-compile.cc
 create mode 100644 gcc/rust/backend/rust-compile.h
 create mode 100644 gcc/rust/backend/rust-constexpr.cc
 create mode 100644 gcc/rust/backend/rust-constexpr.h

diff --git a/gcc/rust/backend/rust-compile-context.cc 
b/gcc/rust/backend/rust-compile-context.cc
new file mode 100644
index 000..cb2addf6c21
--- /dev/null
+++ b/gcc/rust/backend/rust-compile-context.cc
@@ -0,0 +1,146 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-compile-context.h"
+#include "rust-compile-type.h"
+
+namespace Rust {
+namespace Compile {
+
+Context::Context (::Backend *backend)
+  : backend (backend), resolver (Resolver::Resolver::get ()),
+tyctx (Resolver::TypeCheckContext::get ()),
+mappings (Analysis::Mappings::get ()), mangler (Mangler ())
+{
+  setup_builtins ();
+}
+
+void
+Context::setup_builtins ()
+{
+  auto builtins = resolver->get_builtin_types ();
+  for (auto it = builtins.begin (); it != builtins.end (); it++)
+{
+  HirId ref;
+  bool ok = tyctx->lookup_type_by_node_id ((*it)->get_node_id (), );
+  rust_assert (ok);
+
+  TyTy::BaseType *lookup;
+  ok = tyctx->lookup_type (ref, );
+  rust_assert (ok);
+
+  TyTyResolveCompile::compile (this, lookup);
+}
+}
+
+hashval_t
+Context::type_hasher (tree type)
+{
+  inchash::hash hstate;
+
+  hstate.add_int (TREE_CODE (type));
+
+  if (TYPE_NAME (type))
+{
+  hashval_t record_name_hash
+   = IDENTIFIER_HASH_VALUE (DECL_NAME (TYPE_NAME (type)));
+  hstate.add_object (record_name_hash);
+}
+
+  for (tree t = TYPE_ATTRIBUTES (type); t; t = TREE_CHAIN (t))
+/* Just the identifier is adequate to distinguish.  */
+hstate.add_object (IDENTIFIER_HASH_VALUE (TREE_PURPOSE (t)));
+
+  switch (TREE_CODE (type))
+{
+case METHOD_TYPE:
+  hstate.add_object (TYPE_HASH (TYPE_METHOD_BASETYPE (type)));
+  /* FALLTHROUGH. */
+case FUNCTION_TYPE:
+  for (tree t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
+   if (TREE_VALUE (t) != error_mark_node)
+ hstate.add_object (TYPE_HASH (TREE_VALUE (t)));
+  break;
+
+case OFFSET_TYPE:
+  hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type)));
+  break;
+
+  case ARRAY_TYPE: {
+   if (TYPE_DOMAIN (type))
+ hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type)));
+   if (!AGGREGATE_TYPE_P (TREE_TYPE (type)))
+ {
+   unsigned typeless = TYPE_TYPELESS_STORAGE (type);
+   hstate.add_object (typeless);
+ }
+  }
+  break;
+
+  case INTEGER_TYPE: {
+   tree t = TYPE_MAX_VALUE (type);
+   if (!t)
+ t = TYPE_MIN_VALUE (type);
+   for (int i = 0; i < TREE_INT_CST_NUNITS (t); i++)
+ hstate.add_object (TREE_INT_CST_ELT (t, i));
+   break;
+  }
+
+case REAL_TYPE:
+  case FIXED_POINT_TYPE: {
+   unsigned prec = TYPE_PRECISION (type);
+   hstate.add_object (prec);
+   break;
+  }
+
+case VECTOR_TYPE:
+  hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type));
+  break;
+
+case RECORD_TYPE:
+case UNION_TYPE:
+  case QUAL_UNION_TYPE: {
+   for (tree t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+ {
+   hashval_t name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (t));
+   hashval_t type_hash = type_hasher (TREE_TYPE (t));
+   hstate.add_object (name_hash);
+   hstate.add_object (type_hash);
+ }
+  }
+  break;

[PATCH Rust front-end v3 26/46] gccrs: Add helpers mappings canonical path and lang items

2022-10-26 Thread arthur . cohen
From: Philip Herron 

These are various helper classes used in the compiler pipeline.
---
 gcc/rust/util/rust-canonical-path.h   | 195 +
 gcc/rust/util/rust-common.h   |  53 ++
 gcc/rust/util/rust-hir-map.cc | 980 ++
 gcc/rust/util/rust-hir-map.h  | 356 ++
 gcc/rust/util/rust-identifier.h   |  49 ++
 gcc/rust/util/rust-lang-item.h| 377 ++
 gcc/rust/util/rust-mapping-common.h   |  85 +++
 gcc/rust/util/rust-stacked-contexts.h |  86 +++
 8 files changed, 2181 insertions(+)
 create mode 100644 gcc/rust/util/rust-canonical-path.h
 create mode 100644 gcc/rust/util/rust-common.h
 create mode 100644 gcc/rust/util/rust-hir-map.cc
 create mode 100644 gcc/rust/util/rust-hir-map.h
 create mode 100644 gcc/rust/util/rust-identifier.h
 create mode 100644 gcc/rust/util/rust-lang-item.h
 create mode 100644 gcc/rust/util/rust-mapping-common.h
 create mode 100644 gcc/rust/util/rust-stacked-contexts.h

diff --git a/gcc/rust/util/rust-canonical-path.h 
b/gcc/rust/util/rust-canonical-path.h
new file mode 100644
index 000..54cc0390849
--- /dev/null
+++ b/gcc/rust/util/rust-canonical-path.h
@@ -0,0 +1,195 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_CANONICAL_PATH
+#define RUST_CANONICAL_PATH
+
+#include "rust-system.h"
+#include "rust-mapping-common.h"
+
+namespace Rust {
+namespace Resolver {
+
+// https://doc.rust-lang.org/reference/paths.html#canonical-paths
+//
+// struct X - path X
+// impl X { fn test - path X::test }
+//
+// struct X - path X
+//
+// impl X   { fn test - path X::test}
+// impl X { fn test - path X::test }
+// impl X { fn test - path X::test }
+//
+// pub trait Trait { // ::a::Trait
+//   fn f(); // ::a::Trait::f
+// }
+//
+// impl Trait for Struct {
+//fn f() {} // <::a::Struct as ::a::Trait>::f
+// }
+class CanonicalPath
+{
+public:
+  CanonicalPath (const CanonicalPath ) : segs (other.segs) {}
+
+  CanonicalPath = (const CanonicalPath )
+  {
+segs = other.segs;
+return *this;
+  }
+
+  static CanonicalPath new_seg (NodeId id, const std::string )
+  {
+rust_assert (!path.empty ());
+return CanonicalPath ({std::pair (id, path)},
+ UNKNOWN_CREATENUM);
+  }
+
+  static CanonicalPath
+  trait_impl_projection_seg (NodeId id, const CanonicalPath _seg,
+const CanonicalPath _type_seg)
+  {
+return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as "
++ trait_seg.get () + ">");
+  }
+
+  std::string get () const
+  {
+std::string buf;
+for (size_t i = 0; i < segs.size (); i++)
+  {
+   bool have_more = (i + 1) < segs.size ();
+   const std::string  = segs.at (i).second;
+   buf += seg + (have_more ? "::" : "");
+  }
+return buf;
+  }
+
+  static CanonicalPath get_big_self (NodeId id)
+  {
+return CanonicalPath::new_seg (id, "Self");
+  }
+
+  static CanonicalPath create_empty ()
+  {
+return CanonicalPath ({}, UNKNOWN_CREATENUM);
+  }
+
+  bool is_empty () const { return segs.size () == 0; }
+
+  CanonicalPath append (const CanonicalPath ) const
+  {
+rust_assert (!other.is_empty ());
+if (is_empty ())
+  return CanonicalPath (other.segs, crate_num);
+
+std::vector> copy (segs);
+for (auto  : other.segs)
+  copy.push_back (s);
+
+return CanonicalPath (copy, crate_num);
+  }
+
+  // if we have the path A::B::C this will give a callback for each segment
+  // including the prefix, example:
+  //
+  // path:
+  //   A::B::C
+  //
+  // iterate:
+  //   A
+  //   A::B
+  //   A::B::C
+  void iterate (std::function cb) const
+  {
+std::vector> buf;
+for (auto  : segs)
+  {
+   buf.push_back (seg);
+   if (!cb (CanonicalPath (buf, crate_num)))
+ return;
+  }
+  }
+
+  // if we have the path A::B::C this will give a callback for each segment
+  // example:
+  //
+  // path:
+  //   A::B::C
+  //
+  // iterate:
+  //   A
+  //  B
+  // C
+  void iterate_segs (std::function cb) const
+  {
+for (auto  : segs)
+  {
+   std::vector> buf;
+   buf.push_back ({seg.first, seg.second});
+   if (!cb (CanonicalPath (buf, crate_num)))
+ return;
+  }
+  }
+
+  size_t size () const { 

[PATCH Rust front-end v3 25/46] gccrs: Add attributes checker

2022-10-26 Thread arthur . cohen
From: Arthur Cohen 

The attribute checker is responsible for checking the validity of various
attributes including built-in ones. It is currently unfinished and will
receive some modifications, as well as become the host of some existing
code in the compiler which needs to be refactored. One of its
responsibilities is to make sure that arguments given to built-in
attributes are correct, or contain the correct type of information. This
visitor also checks that an attribute is allowed to be used in the current
particular context.
---
 gcc/rust/util/rust-attributes.cc | 839 +++
 gcc/rust/util/rust-attributes.h  | 270 ++
 2 files changed, 1109 insertions(+)
 create mode 100644 gcc/rust/util/rust-attributes.cc
 create mode 100644 gcc/rust/util/rust-attributes.h

diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
new file mode 100644
index 000..b73e9534414
--- /dev/null
+++ b/gcc/rust/util/rust-attributes.cc
@@ -0,0 +1,839 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-system.h"
+#include "rust-attributes.h"
+#include "rust-ast.h"
+#include "rust-ast-full.h"
+#include "rust-diagnostics.h"
+
+namespace Rust {
+namespace Analysis {
+
+// 
https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
+static const BuiltinAttrDefinition __definitions[] = {
+  {"inline", CODE_GENERATION},
+  {"cold", CODE_GENERATION},
+  {"cfg", EXPANSION},
+  {"cfg_attr", EXPANSION},
+  {"deprecated", STATIC_ANALYSIS},
+  {"allow", STATIC_ANALYSIS},
+  {"doc", HIR_LOWERING},
+  {"must_use", STATIC_ANALYSIS},
+  {"lang", HIR_LOWERING},
+  {"link_section", CODE_GENERATION},
+  {"no_mangle", CODE_GENERATION},
+  {"repr", CODE_GENERATION},
+  {"path", EXPANSION},
+};
+
+BuiltinAttributeMappings *
+BuiltinAttributeMappings::get ()
+{
+  static BuiltinAttributeMappings *instance = nullptr;
+  if (instance == nullptr)
+instance = new BuiltinAttributeMappings ();
+
+  return instance;
+}
+
+const BuiltinAttrDefinition &
+BuiltinAttributeMappings::lookup_builtin (const std::string _name) const
+{
+  auto it = mappings.find (attr_name);
+  if (it == mappings.end ())
+return BuiltinAttrDefinition::error_node ();
+
+  return it->second;
+}
+
+BuiltinAttributeMappings::BuiltinAttributeMappings ()
+{
+  size_t ndefinitions = sizeof (__definitions) / sizeof 
(BuiltinAttrDefinition);
+  for (size_t i = 0; i < ndefinitions; i++)
+{
+  const BuiltinAttrDefinition  = __definitions[i];
+  mappings.insert ({def.name, def});
+}
+}
+
+AttributeChecker::AttributeChecker () {}
+
+void
+AttributeChecker::go (AST::Crate )
+{
+  check_attributes (crate.get_inner_attrs ());
+
+  for (auto  : crate.items)
+item->accept_vis (*this);
+}
+
+static bool
+is_builtin (const AST::Attribute , BuiltinAttrDefinition )
+{
+  auto  = attribute.get_path ().get_segments ();
+
+  // Builtin attributes always have a single segment. This avoids us creating
+  // strings all over the place and performing a linear search in the builtins
+  // map
+  if (segments.size () != 1)
+return false;
+
+  builtin = BuiltinAttributeMappings::get ()->lookup_builtin (
+segments.at (0).get_segment_name ());
+
+  return !builtin.is_error ();
+}
+
+/**
+ * Check that the string given to #[doc(alias = ...)] or #[doc(alias(...))] is
+ * valid.
+ *
+ * This means no whitespace characters other than spaces and no quoting
+ * characters.
+ */
+static void
+check_doc_alias (const std::string _input, const Location )
+{
+  // FIXME: The locus here is for the whole attribute. Can we get the locus
+  // of the alias input instead?
+  for (auto c : alias_input)
+if ((ISSPACE (c) && c != ' ') || c == '\'' || c == '\"')
+  {
+   auto to_print = std::string (1, c);
+   switch (c)
+ {
+ case '\n':
+   to_print = "\\n";
+   break;
+ case '\t':
+   to_print = "\\t";
+   break;
+ default:
+   break;
+ }
+   rust_error_at (locus,
+  "invalid character used in %<#[doc(alias)]%> input: %qs",
+  to_print.c_str ());
+  }
+
+  if (alias_input.empty ())
+return;
+
+  if (alias_input.front () == ' ' || alias_input.back () == ' ')
+

[PATCH Rust front-end v3 31/46] gccrs: Add const checker

2022-10-26 Thread arthur . cohen
From: Arthur Cohen 

Similarly to the unsafe checker, constant evaluation can only be performed
in a few contexts and include restrictions on the Rust language. Should
the user fail to uphold those conditions, errors will be reported and the
compilation pipeline interrupted.

These contexts are as follow:

- Array type length expressions
- Array repeat length expressions
- Constants
- Statics
- Enum discriminants
- Const generic arguments

In these contexts, the user is restricted to calling only functions marked
as `const` or perform arithmetic operations only on certain types, among
other restrictions.
---
 gcc/rust/checks/errors/rust-const-checker.cc | 844 +++
 gcc/rust/checks/errors/rust-const-checker.h  | 189 +
 2 files changed, 1033 insertions(+)
 create mode 100644 gcc/rust/checks/errors/rust-const-checker.cc
 create mode 100644 gcc/rust/checks/errors/rust-const-checker.h

diff --git a/gcc/rust/checks/errors/rust-const-checker.cc 
b/gcc/rust/checks/errors/rust-const-checker.cc
new file mode 100644
index 000..35c61fe03f0
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -0,0 +1,844 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-const-checker.h"
+#include "rust-hir.h"
+#include "rust-hir-expr.h"
+#include "rust-hir-stmt.h"
+#include "rust-hir-item.h"
+
+namespace Rust {
+namespace HIR {
+
+ConstChecker::ConstChecker ()
+  : resolver (*Resolver::Resolver::get ()),
+mappings (*Analysis::Mappings::get ())
+{}
+
+void
+ConstChecker::go (HIR::Crate )
+{
+  for (auto  : crate.items)
+item->accept_vis (*this);
+}
+
+bool
+ConstChecker::is_const_extern_fn (HIR::ExternalFunctionItem )
+{
+  // FIXME: Is it really how we want to handle `rustc_const_stable`
+  // and `rustc_const_unstable`?
+  // TODO: Add these attributes to the attribute check and handle
+  // `stable` and `unstable` as well
+  return std::any_of (
+fn.get_outer_attrs ().begin (), fn.get_outer_attrs ().end (),
+[] (const AST::Attribute ) {
+  // `starts_with` in C++11...
+  return attr.get_path ().as_string ().rfind ("rustc_const_", 0) == 0;
+});
+}
+
+void
+ConstChecker::visit (Lifetime )
+{}
+
+void
+ConstChecker::visit (LifetimeParam _param)
+{}
+
+void
+ConstChecker::visit (PathInExpression )
+{}
+
+void
+ConstChecker::visit (TypePathSegment )
+{}
+
+void
+ConstChecker::visit (TypePathSegmentGeneric )
+{}
+
+void
+ConstChecker::visit (TypePathSegmentFunction )
+{}
+
+void
+ConstChecker::visit (TypePath )
+{}
+
+void
+ConstChecker::visit (QualifiedPathInExpression )
+{}
+
+void
+ConstChecker::visit (QualifiedPathInType )
+{}
+
+void
+ConstChecker::visit (LiteralExpr )
+{}
+
+void
+ConstChecker::visit (BorrowExpr )
+{
+  expr.get_expr ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (DereferenceExpr )
+{
+  expr.get_expr ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (ErrorPropagationExpr )
+{
+  expr.get_expr ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (NegationExpr )
+{
+  expr.get_expr ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (ArithmeticOrLogicalExpr )
+{
+  expr.get_lhs ()->accept_vis (*this);
+  expr.get_rhs ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (ComparisonExpr )
+{
+  expr.get_lhs ()->accept_vis (*this);
+  expr.get_rhs ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (LazyBooleanExpr )
+{
+  expr.get_lhs ()->accept_vis (*this);
+  expr.get_rhs ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (TypeCastExpr )
+{
+  expr.get_expr ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (AssignmentExpr )
+{
+  expr.get_lhs ()->accept_vis (*this);
+  expr.get_rhs ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (CompoundAssignmentExpr )
+{
+  expr.get_left_expr ()->accept_vis (*this);
+  expr.get_right_expr ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (GroupedExpr )
+{
+  expr.get_expr_in_parens ()->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (ArrayElemsValues )
+{
+  for (auto  : elems.get_values ())
+elem->accept_vis (*this);
+}
+
+void
+ConstChecker::visit (ArrayElemsCopied )
+{
+  elems.get_elem_to_copy ()->accept_vis (*this);
+
+  const_context.enter (elems.get_mappings ().get_hirid ());
+
+  elems.get_num_copies_expr ()->accept_vis (*this);
+
+  const_context.exit 

[PATCH Rust front-end v3 23/46] gccrs: Add Base62 implementation

2022-10-26 Thread arthur . cohen
From: Arthur Cohen 

Used for V0 symbol mangling scheme which.
---
 gcc/rust/util/rust-base62.cc | 46 
 gcc/rust/util/rust-base62.h  | 34 ++
 2 files changed, 80 insertions(+)
 create mode 100644 gcc/rust/util/rust-base62.cc
 create mode 100644 gcc/rust/util/rust-base62.h

diff --git a/gcc/rust/util/rust-base62.cc b/gcc/rust/util/rust-base62.cc
new file mode 100644
index 000..bdab23338c3
--- /dev/null
+++ b/gcc/rust/util/rust-base62.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-base62.h"
+
+namespace Rust {
+
+std::string
+base62_integer (uint64_t value)
+{
+  const static std::string base_64
+= "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
+  std::string buffer (128, '\0');
+  size_t idx = 0;
+  size_t base = 62;
+
+  do
+{
+  buffer[idx] = base_64[(value % base)];
+  idx++;
+  value = value / base;
+}
+  while (value != 0);
+
+  std::reverse (buffer.begin (), buffer.begin () + idx);
+  return buffer.substr (0, idx);
+}
+
+} // namespace Rust
+
+// FIXME: Add unit testing using the selftest framework
diff --git a/gcc/rust/util/rust-base62.h b/gcc/rust/util/rust-base62.h
new file mode 100644
index 000..fa610d3e5a4
--- /dev/null
+++ b/gcc/rust/util/rust-base62.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_BASE62_H
+#define RUST_BASE62_H
+
+#include "rust-system.h"
+
+namespace Rust {
+
+/**
+ * Get the Base62 representation of an integer
+ */
+std::string
+base62_integer (uint64_t value);
+
+} // namespace Rust
+
+#endif /* !RUST_BASE62_H */
-- 
2.37.2



[PATCH Rust front-end v3 24/46] gccrs: Add implementation of Optional

2022-10-26 Thread arthur . cohen
From: Arthur Cohen 

Add an Optional class to improve error handling
---
 gcc/rust/util/rust-optional-test.cc | 110 +++
 gcc/rust/util/rust-optional.h   | 278 
 2 files changed, 388 insertions(+)
 create mode 100644 gcc/rust/util/rust-optional-test.cc
 create mode 100644 gcc/rust/util/rust-optional.h

diff --git a/gcc/rust/util/rust-optional-test.cc 
b/gcc/rust/util/rust-optional-test.cc
new file mode 100644
index 000..43fa175fa40
--- /dev/null
+++ b/gcc/rust/util/rust-optional-test.cc
@@ -0,0 +1,110 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-system.h"
+#include "rust-optional.h"
+#include "selftest.h"
+
+#if CHECKING_P
+
+static void
+rust_optional_create ()
+{
+  auto opt = Rust::Optional::some (15);
+
+  ASSERT_TRUE (opt.is_some ());
+  ASSERT_EQ (opt.get (), 15);
+
+  Rust::Optional const_opt = Rust::Optional::some (15);
+  const int  = const_opt.get ();
+
+  ASSERT_EQ (value, 15);
+}
+
+static void
+rust_optional_operators ()
+{
+  auto opt = Rust::Optional::some (15);
+
+  // as bool
+  ASSERT_TRUE (opt);
+
+  // deref
+  ASSERT_EQ (*opt, 15);
+
+  class Methodable
+  {
+  public:
+int method () { return 15; }
+  };
+
+  auto m_opt = Rust::Optional::some (Methodable ());
+  ASSERT_EQ (m_opt->method (), 15);
+}
+
+static void
+rust_optional_take ()
+{
+  auto opt = Rust::Optional::some (15);
+  auto value = opt.take ();
+
+  ASSERT_EQ (value, 15);
+  ASSERT_TRUE (opt.is_none ());
+}
+
+static void
+rust_optional_map ()
+{
+  auto opt = Rust::Optional::some (15);
+  auto twice = opt.map ([] (int value) { return value * 2; });
+
+  ASSERT_FALSE (opt);
+  ASSERT_TRUE (twice);
+  ASSERT_EQ (*twice, 30);
+}
+
+static void
+rust_optional_reference ()
+{
+  auto value = std::vector ();
+  value.emplace_back ("rust");
+  value.emplace_back ("+");
+  value.emplace_back ("gcc");
+  value.emplace_back ("=");
+  value.emplace_back ("<3");
+
+  auto opt = Rust::Optional &>::some (value);
+
+  ASSERT_EQ (opt->at (0), "rust");
+  ASSERT_EQ (opt->at (2), "gcc");
+}
+
+#endif /* #if CHECKING_P */
+
+void
+rust_optional_test ()
+{
+#if CHECKING_P
+  rust_optional_create ();
+  rust_optional_operators ();
+  rust_optional_take ();
+  rust_optional_map ();
+  rust_optional_reference ();
+
+#endif /* #if CHECKING_P */
+}
diff --git a/gcc/rust/util/rust-optional.h b/gcc/rust/util/rust-optional.h
new file mode 100644
index 000..56465400250
--- /dev/null
+++ b/gcc/rust/util/rust-optional.h
@@ -0,0 +1,278 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_OPTIONAL_H
+#define RUST_OPTIONAL_H
+
+#include "config.h"
+#include "rust-system.h"
+
+#include "selftest.h"
+
+namespace Rust {
+
+/**
+ * Tagged union to try and simulate a sum type. This is safer and more 
ergonomic
+ * than one of the two alternatives we're currently using in the compiler:
+ *
+ * 1. Storing a raw pointer, which can be `nullptr` or valid
+ *
+ * This is wildly unsafe, and usable in conjunction with local references, 
stack
+ * variables, or pointers managed elsewhere, which can cause crashes, hard to
+ * debug issues or undefined behavior. Likewise, if you do not check for the
+ * pointer's validity, this will cause a crash.
+ *
+ * 2. Storing an extra boolean alongside the object
+ *
+ * This causes implementors to use a "dummy object": Either an empty version or
+ * an error version. But what happens if what you really wanted to store was
+ * the empty or error version? You can also easily incorporate logic bugs if 
you
+ * forget to check for the associated boolean.
+ *
+ * The `Optional` type has the same 

[PATCH Rust front-end v3 22/46] gccrs: Add Rust ABI enum helpers

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This is a simple helper over an enum of possible ABI options in Rust.
---
 gcc/rust/util/rust-abi.cc | 72 +++
 gcc/rust/util/rust-abi.h  | 45 
 2 files changed, 117 insertions(+)
 create mode 100644 gcc/rust/util/rust-abi.cc
 create mode 100644 gcc/rust/util/rust-abi.h

diff --git a/gcc/rust/util/rust-abi.cc b/gcc/rust/util/rust-abi.cc
new file mode 100644
index 000..6477c3790af
--- /dev/null
+++ b/gcc/rust/util/rust-abi.cc
@@ -0,0 +1,72 @@
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-abi.h"
+
+namespace Rust {
+
+Rust::ABI
+get_abi_from_string (const std::string )
+{
+  if (abi.compare ("rust") == 0)
+return Rust::ABI::RUST;
+  else if (abi.compare ("rust-intrinsic") == 0)
+return Rust::ABI::INTRINSIC;
+  else if (abi.compare ("C") == 0)
+return Rust::ABI::C;
+  else if (abi.compare ("cdecl") == 0)
+return Rust::ABI::CDECL;
+  else if (abi.compare ("stdcall") == 0)
+return Rust::ABI::STDCALL;
+  else if (abi.compare ("fastcall") == 0)
+return Rust::ABI::FASTCALL;
+  else if (abi.compare ("sysv64") == 0)
+return Rust::ABI::SYSV64;
+  else if (abi.compare ("win64") == 0)
+return Rust::ABI::WIN64;
+
+  return Rust::ABI::UNKNOWN;
+}
+
+std::string
+get_string_from_abi (Rust::ABI abi)
+{
+  switch (abi)
+{
+case Rust::ABI::RUST:
+  return "rust";
+case Rust::ABI::INTRINSIC:
+  return "rust-intrinsic";
+case Rust::ABI::C:
+  return "C";
+case Rust::ABI::CDECL:
+  return "cdecl";
+case Rust::ABI::STDCALL:
+  return "stdcall";
+case Rust::ABI::FASTCALL:
+  return "fastcall";
+case Rust::ABI::SYSV64:
+  return "sysv64";
+case Rust::ABI::WIN64:
+  return "win64";
+
+case Rust::ABI::UNKNOWN:
+  return "unknown";
+}
+  return "unknown";
+}
+
+} // namespace Rust
diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h
new file mode 100644
index 000..d794cc35fb3
--- /dev/null
+++ b/gcc/rust/util/rust-abi.h
@@ -0,0 +1,45 @@
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_ABI_OPTIONS_H
+#define RUST_ABI_OPTIONS_H
+
+#include "rust-system.h"
+
+namespace Rust {
+
+enum ABI
+{
+  UNKNOWN,
+  RUST,
+  INTRINSIC,
+  C,
+  CDECL,
+  STDCALL,
+  FASTCALL,
+  WIN64,
+  SYSV64
+};
+
+extern Rust::ABI
+get_abi_from_string (const std::string );
+
+extern std::string
+get_string_from_abi (Rust::ABI abi);
+
+} // namespace Rust
+
+#endif // RUST_ABI_OPTIONS_H
-- 
2.37.2



[PATCH Rust front-end v3 18/46] gccrs: Add HIR definitions and visitor framework

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This patch implements the classes mentionned in the previous HIR patch,
as well as a set of visitor frameworks used in handling that HIR.
---
 gcc/rust/hir/tree/rust-hir-full-decls.h |  232 +
 gcc/rust/hir/tree/rust-hir-full-test.cc | 5292 +++
 gcc/rust/hir/tree/rust-hir-full.h   |   30 +
 gcc/rust/hir/tree/rust-hir-visitor.h|  493 +++
 gcc/rust/hir/tree/rust-hir.h|  921 
 5 files changed, 6968 insertions(+)
 create mode 100644 gcc/rust/hir/tree/rust-hir-full-decls.h
 create mode 100644 gcc/rust/hir/tree/rust-hir-full-test.cc
 create mode 100644 gcc/rust/hir/tree/rust-hir-full.h
 create mode 100644 gcc/rust/hir/tree/rust-hir-visitor.h
 create mode 100644 gcc/rust/hir/tree/rust-hir.h

diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h 
b/gcc/rust/hir/tree/rust-hir-full-decls.h
new file mode 100644
index 000..2798ba9fd84
--- /dev/null
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -0,0 +1,232 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_HIR_FULL_DECLS_H
+#define RUST_HIR_FULL_DECLS_H
+
+namespace Rust {
+namespace HIR {
+
+struct Literal;
+class Stmt;
+class Item;
+class Expr;
+class ExprWithoutBlock;
+class Pattern;
+class Type;
+class TypeNoBounds;
+class TypeParamBound;
+class Lifetime;
+class GenericParam;
+class LifetimeParam;
+
+class TraitItem;
+class ImplItem;
+struct Crate;
+class PathExpr;
+
+// rust-path.h
+class PathIdentSegment;
+struct GenericArgsBinding;
+struct GenericArgs;
+class PathExprSegment;
+class PathPattern;
+class PathInExpression;
+class TypePathSegment;
+class TypePathSegmentGeneric;
+struct TypePathFunction;
+class TypePathSegmentFunction;
+class TypePath;
+struct QualifiedPathType;
+class QualifiedPathInExpression;
+class QualifiedPathInType;
+
+// rust-expr.h
+class ExprWithBlock;
+class LiteralExpr;
+class AttrInputLiteral;
+class OperatorExpr;
+class BorrowExpr;
+class DereferenceExpr;
+class ErrorPropagationExpr;
+class NegationExpr;
+class ArithmeticOrLogicalExpr;
+class ComparisonExpr;
+class LazyBooleanExpr;
+class TypeCastExpr;
+class AssignmentExpr;
+class CompoundAssignmentExpr;
+class GroupedExpr;
+class ArrayElems;
+class ArrayElemsValues;
+class ArrayElemsCopied;
+class ArrayExpr;
+class ArrayIndexExpr;
+class TupleExpr;
+class TupleIndexExpr;
+class StructExpr;
+class StructExprStruct;
+struct StructBase;
+class StructExprField;
+class StructExprFieldIdentifier;
+class StructExprFieldWithVal;
+class StructExprFieldIdentifierValue;
+class StructExprFieldIndexValue;
+class StructExprStructFields;
+class StructExprStructBase;
+class CallExpr;
+class MethodCallExpr;
+class FieldAccessExpr;
+struct ClosureParam;
+class ClosureExpr;
+class ClosureExprInner;
+class BlockExpr;
+class ClosureExprInnerTyped;
+class ContinueExpr;
+class BreakExpr;
+class RangeExpr;
+class RangeFromToExpr;
+class RangeFromExpr;
+class RangeToExpr;
+class RangeFullExpr;
+class RangeFromToInclExpr;
+class RangeToInclExpr;
+class ReturnExpr;
+class UnsafeBlockExpr;
+class LoopLabel;
+class BaseLoopExpr;
+class LoopExpr;
+class WhileLoopExpr;
+class WhileLetLoopExpr;
+class ForLoopExpr;
+class IfExpr;
+class IfExprConseqElse;
+class IfExprConseqIf;
+class IfLetExpr;
+class IfExprConseqIfLet;
+class IfLetExprConseqElse;
+class IfLetExprConseqIf;
+class IfLetExprConseqIfLet;
+struct MatchArm;
+// class MatchCase;
+// class MatchCaseBlockExpr;
+// class MatchCaseExpr;
+struct MatchCase;
+class MatchExpr;
+class AwaitExpr;
+class AsyncBlockExpr;
+
+// rust-stmt.h
+class EmptyStmt;
+class LetStmt;
+class ExprStmt;
+class ExprStmtWithoutBlock;
+class ExprStmtWithBlock;
+
+// rust-item.h
+class TypeParam;
+class ConstGenericParam;
+class WhereClauseItem;
+class LifetimeWhereClauseItem;
+class TypeBoundWhereClauseItem;
+struct WhereClause;
+struct SelfParam;
+struct FunctionQualifiers;
+struct FunctionParam;
+struct Visibility;
+class VisItem;
+class Module;
+class ExternCrate;
+class UseTree;
+class UseTreeGlob;
+class UseTreeList;
+class UseTreeRebind;
+class UseDeclaration;
+class Function;
+class TypeAlias;
+class Struct;
+struct StructField;
+class StructStruct;
+struct TupleField;
+class TupleStruct;
+class EnumItem;
+class EnumItemTuple;
+class EnumItemStruct;
+class EnumItemDiscriminant;
+class Enum;
+class Union;
+class 

[PATCH Rust front-end v3 20/46] gccrs: Add wrapper for make_unique

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This is a wrapper for make_unique we can likely get rid of this as there
are other implementations available or simply keep using the unique_ptr
constructor.
---
 gcc/rust/util/rust-make-unique.h | 35 
 1 file changed, 35 insertions(+)
 create mode 100644 gcc/rust/util/rust-make-unique.h

diff --git a/gcc/rust/util/rust-make-unique.h b/gcc/rust/util/rust-make-unique.h
new file mode 100644
index 000..7b79e625ff1
--- /dev/null
+++ b/gcc/rust/util/rust-make-unique.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_MAKE_UNIQUE_H
+#define RUST_MAKE_UNIQUE_H
+
+#include "rust-system.h"
+
+namespace Rust {
+
+template 
+std::unique_ptr
+make_unique (Ts &&...params)
+{
+  return std::unique_ptr (new T (std::forward (params)...));
+}
+
+} // namespace Rust
+
+#endif // RUST_MAKE_UNIQUE_H
-- 
2.37.2



[PATCH Rust front-end v3 09/46] gccrs: Add definitions of Rust Items in AST data structures

2022-10-26 Thread arthur . cohen
From: The Other 

This adds the proper definitions of our AST Item nodes.

Co-authored-by: Philip Herron 
---
 gcc/rust/ast/rust-item.h | 4382 ++
 1 file changed, 4382 insertions(+)
 create mode 100644 gcc/rust/ast/rust-item.h

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
new file mode 100644
index 000..4987674cba1
--- /dev/null
+++ b/gcc/rust/ast/rust-item.h
@@ -0,0 +1,4382 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_AST_ITEM_H
+#define RUST_AST_ITEM_H
+
+#include "rust-ast.h"
+#include "rust-path.h"
+#include "rust-common.h"
+
+namespace Rust {
+namespace AST {
+// forward decls
+class BlockExpr;
+class TypePath;
+
+// TODO: inline?
+/*struct AbiName {
+std::string abi_name;
+// Technically is meant to be STRING_LITERAL
+
+  public:
+// Returns whether abi name is empty, i.e. doesn't exist.
+bool is_empty() const {
+   return abi_name.empty();
+}
+
+AbiName(std::string name) : abi_name(std::move(name)) {}
+
+// Empty AbiName constructor
+AbiName() {}
+};*/
+
+// A type generic parameter (as opposed to a lifetime generic parameter)
+class TypeParam : public GenericParam
+{
+  // bool has_outer_attribute;
+  // std::unique_ptr outer_attr;
+  Attribute outer_attr;
+
+  Identifier type_representation;
+
+  // bool has_type_param_bounds;
+  // TypeParamBounds type_param_bounds;
+  std::vector>
+type_param_bounds; // inlined form
+
+  // bool has_type;
+  std::unique_ptr type;
+
+  Location locus;
+
+public:
+  Identifier get_type_representation () const { return type_representation; }
+
+  // Returns whether the type of the type param has been specified.
+  bool has_type () const { return type != nullptr; }
+
+  // Returns whether the type param has type param bounds.
+  bool has_type_param_bounds () const { return !type_param_bounds.empty (); }
+
+  // Returns whether the type param has an outer attribute.
+  bool has_outer_attribute () const { return !outer_attr.is_empty (); }
+
+  TypeParam (Identifier type_representation, Location locus = Location (),
+std::vector> type_param_bounds
+= std::vector> (),
+std::unique_ptr type = nullptr,
+Attribute outer_attr = Attribute::create_empty ())
+: GenericParam (Analysis::Mappings::get ()->get_next_node_id ()),
+  outer_attr (std::move (outer_attr)),
+  type_representation (std::move (type_representation)),
+  type_param_bounds (std::move (type_param_bounds)),
+  type (std::move (type)), locus (locus)
+  {}
+
+  // Copy constructor uses clone
+  TypeParam (TypeParam const )
+: GenericParam (other.node_id), outer_attr (other.outer_attr),
+  type_representation (other.type_representation), locus (other.locus)
+  {
+// guard to prevent null pointer dereference
+if (other.type != nullptr)
+  type = other.type->clone_type ();
+
+type_param_bounds.reserve (other.type_param_bounds.size ());
+for (const auto  : other.type_param_bounds)
+  type_param_bounds.push_back (e->clone_type_param_bound ());
+  }
+
+  // Overloaded assignment operator to clone
+  TypeParam = (TypeParam const )
+  {
+type_representation = other.type_representation;
+outer_attr = other.outer_attr;
+locus = other.locus;
+node_id = other.node_id;
+
+// guard to prevent null pointer dereference
+if (other.type != nullptr)
+  type = other.type->clone_type ();
+else
+  type = nullptr;
+
+type_param_bounds.reserve (other.type_param_bounds.size ());
+for (const auto  : other.type_param_bounds)
+  type_param_bounds.push_back (e->clone_type_param_bound ());
+
+return *this;
+  }
+
+  // move constructors
+  TypeParam (TypeParam &) = default;
+  TypeParam = (TypeParam &) = default;
+
+  std::string as_string () const override;
+
+  Location get_locus () const override final { return locus; }
+
+  Kind get_kind () const override final { return Kind::Type; }
+
+  void accept_vis (ASTVisitor ) override;
+
+  // TODO: is this better? Or is a "vis_block" better?
+  std::unique_ptr _type ()
+  {
+rust_assert (type != nullptr);
+return type;
+  }
+
+  // TODO: mutable getter seems kinda dodgy
+  std::vector> _type_param_bounds ()
+  {
+return type_param_bounds;
+ 

[PATCH Rust front-end v3 12/46] gccrs: Add Lexer for Rust front-end

2022-10-26 Thread arthur . cohen
From: The Other 

The lexer is refered to as a ManagedTokenSource within the parser, this
lexer does not currently support unicode but serves as a starting point
to do so.

Co-authored-by: Philip Herron 
Co-authored-by: Arthur Cohen 
Co-authored-by: Mark Wielaard 
---
 gcc/rust/lex/rust-codepoint.h  |   46 +
 gcc/rust/lex/rust-lex.cc   | 2728 
 gcc/rust/lex/rust-lex.h|  271 
 gcc/rust/lex/rust-token.cc |  134 ++
 gcc/rust/lex/rust-token.h  |  450 ++
 gcc/rust/rust-buffered-queue.h |  204 +++
 6 files changed, 3833 insertions(+)
 create mode 100644 gcc/rust/lex/rust-codepoint.h
 create mode 100644 gcc/rust/lex/rust-lex.cc
 create mode 100644 gcc/rust/lex/rust-lex.h
 create mode 100644 gcc/rust/lex/rust-token.cc
 create mode 100644 gcc/rust/lex/rust-token.h
 create mode 100644 gcc/rust/rust-buffered-queue.h

diff --git a/gcc/rust/lex/rust-codepoint.h b/gcc/rust/lex/rust-codepoint.h
new file mode 100644
index 000..1a9f0ca7a21
--- /dev/null
+++ b/gcc/rust/lex/rust-codepoint.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_CODEPOINT_H
+#define RUST_CODEPOINT_H
+
+#include "rust-system.h"
+
+namespace Rust {
+struct Codepoint
+{
+  uint32_t value;
+
+  // Creates a zero codepoint.
+  Codepoint () : value (0) {}
+
+  // Creates a codepoint from an encoded UTF-8 value.
+  Codepoint (uint32_t value) : value (value) {}
+
+  static Codepoint eof () { return Codepoint (UINT32_MAX); }
+  bool is_eof () const { return value == UINT32_MAX; }
+
+  // Returns a C++ string containing string value of codepoint.
+  std::string as_string ();
+
+  bool operator== (Codepoint other) const { return value == other.value; }
+  bool operator!= (Codepoint other) const { return !operator== (other); }
+};
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
new file mode 100644
index 000..82949f5fe5f
--- /dev/null
+++ b/gcc/rust/lex/rust-lex.cc
@@ -0,0 +1,2728 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-system.h"
+#include "rust-lex.h"
+#include "rust-diagnostics.h"
+#include "rust-linemap.h"
+#include "rust-session-manager.h"
+#include "safe-ctype.h"
+
+namespace Rust {
+// TODO: move to separate compilation unit?
+// overload += for uint32_t to allow 32-bit encoded utf-8 to be added
+std::string &
+operator+= (std::string , Codepoint char32)
+{
+  if (char32.value < 0x80)
+{
+  str += static_cast (char32.value);
+}
+  else if (char32.value < (0x1F + 1) << (1 * 6))
+{
+  str += static_cast (0xC0 | ((char32.value >> 6) & 0x1F));
+  str += static_cast (0x80 | ((char32.value >> 0) & 0x3F));
+}
+  else if (char32.value < (0x0F + 1) << (2 * 6))
+{
+  str += static_cast (0xE0 | ((char32.value >> 12) & 0x0F));
+  str += static_cast (0x80 | ((char32.value >> 6) & 0x3F));
+  str += static_cast (0x80 | ((char32.value >> 0) & 0x3F));
+}
+  else if (char32.value < (0x07 + 1) << (3 * 6))
+{
+  str += static_cast (0xF0 | ((char32.value >> 18) & 0x07));
+  str += static_cast (0x80 | ((char32.value >> 12) & 0x3F));
+  str += static_cast (0x80 | ((char32.value >> 6) & 0x3F));
+  str += static_cast (0x80 | ((char32.value >> 0) & 0x3F));
+}
+  else
+{
+  rust_debug ("Invalid unicode codepoint found: '%u' ", char32.value);
+}
+  return str;
+}
+
+std::string
+Codepoint::as_string ()
+{
+  std::string str;
+
+  // str += Codepoint (value);
+  str += *this;
+
+  return str;
+}
+
+/* Includes all allowable float digits EXCEPT _ and . as that needs lookahead
+ * 

[PATCH Rust front-end v3 03/46] gccrs: Add Debug info testsuite

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This testsuite is specifically about testcases which scan the asm debug
info for results.

Co-authored-by: Tom Tromey 
---
 gcc/testsuite/rust/debug/chartype.rs  | 10 ++
 .../rust/debug/custom_link_section.rs | 13 
 gcc/testsuite/rust/debug/debug.exp| 33 +++
 gcc/testsuite/rust/debug/i8u8.rs  | 12 +++
 gcc/testsuite/rust/debug/lang.rs  |  6 
 gcc/testsuite/rust/debug/no_mangle.rs | 17 ++
 gcc/testsuite/rust/debug/oldlang.rs   |  6 
 gcc/testsuite/rust/debug/tuple.rs |  8 +
 gcc/testsuite/rust/debug/win64-abi.rs | 11 +++
 9 files changed, 116 insertions(+)
 create mode 100644 gcc/testsuite/rust/debug/chartype.rs
 create mode 100644 gcc/testsuite/rust/debug/custom_link_section.rs
 create mode 100644 gcc/testsuite/rust/debug/debug.exp
 create mode 100644 gcc/testsuite/rust/debug/i8u8.rs
 create mode 100644 gcc/testsuite/rust/debug/lang.rs
 create mode 100644 gcc/testsuite/rust/debug/no_mangle.rs
 create mode 100644 gcc/testsuite/rust/debug/oldlang.rs
 create mode 100644 gcc/testsuite/rust/debug/tuple.rs
 create mode 100644 gcc/testsuite/rust/debug/win64-abi.rs

diff --git a/gcc/testsuite/rust/debug/chartype.rs 
b/gcc/testsuite/rust/debug/chartype.rs
new file mode 100644
index 000..69e7ab0b17f
--- /dev/null
+++ b/gcc/testsuite/rust/debug/chartype.rs
@@ -0,0 +1,10 @@
+// 'char' should use DW_ATE_UTF
+fn main () {
+let c = 'x';
+// { dg-do compile }
+// Use -w to avoid warnings about the unused variables
+// DW_ATE_UTF entered in DWARF 4.
+// { dg-options "-w -gdwarf-4 -dA" }
+// DW_ATE_UTF = 0x10
+// { dg-final { scan-assembler "0x10\[ \t]\[^\n\r]* DW_AT_encoding" } } */
+}
diff --git a/gcc/testsuite/rust/debug/custom_link_section.rs 
b/gcc/testsuite/rust/debug/custom_link_section.rs
new file mode 100644
index 000..142f3513136
--- /dev/null
+++ b/gcc/testsuite/rust/debug/custom_link_section.rs
@@ -0,0 +1,13 @@
+#[link_section = ".universe"]
+fn not_in_text() -> i32 {
+42
+}
+
+fn main() -> i32 {
+// { dg-do compile }
+// { dg-options "-gdwarf-5 -dA -w" }
+not_in_text();
+// { dg-final { scan-assembler ".universe" } } */
+
+0
+}
diff --git a/gcc/testsuite/rust/debug/debug.exp 
b/gcc/testsuite/rust/debug/debug.exp
new file mode 100644
index 000..c71b5930d90
--- /dev/null
+++ b/gcc/testsuite/rust/debug/debug.exp
@@ -0,0 +1,33 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+# Debugging tests.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "compile"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/debug/i8u8.rs b/gcc/testsuite/rust/debug/i8u8.rs
new file mode 100644
index 000..1cd21a4a8ff
--- /dev/null
+++ b/gcc/testsuite/rust/debug/i8u8.rs
@@ -0,0 +1,12 @@
+// i8 and u8 types should not have the DWARF 'char' encoding.
+fn main () {
+let x : i8 = 5;
+let y : u8 = 7;
+// { dg-do compile }
+// Use -w to avoid warnings about the unused variables
+// { dg-options "-w -g -dA" }
+// DW_ATE_signed_char = 6
+// { dg-final { scan-assembler-not "0x6\[ \t]\[^\n\r]* DW_AT_encoding" } } */
+// DW_ATE_unsigned_char = 8
+// { dg-final { scan-assembler-not "0x8\[ \t]\[^\n\r]* DW_AT_encoding" } } */
+}
diff --git a/gcc/testsuite/rust/debug/lang.rs b/gcc/testsuite/rust/debug/lang.rs
new file mode 100644
index 000..12e0b587a02
--- /dev/null
+++ b/gcc/testsuite/rust/debug/lang.rs
@@ -0,0 +1,6 @@
+fn main () {
+// { dg-do compile }
+// { dg-options "-gdwarf-5 -dA" }
+// DW_LANG_Rust is 0x1c
+// { dg-final { scan-assembler "0x1c\[ \t]\[^\n\r]* DW_AT_language" } } */
+}
diff --git a/gcc/testsuite/rust/debug/no_mangle.rs 
b/gcc/testsuite/rust/debug/no_mangle.rs
new file mode 100644
index 000..0cef40482f4
--- /dev/null
+++ b/gcc/testsuite/rust/debug/no_mangle.rs
@@ -0,0 +1,17 @@
+#[no_mangle]
+fn do_not_mangle() -> i32 {
+0 
+}
+
+fn please_mangle() {}
+
+fn main() {
+// { dg-do compile }
+// { dg-options "-gdwarf-5 -dA" }
+let _ = do_not_mangle();
+please_mangle();
+// look for 

[PATCH Rust front-end v3 07/46] gccrs: Add gcc-check-target check-rust

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This allows us to invoke the rust testsuite.

ChangeLog:
* Makefile.def: Add Rust language.
* Makefile.in: Regenerate via autogen.
---
 Makefile.def | 1 +
 Makefile.in  | 8 
 2 files changed, 9 insertions(+)

diff --git a/Makefile.def b/Makefile.def
index 3291b126b26..821016af3a2 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -681,6 +681,7 @@ languages = { language=go;  gcc-check-target=check-go;
 languages = { language=d;  gcc-check-target=check-d;
lib-check-target=check-target-libphobos; };
 languages = { language=jit;gcc-check-target=check-jit; };
+languages = { language=rust;   gcc-check-target=check-rust; };
 
 // Toplevel bootstrap
 bootstrap_stage = { id=1 ; };
diff --git a/Makefile.in b/Makefile.in
index 1919dfee829..9ed2c0dec52 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60583,6 +60583,14 @@ check-gcc-jit:
(cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-jit);
 check-jit: check-gcc-jit
 
+.PHONY: check-gcc-rust check-rust
+check-gcc-rust:
+   r=`${PWD_COMMAND}`; export r; \
+   s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+   $(HOST_EXPORTS) \
+   (cd gcc && $(MAKE) $(GCC_FLAGS_TO_PASS) check-rust);
+check-rust: check-gcc-rust
+
 
 # The gcc part of install-no-fixedincludes, which relies on an intimate
 # knowledge of how a number of gcc internal targets (inter)operate.  Delegate.
-- 
2.37.2



[PATCH Rust front-end v3 11/46] gccrs: Add Rust AST visitors

2022-10-26 Thread arthur . cohen
From: The Other 

This patch contains the basic framework of our AST visitors, as well as
one aimed at pretty-printing and exporting these AST nodes

Co-authored-by: Philip Herron 
Co-authored-by: Arthur Cohen 
---
 gcc/rust/ast/rust-ast-dump.cc| 1089 ++
 gcc/rust/ast/rust-ast-dump.h |  246 ++
 gcc/rust/ast/rust-ast-visitor.h  |  234 ++
 gcc/rust/ast/rust-cond-compilation.h |  249 ++
 4 files changed, 1818 insertions(+)
 create mode 100644 gcc/rust/ast/rust-ast-dump.cc
 create mode 100644 gcc/rust/ast/rust-ast-dump.h
 create mode 100644 gcc/rust/ast/rust-ast-visitor.h
 create mode 100644 gcc/rust/ast/rust-cond-compilation.h

diff --git a/gcc/rust/ast/rust-ast-dump.cc b/gcc/rust/ast/rust-ast-dump.cc
new file mode 100644
index 000..ad9ad0b7de7
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-dump.cc
@@ -0,0 +1,1089 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-ast-dump.h"
+
+namespace Rust {
+namespace AST {
+
+Indent::Indent () : tabs (0) {}
+
+std::ostream &
+operator<< (std::ostream , const Indent )
+{
+  return stream << std::string (indent.tabs, '\t');
+}
+
+void
+Indent::increment ()
+{
+  tabs++;
+}
+
+void
+Indent::decrement ()
+{
+  rust_assert (tabs != 0);
+  tabs--;
+}
+
+Dump::Dump (std::ostream ) : stream (stream), indentation (Indent ()) {}
+
+void
+Dump::go (AST::Crate )
+{
+  for (auto  : crate.items)
+{
+  stream << indentation;
+  item->accept_vis (*this);
+  stream << "\n";
+}
+}
+
+void
+Dump::go (AST::Item )
+{
+  item.accept_vis (*this);
+}
+
+void
+Dump::format_function_param (FunctionParam )
+{
+  param.get_pattern ()->accept_vis (*this);
+  stream << ": ";
+  param.get_type ()->accept_vis (*this);
+}
+
+void
+Dump::emit_attrib (const Attribute )
+{
+  stream << "#";
+  stream << "[";
+
+  for (size_t i = 0; i < attrib.get_path ().get_segments ().size (); i++)
+{
+  const auto  = attrib.get_path ().get_segments ().at (i);
+  bool has_next = (i + 1) < attrib.get_path ().get_segments ().size ();
+
+  stream << seg.get_segment_name ();
+  if (has_next)
+   stream << "::";
+}
+
+  if (attrib.has_attr_input ())
+{
+  stream << " = ";
+
+  bool is_literal = attrib.get_attr_input ().get_attr_input_type ()
+   == AST::AttrInput::AttrInputType::LITERAL;
+  if (is_literal)
+   {
+ auto 
+   = static_cast (attrib.get_attr_input ());
+ const auto  = literal.get_literal ().as_string ();
+
+ stream << "\"" << value << "\"";
+   }
+  else
+   {
+ stream << "FIXME";
+   }
+}
+
+  stream << "]";
+}
+
+void
+Dump::visit (Token )
+{}
+
+void
+Dump::visit (DelimTokenTree _tok_tree)
+{}
+
+void
+Dump::visit (AttrInputMetaItemContainer )
+{}
+
+void
+Dump::visit (IdentifierExpr _expr)
+{
+  stream << ident_expr.get_ident ();
+}
+
+void
+Dump::visit (Lifetime )
+{}
+
+void
+Dump::visit (LifetimeParam _param)
+{}
+
+void
+Dump::visit (ConstGenericParam _param)
+{}
+
+// rust-path.h
+void
+Dump::visit (PathInExpression )
+{}
+
+void
+Dump::visit (TypePathSegment )
+{}
+
+void
+Dump::visit (TypePathSegmentGeneric )
+{}
+
+void
+Dump::visit (TypePathSegmentFunction )
+{}
+
+void
+Dump::visit (TypePath )
+{
+  stream << path.as_string ();
+}
+
+void
+Dump::visit (QualifiedPathInExpression )
+{}
+
+void
+Dump::visit (QualifiedPathInType )
+{}
+
+// rust-expr.h
+void
+Dump::visit (LiteralExpr )
+{
+  stream << expr.as_string ();
+}
+
+void
+Dump::visit (AttrInputLiteral _input)
+{}
+
+void
+Dump::visit (MetaItemLitExpr _item)
+{}
+
+void
+Dump::visit (MetaItemPathLit _item)
+{}
+
+void
+Dump::visit (BorrowExpr )
+{}
+
+void
+Dump::visit (DereferenceExpr )
+{}
+
+void
+Dump::visit (ErrorPropagationExpr )
+{}
+
+void
+Dump::visit (NegationExpr )
+{}
+
+void
+Dump::visit (ArithmeticOrLogicalExpr )
+{
+  expr.get_left_expr ()->accept_vis (*this);
+  stream << " ";
+
+  switch (expr.get_expr_type ())
+{
+case ArithmeticOrLogicalOperator::ADD:
+  stream << "+";
+  break;
+
+case ArithmeticOrLogicalOperator::SUBTRACT:
+  stream << "-";
+  break;
+
+case ArithmeticOrLogicalOperator::MULTIPLY:
+  stream << "*";
+  break;
+
+case ArithmeticOrLogicalOperator::DIVIDE:
+  stream << 

[PATCH Rust front-end v3 02/46] gccrs: Add nessecary hooks for a Rust front-end testsuite

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This copy's over code from other front-end testsuites to enable testing
for the rust front-end specifically.

Co-authored-by: Marc Poulhiès 
Co-authored-by: Thomas Schwinge 
---
 gcc/testsuite/lib/rust-dg.exp |  49 +
 gcc/testsuite/lib/rust.exp| 186 ++
 2 files changed, 235 insertions(+)
 create mode 100644 gcc/testsuite/lib/rust-dg.exp
 create mode 100644 gcc/testsuite/lib/rust.exp

diff --git a/gcc/testsuite/lib/rust-dg.exp b/gcc/testsuite/lib/rust-dg.exp
new file mode 100644
index 000..a8a2ac0c8eb
--- /dev/null
+++ b/gcc/testsuite/lib/rust-dg.exp
@@ -0,0 +1,49 @@
+# Copyright (C) 1997-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+load_lib gcc-dg.exp
+
+# Define rust callbacks for dg.exp.
+
+proc rust-dg-test { prog do_what extra_tool_flags } {
+return [gcc-dg-test-1 rust_target_compile $prog $do_what $extra_tool_flags]
+}
+
+proc rust-dg-prune { system text } {
+return [gcc-dg-prune $system $text]
+}
+
+# Utility routines.
+
+#
+# rust_load -- wrapper around default rust_load to handle tests that
+# require program arguments passed to them.
+#
+
+if { [info procs rust_load] != [list] \
+  && [info procs prev_rust_load] == [list] } {
+rename rust_load prev_rust_load
+
+proc rust_load { program args } {
+   global RUST_EXECUTE_ARGS
+   if [info exists RUST_EXECUTE_ARGS] then {
+   set args [concat "{$RUST_EXECUTE_ARGS}"]
+   }
+   set result [eval [list prev_rust_load $program] $args ]
+   return $result
+}
+}
+
diff --git a/gcc/testsuite/lib/rust.exp b/gcc/testsuite/lib/rust.exp
new file mode 100644
index 000..6993c976304
--- /dev/null
+++ b/gcc/testsuite/lib/rust.exp
@@ -0,0 +1,186 @@
+# Copyright (C) 2012-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+#
+# rust support library routines
+#
+
+load_lib prune.exp
+load_lib gcc-defs.exp
+load_lib timeout.exp
+load_lib target-libpath.exp
+
+#
+# RUST_UNDER_TEST is the compiler under test.
+#
+
+set rust_compile_options ""
+
+
+#
+# rust_include_flags -- include flags for the gcc tree structure
+#
+
+proc rust_include_flags { paths } {
+global srcdir
+global TESTING_IN_BUILD_TREE
+
+set flags ""
+
+if { [is_remote host] || ![info exists TESTING_IN_BUILD_TREE] } {
+   return "${flags}"
+}
+
+set gccpath ${paths}
+
+return "$flags"
+}
+
+#
+# rust_link_flags -- linker flags for the gcc tree structure
+#
+
+proc rust_link_flags { paths } {
+global srcdir
+global ld_library_path
+global RUST_UNDER_TEST
+global shlib_ext
+global SHARED_OPTION
+
+set gccpath ${paths}
+set libio_dir ""
+set flags ""
+set ld_library_path "."
+set shlib_ext [get_shlib_extension]
+set SHARED_OPTION ""
+verbose "shared lib extension: $shlib_ext"
+
+set_ld_library_path_env_vars
+
+return "$flags"
+}
+
+#
+# rust_init -- called at the start of each subdir of tests
+#
+
+proc rust_init { args } {
+global subdir
+global rust_initialized
+global base_dir
+global tmpdir
+global libdir
+global gluefile wrap_flags
+global objdir srcdir
+global ALWAYS_RUSTFLAGS
+global TOOL_EXECUTABLE TOOL_OPTIONS
+global RUST_UNDER_TEST
+global TESTING_IN_BUILD_TREE
+global TEST_ALWAYS_FLAGS
+global gcc_warning_prefix
+global gcc_error_prefix
+
+# We set LC_ALL and LANG to C so that we get the same error messages as 
expected.
+setenv LC_ALL C
+setenv LANG C
+
+if ![info exists RUST_UNDER_TEST] then {
+   if [info exists TOOL_EXECUTABLE] {
+   set RUST_UNDER_TEST $TOOL_EXECUTABLE
+   } else {
+   if { 

[PATCH Rust front-end v3 04/46] gccrs: Add link cases testsuite

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This testsuite is heavily inspired from the lto testsuite which uses a
pattern that each file is compiled to an object file and finally linked
together. Since rust does not have headers/prototypes we rely on the
ordering here so that all files numbered greater than zero get compiled to
object files first leaving the _0 file free to test the 'extern crate' and
use keywords to force testing of the compiler to read metadata from the
other 'crates'.
---
 gcc/testsuite/rust/link/generic_function_0.rs |   7 +
 gcc/testsuite/rust/link/generic_function_1.rs |   3 +
 gcc/testsuite/rust/link/link.exp  | 172 ++
 gcc/testsuite/rust/link/simple_function_0.rs  |   8 +
 gcc/testsuite/rust/link/simple_function_1.rs  |   3 +
 gcc/testsuite/rust/link/trait_import_0.rs |  19 ++
 gcc/testsuite/rust/link/trait_import_1.rs |   6 +
 7 files changed, 218 insertions(+)
 create mode 100644 gcc/testsuite/rust/link/generic_function_0.rs
 create mode 100644 gcc/testsuite/rust/link/generic_function_1.rs
 create mode 100644 gcc/testsuite/rust/link/link.exp
 create mode 100644 gcc/testsuite/rust/link/simple_function_0.rs
 create mode 100644 gcc/testsuite/rust/link/simple_function_1.rs
 create mode 100644 gcc/testsuite/rust/link/trait_import_0.rs
 create mode 100644 gcc/testsuite/rust/link/trait_import_1.rs

diff --git a/gcc/testsuite/rust/link/generic_function_0.rs 
b/gcc/testsuite/rust/link/generic_function_0.rs
new file mode 100644
index 000..58b8eb13db6
--- /dev/null
+++ b/gcc/testsuite/rust/link/generic_function_0.rs
@@ -0,0 +1,7 @@
+extern crate generic_function_1;
+use generic_function_1::generic_function;
+
+fn main() -> i32 {
+let a = generic_function(123);
+a - 123
+}
diff --git a/gcc/testsuite/rust/link/generic_function_1.rs 
b/gcc/testsuite/rust/link/generic_function_1.rs
new file mode 100644
index 000..8fb0788e388
--- /dev/null
+++ b/gcc/testsuite/rust/link/generic_function_1.rs
@@ -0,0 +1,3 @@
+pub fn generic_function(a: X) -> X {
+a
+}
diff --git a/gcc/testsuite/rust/link/link.exp b/gcc/testsuite/rust/link/link.exp
new file mode 100644
index 000..8b2e93ceab6
--- /dev/null
+++ b/gcc/testsuite/rust/link/link.exp
@@ -0,0 +1,172 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# .
+
+# Execute tests, torture testing.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "assemble"
+
+# rs-obj -- compile to an object file
+#
+# SOURCE is the source file
+# DEST is the object file
+# OPTALL is the list of compiler options to use with all tests
+# OPTFILE is the list of compiler options to use with this file
+# OPTSTR is the options to print with test messages
+# XFAILDATA is the xfail data to be passed to the compiler
+proc rs-obj { source dest optall optfile optstr xfaildata } {
+global tool
+global compiler_conditional_xfail_data
+
+# Set up the options for compiling this file.
+set options ""
+lappend options "additional_flags=$optall $optfile"
+
+set compiler_conditional_xfail_data $xfaildata
+set comp_output [${tool}_target_compile "$source" "$dest" object $options]
+}
+
+# rs-execute -- compile multi-file tests
+#
+# SRC1 is the full pathname of the main file of the testcase.
+# SID identifies a test suite in the names of temporary files.
+proc rs-execute-1 { src1 } {
+global srcdir tmpdir
+
+# Get extra flags for this test from the primary source file, and
+# process other dg-* options that this suite supports.  Warn about
+# unsupported flags.
+verbose "rs-execute: $src1" 1
+set compile_type "run"
+set compile_xfail(0) "" 
+
+# Set up the names of the other source files.
+set dir [file dirname $src1]
+set base [file rootname $src1]
+set base [string range $base [string length $dir] end]
+regsub "_0" $base "" base
+regsub "/" $base "" base
+set src_list $src1
+set i 1
+set done 0
+while { !$done } {
+   set names [glob -nocomplain -types f -- "${dir}/${base}_${i}.*"]
+   if { [llength ${names}] > 1 } {
+   warning "rs-link-execute: more than one file matched 
${dir}/${base}_${i}.*"
+   }
+   if { [llength ${names}] == 1 } {
+   

[PATCH Rust front-end v3 06/46] gccrs: Add execution test cases

2022-10-26 Thread arthur . cohen
From: Philip Herron 

This is similar to the compile/torture/*.rs test cases but all of these are
dg-execute testcases so they get compiled, linked and executed by default,
all the while being compiled with the matrix of torture options.

The only caveat here is that currently gccrs does not currently support
the main shim yet so we have a C-style main function here returning zero
which is not supported in Rustc.

Co-authored-by: Arthur Cohen 
Co-authored-by: Thomas Schwinge 
Co-authored-by: Mark Wielaard 
Co-authored-by: Marc Poulhiès 
---
 .../rust/execute/torture/block_expr1.rs   |   8 +
 .../rust/execute/torture/builtin_macro_cfg.rs |  32 
 .../execute/torture/builtin_macro_concat.rs   |  29 +++
 .../rust/execute/torture/builtin_macro_env.rs |  31 
 .../torture/builtin_macro_include_bytes.rs|  46 +
 .../torture/builtin_macro_include_str.rs  |  27 +++
 .../execute/torture/builtin_macro_line.rs |  25 +++
 .../rust/execute/torture/builtin_macros1.rs   |  21 +++
 .../rust/execute/torture/builtin_macros3.rs   |  28 +++
 gcc/testsuite/rust/execute/torture/cfg1.rs|  32 
 gcc/testsuite/rust/execute/torture/cfg2.rs|  31 
 gcc/testsuite/rust/execute/torture/cfg3.rs|  37 
 gcc/testsuite/rust/execute/torture/cfg4.rs|  38 
 gcc/testsuite/rust/execute/torture/cfg5.rs|  13 ++
 .../rust/execute/torture/coercion1.rs |  41 +
 .../rust/execute/torture/coercion2.rs |  39 
 .../rust/execute/torture/const_fold1.rs   |  13 ++
 .../rust/execute/torture/const_fold2.rs   |  16 ++
 .../execute/torture/copy_nonoverlapping1.rs   |  17 ++
 .../rust/execute/torture/empty_main.rs|   3 +
 .../rust/execute/torture/execute.exp  |  33 
 .../rust/execute/torture/exit_error.rs|   5 +
 .../rust/execute/torture/extern_mod4.rs   |  19 ++
 gcc/testsuite/rust/execute/torture/func1.rs   |   5 +
 .../rust/execute/torture/helloworld1.rs   |  15 ++
 .../rust/execute/torture/helloworld2.rs   |  15 ++
 .../rust/execute/torture/include.txt  |   1 +
 gcc/testsuite/rust/execute/torture/index1.rs  |  28 +++
 .../rust/execute/torture/issue-1120.rs| 123 +
 .../rust/execute/torture/issue-1133.rs| 146 +++
 .../rust/execute/torture/issue-1198.rs|  75 
 .../rust/execute/torture/issue-1231.rs|  36 
 .../rust/execute/torture/issue-1232.rs| 159 
 .../rust/execute/torture/issue-1249.rs|  39 
 .../rust/execute/torture/issue-1436.rs| 172 ++
 .../rust/execute/torture/issue-1496.rs|  75 
 .../rust/execute/torture/issue-647.rs |  33 
 .../rust/execute/torture/issue-845.rs |  47 +
 .../rust/execute/torture/issue-851.rs |  35 
 .../rust/execute/torture/issue-858.rs |  32 
 .../rust/execute/torture/issue-976.rs |  14 ++
 .../rust/execute/torture/issue-995.rs |   9 +
 gcc/testsuite/rust/execute/torture/macros1.rs |  13 ++
 .../rust/execute/torture/macros10.rs  |  22 +++
 .../rust/execute/torture/macros11.rs  |  25 +++
 .../rust/execute/torture/macros12.rs  |  22 +++
 .../rust/execute/torture/macros13.rs  |  22 +++
 .../rust/execute/torture/macros14.rs  |  22 +++
 .../rust/execute/torture/macros16.rs  |  14 ++
 .../rust/execute/torture/macros17.rs  |  17 ++
 .../rust/execute/torture/macros18.rs  |  14 ++
 .../rust/execute/torture/macros19.rs  |  14 ++
 gcc/testsuite/rust/execute/torture/macros2.rs |  40 
 .../rust/execute/torture/macros20.rs  |  14 ++
 .../rust/execute/torture/macros21.rs  |  15 ++
 .../rust/execute/torture/macros22.rs  |  27 +++
 .../rust/execute/torture/macros23.rs  |  19 ++
 .../rust/execute/torture/macros24.rs  |   9 +
 .../rust/execute/torture/macros25.rs  |  13 ++
 .../rust/execute/torture/macros26.rs  |  12 ++
 .../rust/execute/torture/macros27.rs  |  24 +++
 .../rust/execute/torture/macros28.rs  |  13 ++
 .../rust/execute/torture/macros29.rs  |  24 +++
 gcc/testsuite/rust/execute/torture/macros3.rs |  61 +++
 .../rust/execute/torture/macros30.rs  |  25 +++
 .../rust/execute/torture/macros31.rs  |  32 
 gcc/testsuite/rust/execute/torture/macros4.rs |  15 ++
 gcc/testsuite/rust/execute/torture/macros5.rs |  13 ++
 gcc/testsuite/rust/execute/torture/macros6.rs |  12 ++
 gcc/testsuite/rust/execute/torture/macros7.rs |  28 +++
 gcc/testsuite/rust/execute/torture/macros8.rs |  27 +++
 gcc/testsuite/rust/execute/torture/macros9.rs |  28 +++
 gcc/testsuite/rust/execute/torture/match1.rs  |  58 ++
 gcc/testsuite/rust/execute/torture/match2.rs  |  41 +
 gcc/testsuite/rust/execute/torture/match3.rs  |  51 ++
 .../rust/execute/torture/match_bool1.rs   |  49 +
 .../rust/execute/torture/match_byte1.rs   |  56 ++
 

Rust frontend patches v3

2022-10-26 Thread arthur . cohen
This is the fixed version of our previous patch set for gccrs - We've adressed
the comments raised in our previous emails.

This patch set does not contain any work that was not previously included, such
as closure support, the constant evaluator port, or the better implementation
of target hooks by Iain Buclaw. They will follow up in subsequent patch sets.

Thanks again to Open Source Security, inc and Embecosm who have accompanied us
for this work.

Many thanks to all of the contributors and our community, who made this
possible.

A very special thanks to Philip Herron, without whose mentoring I would have
never been in a position to send these patches.

You can see the current status of our work on our branch:
https://gcc.gnu.org/git/?p=gcc.git;a=shortlog;h=refs/heads/devel/rust/master

The patch set contains the following:

[PATCH Rust front-end v3 01/46] Use DW_ATE_UTF for the Rust 'char'
[PATCH Rust front-end v3 02/46] gccrs: Add nessecary hooks for a Rust
[PATCH Rust front-end v3 03/46] gccrs: Add Debug info testsuite
[PATCH Rust front-end v3 04/46] gccrs: Add link cases testsuite
[PATCH Rust front-end v3 05/46] gccrs: Add general compilation test
[PATCH Rust front-end v3 06/46] gccrs: Add execution test cases
[PATCH Rust front-end v3 07/46] gccrs: Add gcc-check-target
[PATCH Rust front-end v3 08/46] gccrs: Add Rust front-end base AST
[PATCH Rust front-end v3 09/46] gccrs: Add definitions of Rust Items
[PATCH Rust front-end v3 10/46] gccrs: Add full definitions of Rust
[PATCH Rust front-end v3 11/46] gccrs: Add Rust AST visitors
[PATCH Rust front-end v3 12/46] gccrs: Add Lexer for Rust front-end
[PATCH Rust front-end v3 13/46] gccrs: Add Parser for Rust front-end
[PATCH Rust front-end v3 14/46] gccrs: Add Parser for Rust front-end
[PATCH Rust front-end v3 15/46] gccrs: Add expansion pass for the
[PATCH Rust front-end v3 16/46] gccrs: Add name resolution pass to
[PATCH Rust front-end v3 17/46] gccrs: Add declarations for Rust HIR
[PATCH Rust front-end v3 18/46] gccrs: Add HIR definitions and
[PATCH Rust front-end v3 19/46] gccrs: Add AST to HIR lowering pass
[PATCH Rust front-end v3 20/46] gccrs: Add wrapper for make_unique
[PATCH Rust front-end v3 21/46] gccrs: Add port of FNV hash used
[PATCH Rust front-end v3 22/46] gccrs: Add Rust ABI enum helpers
[PATCH Rust front-end v3 23/46] gccrs: Add Base62 implementation
[PATCH Rust front-end v3 24/46] gccrs: Add implementation of Optional
[PATCH Rust front-end v3 25/46] gccrs: Add attributes checker
[PATCH Rust front-end v3 26/46] gccrs: Add helpers mappings canonical
[PATCH Rust front-end v3 27/46] gccrs: Add type resolution and trait
[PATCH Rust front-end v3 28/46] gccrs: Add Rust type information
[PATCH Rust front-end v3 29/46] gccrs: Add remaining type system
[PATCH Rust front-end v3 30/46] gccrs: Add unsafe checks for Rust
[PATCH Rust front-end v3 31/46] gccrs: Add const checker
[PATCH Rust front-end v3 32/46] gccrs: Add privacy checks
[PATCH Rust front-end v3 33/46] gccrs: Add dead code scan on HIR
[PATCH Rust front-end v3 34/46] gccrs: Add unused variable scan
[PATCH Rust front-end v3 35/46] gccrs: Add metadata ouptput pass
[PATCH Rust front-end v3 36/46] gccrs: Add base for HIR to GCC
[PATCH Rust front-end v3 37/46] gccrs: Add HIR to GCC GENERIC
[PATCH Rust front-end v3 38/46] gccrs: Add HIR to GCC GENERIC
[PATCH Rust front-end v3 39/46] gccrs: These are wrappers ported from
[PATCH Rust front-end v3 40/46] gccrs: Add GCC Rust front-end
[PATCH Rust front-end v3 41/46] gccrs: Add config-lang.in
[PATCH Rust front-end v3 42/46] gccrs: Add lang-spec.h
[PATCH Rust front-end v3 43/46] gccrs: Add lang.opt
[PATCH Rust front-end v3 44/46] gccrs: Add compiler driver
[PATCH Rust front-end v3 45/46] gccrs: Compiler proper interface
[PATCH Rust front-end v3 46/46] gccrs: Add README, CONTRIBUTING and



[PATCH Rust front-end v3 01/46] Use DW_ATE_UTF for the Rust 'char' type

2022-10-26 Thread arthur . cohen
From: Tom Tromey 

The Rust 'char' type should use the DWARF DW_ATE_UTF encoding.
---
 gcc/dwarf2out.cc | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index e3920c898f5..a8bccbabca4 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -5600,6 +5600,16 @@ is_fortran (const_tree decl)
   return is_fortran ();
 }
 
+/* Return TRUE if the language is Rust.  */
+
+static inline bool
+is_rust ()
+{
+  unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
+
+  return lang == DW_LANG_Rust || lang == DW_LANG_Rust_old;
+}
+
 /* Return TRUE if the language is Ada.  */
 
 static inline bool
@@ -13231,7 +13241,11 @@ base_type_die (tree type, bool reverse)
}
   if (TYPE_STRING_FLAG (type))
{
- if (TYPE_UNSIGNED (type))
+ if ((dwarf_version >= 4 || !dwarf_strict)
+ && is_rust ()
+ && int_size_in_bytes (type) == 4)
+   encoding = DW_ATE_UTF;
+ else if (TYPE_UNSIGNED (type))
encoding = DW_ATE_unsigned_char;
  else
encoding = DW_ATE_signed_char;
@@ -25201,6 +25215,13 @@ gen_compile_unit_die (const char *filename)
 }
   else if (strcmp (language_string, "GNU F77") == 0)
 language = DW_LANG_Fortran77;
+  else if (strcmp (language_string, "GNU Rust") == 0)
+{
+  if (dwarf_version >= 5 || !dwarf_strict)
+   language = DW_LANG_Rust;
+  else
+   language = DW_LANG_Rust_old;
+}
   else if (dwarf_version >= 3 || !dwarf_strict)
 {
   if (strcmp (language_string, "GNU Ada") == 0)
-- 
2.37.2



Re: [PATCH] [PR tree-optimization/107394] Canonicalize global franges as they are read back.

2022-10-26 Thread Aldy Hernandez via Gcc-patches
Updated tested patch.

Aldy

On Tue, Oct 25, 2022 at 11:02 PM Aldy Hernandez  wrote:
>
> [Richi/Jakub/FP experts, does this sound like the right solution, or am I
> missing some subtle IPA/inlining issue?]
>
> The problem here is that we're inlining a global range with NANs into
> a function that has been tagged with __attribute__((optimize
> ("-ffinite-math-only"))).  As the global range is copied from
> SSA_NAME_RANGE_INFO, its NAN bits are copied, which then cause
> frange::verify_range() to fail a sanity check making sure no NANs
> creep in when !HONOR_NANS.
>
> I think what we should do is nuke the NAN bits as we're restoring the
> global range.  For that matter, if we use the frange constructor,
> everything except that NAN sign will be done automatically, including
> dropping INFs to the min/max representable range when appropriate.
>
> PR tree-optimization/107394
>
> gcc/ChangeLog:
>
> * value-range-storage.cc (frange_storage_slot::get_frange): Use
> frange constructor.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/tree-ssa/pr107394.c: New test.
> ---
>  gcc/testsuite/gcc.dg/tree-ssa/pr107394.c | 22 ++
>  gcc/value-range-storage.cc   | 18 +++---
>  2 files changed, 29 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr107394.c
>
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c
> new file mode 100644
> index 000..0e1e5ac40ce
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c
> @@ -0,0 +1,22 @@
> +// { dg-do compile }
> +// { dg-options "-O2" }
> +
> +static double
> +quux (double x)
> +{
> +  return __builtin_fabs (x);
> +}
> +
> +__attribute__ ((flatten, optimize ("-ffinite-math-only"))) static int
> +bar (int *p)
> +{
> +  *p = quux (0.0);
> +
> +  return 0;
> +}
> +
> +void
> +foo (int *p)
> +{
> +  (void) bar (p);
> +}
> diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
> index 6e054622830..b660102e064 100644
> --- a/gcc/value-range-storage.cc
> +++ b/gcc/value-range-storage.cc
> @@ -261,17 +261,13 @@ frange_storage_slot::get_frange (frange , tree type) 
> const
>  {
>gcc_checking_assert (r.supports_type_p (type));
>
> -  r.set_undefined ();
> -  r.m_kind = m_kind;
> -  r.m_type = type;
> -  r.m_min = m_min;
> -  r.m_max = m_max;
> -  r.m_pos_nan = m_pos_nan;
> -  r.m_neg_nan = m_neg_nan;
> -  r.normalize_kind ();
> -
> -  if (flag_checking)
> -r.verify_range ();
> +  // Use the constructor because it will canonicalize the range.
> +  r = frange (type, m_min, m_max, m_kind);
> +
> +  // The constructor will set the NAN bits for HONOR_NANS, but we must
> +  // make sure to set the NAN sign if known.
> +  if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
> +r.update_nan (m_neg_nan);
>  }
>
>  bool
> --
> 2.37.3
>
From 89eaccbc4b1e5ff7fea2eb4e3fb5870c6ca4160b Mon Sep 17 00:00:00 2001
From: Aldy Hernandez 
Date: Tue, 25 Oct 2022 22:44:51 +0200
Subject: [PATCH] [PR tree-optimization/107394] Canonicalize global franges as
 they are read back.

The problem here is that we're inlining a global range with NANs into
a function that has been tagged with __attribute__((optimize
("-ffinite-math-only"))).  As the global range is copied from
SSA_NAME_RANGE_INFO, its NAN bits are copied, which then cause
frange::verify_range() to fail a sanity check making sure no NANs
creep in when !HONOR_NANS.

I think what we should do is nuke the NAN bits as we're restoring the
global range.  For that matter, if we use the frange constructor,
everything except that NAN sign will be done automatically, including
dropping INFs to the min/max representable range when appropriate.

	PR tree-optimization/107394

gcc/ChangeLog:

	* value-range-storage.cc (frange_storage_slot::get_frange): Use
	frange constructor.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/pr107394.c: New test.
---
 gcc/testsuite/gcc.dg/tree-ssa/pr107394.c | 22 
 gcc/value-range-storage.cc   | 33 
 2 files changed, 44 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr107394.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c b/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c
new file mode 100644
index 000..0e1e5ac40ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr107394.c
@@ -0,0 +1,22 @@
+// { dg-do compile }
+// { dg-options "-O2" }
+
+static double
+quux (double x)
+{
+  return __builtin_fabs (x);
+}
+
+__attribute__ ((flatten, optimize ("-ffinite-math-only"))) static int
+bar (int *p)
+{
+  *p = quux (0.0);
+
+  return 0;
+}
+
+void
+foo (int *p)
+{
+  (void) bar (p);
+}
diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc
index 6e054622830..462447ba250 100644
--- a/gcc/value-range-storage.cc
+++ b/gcc/value-range-storage.cc
@@ -261,17 +261,28 @@ frange_storage_slot::get_frange (frange , tree type) const
 {
   gcc_checking_assert 

[PATCH] riscv/RTEMS: Add RISCV_GCOV_TYPE_SIZE

2022-10-26 Thread Sebastian Huber
The RV32A extension does not support 64-bit atomic operations.  For RTEMS, use
a 32-bit gcov type for RV32.

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_gcov_type_size): New.
(TARGET_GCOV_TYPE_SIZE): Likewise.
* config/riscv/rtems.h (RISCV_GCOV_TYPE_SIZE): New.
---
 gcc/config/riscv/riscv.cc | 11 +++
 gcc/config/riscv/rtems.h  |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 4e18a43539a..1b7f4fb1981 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -6637,6 +6637,17 @@ riscv_vector_alignment (const_tree type)
 #undef TARGET_VECTOR_ALIGNMENT
 #define TARGET_VECTOR_ALIGNMENT riscv_vector_alignment
 
+#ifdef RISCV_GCOV_TYPE_SIZE
+static HOST_WIDE_INT
+riscv_gcov_type_size (void)
+{
+  return RISCV_GCOV_TYPE_SIZE;
+}
+
+#undef TARGET_GCOV_TYPE_SIZE
+#define TARGET_GCOV_TYPE_SIZE riscv_gcov_type_size
+#endif
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
diff --git a/gcc/config/riscv/rtems.h b/gcc/config/riscv/rtems.h
index 14e5e59caaa..3982b24382f 100644
--- a/gcc/config/riscv/rtems.h
+++ b/gcc/config/riscv/rtems.h
@@ -29,3 +29,5 @@
builtin_define ("__USE_INIT_FINI__");   \
builtin_assert ("system=rtems");\
 } while (0)
+
+#define RISCV_GCOV_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
-- 
2.35.3



Re: [PATCH v3] c++: parser - Support for target address spaces in C++

2022-10-26 Thread Paul Iannetta via Gcc-patches
On Wed, Oct 19, 2022 at 02:55:21PM -0400, Jason Merrill wrote:
> On 10/18/22 13:01, Paul Iannetta wrote:
> > Thank you very much for the detailed review.
> > 
> > On Tue, Oct 18, 2022 at 10:24:23AM -0400, Jason Merrill wrote:
> > > On 10/18/22 03:37, Paul Iannetta wrote:
> > > > On Fri, Oct 14, 2022 at 11:19:50AM -0400, Jason Merrill wrote:
> > > > > On 10/13/22 17:57, Paul Iannetta wrote:
> > > > > > On Thu, Oct 13, 2022 at 03:41:16PM -0400, Jason Merrill wrote:
> > > > > > > On 10/13/22 12:02, Paul Iannetta wrote:
> > > > > > > > On Thu, Oct 13, 2022 at 11:47:42AM -0400, Jason Merrill wrote:
> > > > > > > > > On 10/13/22 11:23, Paul Iannetta wrote:
> > > > > > > > > > On Thu, Oct 13, 2022 at 11:02:24AM -0400, Jason Merrill 
> > > > > > > > > > wrote:
> > > > > > > > > > > On 10/12/22 20:52, Paul Iannetta wrote:
> > > > > > > > > > > > There are quite a few things I would like to clarify 
> > > > > > > > > > > > concerning some
> > > > > > > > > > > > implementation details.
> > > > > > > > > > > > - A variable with automatic storage (which is 
> > > > > > > > > > > > neither a pointer nor
> > > > > > > > > > > >   a reference) cannot be qualified with an 
> > > > > > > > > > > > address space.  I detect
> > > > > > > > > > > >   this by the combination of `sc_none' and `! 
> > > > > > > > > > > > toplevel_bindings_p ()',
> > > > > > > > > > > >   but I've also seen the use of 
> > > > > > > > > > > > `at_function_scope' at other places.
> > > > > > > > > > > >   And I'm unsure which one is appropriate here.
> > > > > > > > > > > >   This detection happens at the very end of 
> > > > > > > > > > > > grokdeclarator because I
> > > > > > > > > > > >   need to know that the type is a pointer, 
> > > > > > > > > > > > which is not know until
> > > > > > > > > > > >   very late in the function.
> > > > > > > > > > > 
> > > > > > > > > > > At that point you have the decl, and you can ask directly 
> > > > > > > > > > > what its storage
> > > > > > > > > > > duration is, perhaps using decl_storage_duration.
> > > > > > > > > > > 
> > > > > > > > > > > But why do you need to know whether the type is a 
> > > > > > > > > > > pointer?  The attribute
> > > > > > > > > > > applies to the target type of the pointer, not the 
> > > > > > > > > > > pointer type.  I think
> > > > > > > > > > > the problem is that you're looking at declspecs when you 
> > > > > > > > > > > ought to be looking
> > > > > > > > > > > at type_quals.
> > > > > > > > > > 
> > > > > > > > > > I need to know that the base type is a pointer to reject 
> > > > > > > > > > invalid
> > > > > > > > > > declarations such as:
> > > > > > > > > > 
> > > > > > > > > >  int f (__seg_fs int a) { } or int f () { 
> > > > > > > > > > __seg_fs int a; }
> > > > > > > > > > 
> > > > > > > > > > because parameters and auto variables can have an address 
> > > > > > > > > > space
> > > > > > > > > > qualifier only if they are pointer or reference type, which 
> > > > > > > > > > I can't
> > > > > > > > > > tell only from type_quals.
> > > > > > > > > 
> > > > > > > > > But "int *__seg_fs a" is just as invalid as the above; the 
> > > > > > > > > difference is not
> > > > > > > > > whether a is a pointer, but whether the 
> > > > > > > > > address-space-qualified is the type
> > > > > > > > > of a itself or some sub-type.
> > > > > > > > 
> > > > > > > > I agree that "int * __seg_fs a" is invalid but it is accepted 
> > > > > > > > by the C
> > > > > > > > front-end, and by clang (both C and C++), the behavior is that 
> > > > > > > > the
> > > > > > > > address-name is silently ignored.
> > > > > > > 
> > > > > > > Hmm, that sounds like a bug; in that case, presumably the user 
> > > > > > > meant to
> > > > > > > qualify the pointed-to type, and silently ignoring seems unlikely 
> > > > > > > to give
> > > > > > > the effect they want.
> > > > > > > 
> > > > > > 
> > > > > > Well, actually, I'm re-reading the draft and "int * __seg_fs a" is
> > > > > > valid.  It means "pointer in address space __seg_fs pointing to an
> > > > > > object in the generic address space", whereas "__seg_fs int * a" 
> > > > > > means
> > > > > > "pointer in the generic address space pointing to an object in the
> > > > > > __seg_fs address-space".
> > > > > > 
> > > > > > Oddities such as, "__seg_fs int * __seg_gs a" are also perfectly
> > > > > > valid.
> > > > > 
> > > > > If a has static storage duration, sure; I was still thinking about
> > > > > declarations with automatic storage duration such as in your example 
> > > > > above.
> > > > > 
> > > > 
> > > > Thanks, I only use type_quals now. I also took into account the style
> > > > recommendations from Jakub, and included the other template tests.
> > > > I rebased over trunk, bootstrapped the compiler and run the "make
> > > > check-gcc" with no regressions on x86.
> > > > 
> > > > Paul
> > > > 
> > > > #  >8 

Re: [PATCH] i386: Enable small loop unrolling for O2

2022-10-26 Thread Uros Bizjak via Gcc-patches
On Wed, Oct 26, 2022 at 7:53 AM Hongyu Wang  wrote:
>
> Hi,
>
> Inspired by rs6000 and s390 port changes, this patch
> enables loop unrolling for small size loop at O2 by default.
> The default behavior is to unroll loop with unknown trip-count and
> less than 4 insns by 1 time.
>
> This improves 548.exchange2 by 3.5% on icelake and 6% on zen3 with
> 1.2% codesize increment. For other benchmarks the variants are minor
> and overall codesize increased by 0.2%.
>
> The kernel image size increased by 0.06%, and no impact on eembc.

Does this setting benefit all targets?  IIRC, in the past all
benchmarks also enabled -funroll-loops, so it looks to me that
unrolling small loops by default is a good compromise.

The patch is technically OK, but as a tuning default, I would leave
the final approval to HJ.

Thanks,
Uros.

>
> Bootstrapped & regrtested on x86_64-pc-linux-gnu.
>
> Ok for trunk?
>
> gcc/ChangeLog:
>
> * common/config/i386/i386-common.cc (ix86_optimization_table):
> Enable loop unroll and small loop unroll at O2 by default.
> * config/i386/i386-options.cc
> (ix86_override_options_after_change):
> Disable small loop unroll when funroll-loops enabled, reset
> cunroll_grow_size when it is not explicitly enabled.
> (ix86_option_override_internal): Call
> ix86_override_options_after_change instead of calling
> ix86_recompute_optlev_based_flags and ix86_default_align
> separately.
> * config/i386/i386.cc (ix86_loop_unroll_adjust): Adjust unroll
> factor if -munroll-only-small-loops enabled.
> * config/i386/i386.opt: Add -munroll-only-small-loops,
> -param=x86-small-unroll-ninsns= for loop insn limit,
> -param=x86-small-unroll-factor= for unroll factor.
> * doc/invoke.texi: Document -munroll-only-small-loops,
> x86-small-unroll-ninsns and x86-small-unroll-factor.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/i386/pr86270.c: Add -mno-unroll-only-small-loops.
> * gcc.target/i386/pr93002.c: Likewise.
> ---
>  gcc/common/config/i386/i386-common.cc   |  6 
>  gcc/config/i386/i386-options.cc | 40 ++---
>  gcc/config/i386/i386.cc | 13 
>  gcc/config/i386/i386.opt| 13 
>  gcc/doc/invoke.texi | 14 +
>  gcc/testsuite/gcc.target/i386/pr86270.c |  2 +-
>  gcc/testsuite/gcc.target/i386/pr93002.c |  2 +-
>  7 files changed, 84 insertions(+), 6 deletions(-)
>
> diff --git a/gcc/common/config/i386/i386-common.cc 
> b/gcc/common/config/i386/i386-common.cc
> index d6a68dc9b1d..0e580b39d14 100644
> --- a/gcc/common/config/i386/i386-common.cc
> +++ b/gcc/common/config/i386/i386-common.cc
> @@ -1686,6 +1686,12 @@ static const struct default_options 
> ix86_option_optimization_table[] =
>  /* The STC algorithm produces the smallest code at -Os, for x86.  */
>  { OPT_LEVELS_2_PLUS, OPT_freorder_blocks_algorithm_, NULL,
>REORDER_BLOCKS_ALGORITHM_STC },
> +{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_funroll_loops, NULL, 1 },
> +{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_munroll_only_small_loops, NULL, 1 },
> +/* Turns off -frename-registers and -fweb which are enabled by
> +   funroll-loops.  */
> +{ OPT_LEVELS_ALL, OPT_frename_registers, NULL, 0 },
> +{ OPT_LEVELS_ALL, OPT_fweb, NULL, 0 },
>  /* Turn off -fschedule-insns by default.  It tends to make the
> problem with not enough registers even worse.  */
>  { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 },
> diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
> index acb2291e70f..6ea347c32e1 100644
> --- a/gcc/config/i386/i386-options.cc
> +++ b/gcc/config/i386/i386-options.cc
> @@ -1819,8 +1819,43 @@ ix86_recompute_optlev_based_flags (struct gcc_options 
> *opts,
>  void
>  ix86_override_options_after_change (void)
>  {
> +  /* Default align_* from the processor table.  */
>ix86_default_align (_options);
> +
>ix86_recompute_optlev_based_flags (_options, _options_set);
> +
> +  /* Disable unrolling small loops when there's explicit
> + -f{,no}unroll-loop.  */
> +  if ((OPTION_SET_P (flag_unroll_loops))
> + || (OPTION_SET_P (flag_unroll_all_loops)
> +&& flag_unroll_all_loops))
> +{
> +  if (!OPTION_SET_P (ix86_unroll_only_small_loops))
> +   ix86_unroll_only_small_loops = 0;
> +  /* Re-enable -frename-registers and -fweb if funroll-loops
> +enabled.  */
> +  if (!OPTION_SET_P (flag_web))
> +   flag_web = flag_unroll_loops;
> +  if (!OPTION_SET_P (flag_rename_registers))
> +   flag_rename_registers = flag_unroll_loops;
> +  if (!OPTION_SET_P (flag_cunroll_grow_size))
> +   flag_cunroll_grow_size = flag_unroll_loops
> +|| flag_peel_loops
> +|| optimize >= 3;
> +}
> +  else
> +{
> +  if (!OPTION_SET_P