[PATCHv3, rs6000] rs6000: correct vector sign extend built-ins on Big Endian [PR108812]

2023-04-05 Thread HAO CHEN GUI via Gcc-patches
Hi,
  This patch removes byte reverse operation before vector integer sign
extension on big endian. These built-ins require to sign extend the element
of the input vector that would fall in the least significant portion of the
result element. So both BE and LE should do the same operation and the byte
reversion is no need. This patch fixes it. Now these built-ins have the same
behavior on all compilers.

  The unnecessary expand patterns are removed and the names of insn pattern
are set to the same style. Also the test cases are modified.

  The patch passed regression test on Power Linux platforms.

Thanks
Gui Haochen

ChangeLog
rs6000: correct vector sign extend builtins on Big Endian

gcc/
PR target/108812
* config/rs6000/vsx.md (vsx_sign_extend_qi_): Rename to...
(vsx_sign_extend_v16qi_): ... this.
(vsx_sign_extend_hi_): Rename to...
(vsx_sign_extend_v8hi_): ... this.
(vsx_sign_extend_si_v2di): Rename to...
(vsx_sign_extend_v4si_v2di): ... this.
(vsignextend_qi_): Remove.
(vsignextend_hi_): Remove.
(vsignextend_si_v2di): Remove.
(vsignextend_v2di_v1ti): Remove.
(*xxspltib__split): Replace gen_vsx_sign_extend_qi_v2di with
gen_vsx_sign_extend_v16qi_v2di and gen_vsx_sign_extend_qi_v4si
with gen_vsx_sign_extend_v16qi_v4si.
* config/rs6000/rs6000.md (split for DI constant generation):
Replace gen_vsx_sign_extend_qi_si with gen_vsx_sign_extend_v16qi_si.
(split for HSDI constant generation): Replace gen_vsx_sign_extend_qi_di
with gen_vsx_sign_extend_v16qi_di and gen_vsx_sign_extend_qi_si
with gen_vsx_sign_extend_v16qi_si.
* config/rs6000/rs6000-builtins.def (__builtin_altivec_vsignextsb2d):
Set bif-pattern to vsx_sign_extend_v16qi_v2di.
(__builtin_altivec_vsignextsb2w): Set bif-pattern to
vsx_sign_extend_v16qi_v4si.
(__builtin_altivec_visgnextsh2d): Set bif-pattern to
vsx_sign_extend_v8hi_v2di.
(__builtin_altivec_vsignextsh2w): Set bif-pattern to
vsx_sign_extend_v8hi_v4si.
(__builtin_altivec_vsignextsw2d): Set bif-pattern to
vsx_sign_extend_si_v2di.
(__builtin_altivec_vsignext): Set bif-pattern to
vsx_sign_extend_v2di_v1ti.
* config/rs6000/rs6000-builtin.cc (lxvrse_expand_builtin): Replace
gen_vsx_sign_extend_qi_v2di with gen_vsx_sign_extend_v16qi_v2di,
gen_vsx_sign_extend_hi_v2di with gen_vsx_sign_extend_v8hi_v2di and
gen_vsx_sign_extend_si_v2di with gen_vsx_sign_extend_v4si_v2di.

gcc/testsuite/
PR target/108812
* gcc.target/powerpc/p9-sign_extend-runnable.c: Set corresponding
expected vectors for Big Endian.
* gcc.target/powerpc/int_128bit-runnable.c: Likewise.

patch.diff
diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
b/gcc/config/rs6000/rs6000-builtin.cc
index 90ab39dc258..c66cff17681 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -2840,17 +2840,17 @@ lxvrse_expand_builtin (rtx target, insn_code icode, rtx 
*op,
   if (icode == CODE_FOR_vsx_lxvrbx)
 {
   temp1  = simplify_gen_subreg (V16QImode, tiscratch, TImode, 0);
-  emit_insn (gen_vsx_sign_extend_qi_v2di (discratch, temp1));
+  emit_insn (gen_vsx_sign_extend_v16qi_v2di (discratch, temp1));
 }
   else if (icode == CODE_FOR_vsx_lxvrhx)
 {
   temp1  = simplify_gen_subreg (V8HImode, tiscratch, TImode, 0);
-  emit_insn (gen_vsx_sign_extend_hi_v2di (discratch, temp1));
+  emit_insn (gen_vsx_sign_extend_v8hi_v2di (discratch, temp1));
 }
   else if (icode == CODE_FOR_vsx_lxvrwx)
 {
   temp1  = simplify_gen_subreg (V4SImode, tiscratch, TImode, 0);
-  emit_insn (gen_vsx_sign_extend_si_v2di (discratch, temp1));
+  emit_insn (gen_vsx_sign_extend_v4si_v2di (discratch, temp1));
 }
   else if (icode == CODE_FOR_vsx_lxvrdx)
 discratch = simplify_gen_subreg (V2DImode, tiscratch, TImode, 0);
diff --git a/gcc/config/rs6000/rs6000-builtins.def 
b/gcc/config/rs6000/rs6000-builtins.def
index f76f54793d7..6bfe9246a02 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -2687,19 +2687,19 @@
 VRLWNM altivec_vrlwnm {}

   const vsll __builtin_altivec_vsignextsb2d (vsc);
-VSIGNEXTSB2D vsignextend_qi_v2di {}
+VSIGNEXTSB2D vsx_sign_extend_v16qi_v2di {}

   const vsi __builtin_altivec_vsignextsb2w (vsc);
-VSIGNEXTSB2W vsignextend_qi_v4si {}
+VSIGNEXTSB2W vsx_sign_extend_v16qi_v4si {}

   const vsll __builtin_altivec_visgnextsh2d (vss);
-VSIGNEXTSH2D vsignextend_hi_v2di {}
+VSIGNEXTSH2D vsx_sign_extend_v8hi_v2di {}

   const vsi __builtin_altivec_vsignextsh2w (vss);
-VSIGNEXTSH2W vsignextend_hi_v4si {}
+VSIGNEXTSH2W vsx_sign_extend_v8hi_v4si {}

   const vsll __builtin_altivec_vsignextsw2d (vsi);
-VSIGNEXTSW2D vsignextend_si_v2di {}
+VSIGNEXTSW2D vsx_sign_extend_v4si_v2di {}

Re: [PATCH] [testsuite] [ppc] expect vectorization in gen-vect-11c.c

2023-04-05 Thread Alexandre Oliva via Gcc-patches
Hello, Kewen,

On Mar 27, 2023, "Kewen.Lin"  wrote:

> on 2023/3/25 16:35, Alexandre Oliva wrote:

>> The first loop in main gets stores "vectorized" on powerpc into
>> full-word stores, even without any vector instruction support, so the
>> test's expectation of no loop vectorization is not met.

> I think this test issue has been gone since r13-5771-gdc87e1391c55c6.

That patch has been backported to gcc-12 as r12-9258-g21e7145aaf582c.

> Could you have a double check?

I confirm I observe the problem with gcc-12 targeting ppc64-vx7r2,
containing the backported patch, and that the loop is vectorized,
failing the test.


It's unfortunately not viable for me to test GCC trunk with vxworks, so
my testing with it is limited to earlier GCC versions, that we (AdaCore)
have already ported or are in the process of porting.  I make up for
that by testing trunk with other target variants, to the best of my
abilities, to avoid regressions, but sometimes I just can't tell whether
my baseline for regression testing doesn't contain a failure because
there's another fix, or because it just doesn't fail on that target
variant.


In this case, the comments in the patch you mentioned don't seem to
match the situation at hand: the SImode stores vectorized into V2SImode
(DImode) seem profitable and are *not* split by vector lowering.

-- 
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 


RE: [PATCH] Check hard_regno_mode_ok before setting lowest memory move cost for the mode with different reg classes.

2023-04-05 Thread Liu, Hongtao via Gcc-patches


> -Original Message-
> From: Vladimir Makarov 
> Sent: Wednesday, April 5, 2023 8:59 PM
> To: Jeff Law ; Liu, Hongtao
> ; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Check hard_regno_mode_ok before setting lowest
> memory move cost for the mode with different reg classes.
> 
> 
> On 4/4/23 21:29, Jeff Law wrote:
> >
> >
> > On 4/3/23 23:13, liuhongt via Gcc-patches wrote:
> >> There's a potential performance issue when backend returns some
> >> unreasonable value for the mode which can be never be allocate with
> >> reg class.
> >>
> >> Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
> >> Ok for trunk(or GCC14 stage1)?
> >>
> >> gcc/ChangeLog:
> >>
> >> PR rtl-optimization/109351
> >> * ira.cc (setup_class_subset_and_memory_move_costs): Check
> >> hard_regno_mode_ok before setting lowest memory move cost for
> >> the mode with different reg classes.
> > Not a regression *and* changing register allocation.  This seems like
> > it should defer to gcc-14.
> >
> Yes, I am agree.  It should wait for gcc-14, especially when we are close to 
> the
> release. Also the testing x86-64 is not enough for such changes (although I
> tried ppc64le and did not find any problem).
> 
> Cost related patches for RA frequently result in new testsuite failures on
> some targets.  Even if the change seems obvious and expected to improve
> the generated code.
> 
> Target dependent code sometimes defines correctly the costs only for some
> possible cases and making less dependent from this pitfall is good.  So I 
> think
> the patch moves us to the right direction.
> 
> The patch is ok for me to commit it to the trunk after the gcc-13 release and 
> if
> arm64 testing shows no GCC testsuite regression.
Bootstrapped and regtested on aarch64-unknown-linux-gnu.
Waiting for GCC14.
> 
> Thank you for working on this issue.
> 



Re: [PATCH] [PR99708] [rs6000] don't expect __ibm128 with 64-bit long double

2023-04-05 Thread Alexandre Oliva via Gcc-patches
Hello, Kewen,

Thanks for the feedback.

On Mar 27, 2023, "Kewen.Lin"  wrote:

> on 2023/3/25 16:37, Alexandre Oliva via Gcc-patches wrote:
>> 
>> When long double is 64-bit wide, as on vxworks, the rs6000 backend
>> defines neither the __ibm128 type nor the __SIZEOF_IBM128__ macro, but
>> pr99708.c expected both to be always defined.  Adjust the test to
>> match the implementation.

> There is one patch from Mike to define type __ibm128 even without
> IEEE 128-bit floating point support, it's at the link:

> https://gcc.gnu.org/pipermail/gcc-patches/2022-August/599984.html

> I would expect this issue would be gone if the adjustment on the
> support of type __ibm128 gets landed in future.

Yeah, the issue would then be gone, but the patch is compatible with
that proposed change: if __ibm128 and the corresponding SIZEOF macro are
defined, the proposed change is a no-op.

> So maybe we can just xfail this for longdouble64?  What do you
> think?

I wouldn't object to that, and I could even write and test the alternate
patch for that, but I fail to understand why that would be more
desirable.  Would you be so kind as to enlighten me?

Thanks,

-- 
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 


[PATCH] Fix typo in -param=vect-induction-float= attributes

2023-04-05 Thread Andrew Pinski via Gcc-patches
There was a typo in the attributes of the option
-param=vect-induction-float= for IntegerRange.
This fixes that typo.

Committed to GCC 12 branch as obvious after a build/test.

gcc/ChangeLog:

PR tree-optimization/109427
* params.opt (-param=vect-induction-float=):
Fix option attribute typo for IntegerRange.

(cherry picked from commit 0f816116356fec32e3a3a2fb5af790a0438c5da4)
---
 gcc/params.opt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/params.opt b/gcc/params.opt
index b88e1372005..e0ff9e21054 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -1181,7 +1181,7 @@ Common Joined UInteger 
Var(param_vect_inner_loop_cost_factor) Init(50) IntegerRa
 The maximum factor which the loop vectorizer applies to the cost of statements 
in an inner loop relative to the loop being vectorized.
 
 -param=vect-induction-float=
-Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRage(0, 
1) Param Optimization
+Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRange(0, 
1) Param Optimization
 Enable loop vectorization of floating point inductions.
 
 -param=vrp1-mode=
-- 
2.31.1



[PATCH] Fix typo in -param=vect-induction-float= attributes

2023-04-05 Thread Andrew Pinski via Gcc-patches
There was a typo in the attributes of the option
-param=vect-induction-float= for IntegerRange.
This fixes that typo.

Committed as obvious after a build/test.

gcc/ChangeLog:

PR tree-optimization/109427
* params.opt (-param=vect-induction-float=):
Fix option attribute typo for IntegerRange.
---
 gcc/params.opt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/params.opt b/gcc/params.opt
index aecc01c6adf..823cdb2ff85 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -1179,7 +1179,7 @@ Common Joined UInteger 
Var(param_vect_inner_loop_cost_factor) Init(50) IntegerRa
 The maximum factor which the loop vectorizer applies to the cost of statements 
in an inner loop relative to the loop being vectorized.
 
 -param=vect-induction-float=
-Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRage(0, 
1) Param Optimization
+Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRange(0, 
1) Param Optimization
 Enable loop vectorization of floating point inductions.
 
 ; This comment is to ensure we retain the blank line above.
-- 
2.39.1



Re: Re: [PATCH v2] RISC-V: Add Z*inx imcompatible check in gcc.

2023-04-05 Thread jiawei



 -原始邮件-
 发件人: "Jeff Law" 
 发送时间: 2023-04-05 09:30:43 (星期三)
 收件人: "Hans-Peter Nilsson" , Jiawei 
 抄送: gcc-patches@gcc.gnu.org, kito.ch...@sifive.com, pal...@dabbelt.com, 
christoph.muell...@vrull.eu, wuwei2...@iscas.ac.cn
 主题: Re: [PATCH v2] RISC-V: Add Z*inx imcompatible check in gcc.
 
 
 
 On 4/3/23 19:46, Hans-Peter Nilsson wrote:
  On Tue, 28 Mar 2023, Jiawei wrote:
  
  +  // Zfinx is conflict with float extensions.
  +  if (TARGET_ZFINX  TARGET_HARD_FLOAT)
  +error ("z*inx is conflict with float extensions");
  +
  
  While I'm not a native English speaker, "is conflict with"
  doesn't sound grammatically correct.  Perhaps "conflicts with"
  or "is in conflict with"?
 "conflicts with" is better.
 
 Jeff

Thanks for your reply, fixed in the trunk.

BR,
Jiawei

Re: 'g++.dg/modules/modules.exp': don't leak local 'unsupported' proc [PR108899]

2023-04-05 Thread Alexandre Oliva via Gcc-patches
On Apr  5, 2023, Thomas Schwinge  wrote:

> Given the two "OK"s that you got end of last week, are you going to push
> that anytime soon, please?

Apologies for the delay.

> With...

> Co-authored-by: Thomas Schwinge 

> ... added, I suppose.

I wrote the patch based on your report, before even seeing your patch,
though I only posted mine later, so I tried to give you credit for the
report in the commit message, but if you feel that the note is
appropriate, sure :-)  Thanks again!

Here's what I'm checking in.


testsuite: fix proc unsupported overriding in modules.exp [PR108899]

The overrider of proc unsupported in modules.exp had two problems
reported by Thomas Schwinge, even after Jakub Jelínek's fix:

- it remained in effect while running other dejagnu testsets

- it didn't quote correctly the argument list passed to it, which
  caused test names to be surrounded by curly braces, as in:

UNSUPPORTED: {...}

This patch fixes both issues, obsoleting and reverting Jakub's change,
by dropping the overrider and renaming the saved proc back, and by
using uplevel's argument list splicing.


Co-authored-by: Thomas Schwinge 

for  gcc/testsuite/ChangeLog

PR testsuite/108899
* g++.dg/modules/modules.exp (unsupported): Drop renaming.
Fix quoting.
---
 gcc/testsuite/g++.dg/modules/modules.exp |   20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/gcc/testsuite/g++.dg/modules/modules.exp 
b/gcc/testsuite/g++.dg/modules/modules.exp
index 80aa392bc7f3b..dc302d3d0af48 100644
--- a/gcc/testsuite/g++.dg/modules/modules.exp
+++ b/gcc/testsuite/g++.dg/modules/modules.exp
@@ -319,15 +319,11 @@ cleanup_module_files [find $DEFAULT_REPO *.gcm]
 # so that, after an unsupported result in dg-test, we can skip rather
 # than fail subsequent related tests.
 set module_do {"compile" "P"}
-if { [info procs unsupported] != [list] \
-  && [info procs saved-unsupported] == [list] } {
-rename unsupported saved-unsupported
-
-proc unsupported { args } {
-   global module_do
-   lset module_do 1 "N"
-   return [saved-unsupported $args]
-}
+rename unsupported modules-saved-unsupported
+proc unsupported { args } {
+global module_do
+lset module_do 1 "N"
+return [uplevel 1 modules-saved-unsupported $args]
 }
 
 # not grouped tests, sadly tcl doesn't have negated glob
@@ -412,4 +408,10 @@ foreach src [lsort [find $srcdir/$subdir {*_a.[CHX}]] {
 }
 }
 
+# Restore the original unsupported proc, lest it will affect
+# subsequent test runs, or even fail renaming if we run modules.exp
+# for multiple targets/multilibs/options.
+rename unsupported {}
+rename modules-saved-unsupported unsupported
+
 dg-finish



-- 
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 


Re: [PATCH 0/2] Support Intel AMX-COMPLEX

2023-04-05 Thread Hongtao Liu via Gcc-patches
On Mon, Apr 3, 2023 at 4:51 PM Haochen Jiang via Gcc-patches
 wrote:
>
> Hi all,
>
> These patch aims to add Intel AMX-COMPLEX instructions. Also we added
> AMX-COMPLEX to -march=graniterapids.
>
> The information is based on newly released
> Intel Architecture Instruction Set Extensions and Future Features.
>
> The document comes following:
> https://www.intel.com/content/www/us/en/develop/download/intel-architecture-instruction-set-extensions-programming-reference.html
>
> Since there are only two instructions under this new ISA, I suppose the
> risk is low and might get a change for GCC13. So I send the patches out now.
>
> Tested on x86_64-pc-linux-gnu. Ok for trunk?
Ok if there's no objection in the next 2 days.
>
> BRs,
> Haochen
>
>


-- 
BR,
Hongtao


Re: [PATCH] Introduce -nolibstdc++ option

2023-04-05 Thread Alexandre Oliva via Gcc-patches
On Mar 30, 2023, Gerald Pfeifer  wrote:

> On Thu, 30 Mar 2023, Alexandre Oliva wrote:
>> How about this, does this seem useful?

> I like it - helpful and easy to understand. :-)

'k, I'm putting it in, thanks


On Mar 30, 2023, Arsen Arsenović  wrote:

> IMO, yes - in fact, the libstdc++ manual even has a use-case for this

Yeah, and it also had the means to accomplish that already.  -nostdlib++
was for the testsuite, that always uses g++ for linking C++ tests.

I suppose libstdc++ now has an alternative it might consider switching
to, namely using g++ -nostdlib++ rather than gcc to link itself, but
should it?  I don't see the upside.  Its build process is not broken,
it's not even inconvenient, so what's the expected benefit that the
change would bring about?  As for downsides, I perceive risks of build
scripts (e.g. libtool)'s not yet having support for -nostdlib++, and
thus trying to use the flag could break rather than improve the state of
affairs.  It feels like inviting trouble to me.

> If you think the flag you added fits here, would you mind also including
> this file in your patch?

The patch was for the online release documentation, it's not even the
same repository as libstdc++, so there's no way to add it to the same
patch.

Given that, and since I'm not so sure I understand what change you're
suggesting to libstdc++'s manual or build procedures, how about you
give it a shot yourself?

-- 
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 


Re: [PATCH] PR tree-optimization/109417 - Check if dependency is valid before using in may_recompute_p.

2023-04-05 Thread Jeff Law via Gcc-patches




On 4/5/23 14:10, Andrew MacLeod via Gcc-patches wrote:
When a statement is first processed, any SSA_NAMEs that are dependencies 
are cached for quick future access.


if we ;later rewrite the statement (say propagate a constant into it), 
its possible the ssa-name in this cache is no longer active.   Normally 
this is not a problem, but the changed to may_recompute_p forgot to take 
that into account, and was checking a dependency from the cache that was 
in the SSA_NAME_FREE_LIST. It thus had no SSA_NAME_DEF_STMT when we were 
expecting one.


This patch simply rejects dependencies from consideration if they are in 
the free list.


Bootstrapping on x86_64-pc-linux-gnu  and presuming no regressio0ns, OK 
for trunk?
eek.  So you've got a released name in the cache?  What happens if the 
name gets released, then re-used?  Aren't you going to get bogus results 
in that case?


jeff


Ping^7: [PATCH] jit: Install jit headers in $(libsubincludedir) [PR 101491]

2023-04-05 Thread Lorenzo Salvadore via Gcc-patches
Hello,

Ping https://gcc.gnu.org/pipermail/gcc-patches/2022-November/606450.html

Thanks,

Lorenzo Salvadore

> From f8e2c2ee89a7d8741bb65163d1f1c20edcd546ac Mon Sep 17 00:00:00 2001
> From: Lorenzo Salvadore develo...@lorenzosalvadore.it
> 
> Date: Wed, 16 Nov 2022 11:27:38 +0100
> Subject: [PATCH] jit: Install jit headers in $(libsubincludedir) [PR 101491]
> 
> Installing jit/libgccjit.h and jit/libgccjit++.h headers in
> $(includedir) can be a problem for machines where multiple versions of
> GCC are required simultaneously, see for example this bug report on
> FreeBSD:
> 
> https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=257060
> 
> Hence,
> 
> - define $(libsubincludedir) the same way it is defined in libgomp;
> - install jit/libgccjit.h and jit/libgccjit++.h in $(libsubincludedir).
> 
> The patch has already been applied successfully in the official FreeBSD
> ports tree for the ports lang/gcc11 and lang/gcc12. Please see the
> following commits:
> 
> https://cgit.freebsd.org/ports/commit/?id=0338e04504ee269b7a95e6707f1314bc1c4239fe
> https://cgit.freebsd.org/ports/commit/?id=f1957296ed2dce8a09bb9582e9a5a715bf8b3d4d
> 
> gcc/ChangeLog:
> 
> 2022-11-16 Lorenzo Salvadore develo...@lorenzosalvadore.it
> 
> PR jit/101491
> * Makefile.in: Define and create $(libsubincludedir)
> 
> gcc/jit/ChangeLog:
> 
> 2022-11-16 Lorenzo Salvadore develo...@lorenzosalvadore.it
> 
> PR jit/101491
> * Make-lang.in: Install headers in $(libsubincludedir)
> ---
> gcc/Makefile.in | 3 +++
> gcc/jit/Make-lang.in | 4 ++--
> 2 files changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index f672e6ea549..3bcf1c491ab 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -635,6 +635,8 @@ libexecdir = @libexecdir@
> 
> # Directory in which the compiler finds libraries etc.
> libsubdir = 
> $(libdir)/gcc/$(real_target_noncanonical)/$(version)$(accel_dir_suffix)
> +# Directory in which the compiler finds headers.
> +libsubincludedir = $(libdir)/gcc/$(target_alias)/$(version)/include
> # Directory in which the compiler finds executables
> libexecsubdir = 
> $(libexecdir)/gcc/$(real_target_noncanonical)/$(version)$(accel_dir_suffix)
> # Directory in which all plugin resources are installed
> @@ -3642,6 +3644,7 @@ install-cpp: installdirs cpp$(exeext)
> # $(libdir)/gcc/include isn't currently searched by cpp.
> installdirs:
> $(mkinstalldirs) $(DESTDIR)$(libsubdir)
> + $(mkinstalldirs) $(DESTDIR)$(libsubincludedir)
> $(mkinstalldirs) $(DESTDIR)$(libexecsubdir)
> $(mkinstalldirs) $(DESTDIR)$(bindir)
> $(mkinstalldirs) $(DESTDIR)$(includedir)
> diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
> index 248ec45b729..ba1b3e95da5 100644
> --- a/gcc/jit/Make-lang.in
> +++ b/gcc/jit/Make-lang.in
> @@ -360,9 +360,9 @@ selftest-jit:
> # Install hooks:
> jit.install-headers: installdirs
> $(INSTALL_DATA) $(srcdir)/jit/libgccjit.h \
> - $(DESTDIR)$(includedir)/libgccjit.h
> + $(DESTDIR)$(libsubincludedir)/libgccjit.h
> $(INSTALL_DATA) $(srcdir)/jit/libgccjit++.h \
> - $(DESTDIR)$(includedir)/libgccjit++.h
> + $(DESTDIR)$(libsubincludedir)/libgccjit++.h
> 
> ifneq (,$(findstring mingw,$(target)))
> jit.install-common: installdirs jit.install-headers
> --
> 2.38.0


[PATCH v2 8/8] RISCV: Weaken mem_thread_fence

2023-04-05 Thread Patrick O'Neill
This change brings atomic fences in line with table A.6 of the ISA
manual.

Relax mem_thread_fence according to the memmodel given.

2023-04-05 Patrick O'Neill 

* riscv.cc: Expose helper functions to sync.md.
* riscv-protos.h: Likewise.
* sync.md (mem_thread_fence_1): Change fence depending on
aquire/release requirements.
* amo-thread-fence-1: New test.
* amo-thread-fence-2: Likewise.
* amo-thread-fence-3: Likewise.
* amo-thread-fence-4: Likewise.
* amo-thread-fence-5: Likewise.

Signed-off-by: Patrick O'Neill 
---
 gcc/config/riscv/riscv-protos.h |  2 ++
 gcc/config/riscv/riscv.cc   |  4 ++--
 gcc/config/riscv/sync.md| 17 ++---
 .../gcc.target/riscv/amo-thread-fence-1.c   |  6 ++
 .../gcc.target/riscv/amo-thread-fence-2.c   |  6 ++
 .../gcc.target/riscv/amo-thread-fence-3.c   |  6 ++
 .../gcc.target/riscv/amo-thread-fence-4.c   |  6 ++
 .../gcc.target/riscv/amo-thread-fence-5.c   |  6 ++
 8 files changed, 48 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-5.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index b03edc3e8a5..233b8070047 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -81,6 +81,8 @@ extern void riscv_reinit (void);
 extern poly_uint64 riscv_regmode_natural_size (machine_mode);
 extern bool riscv_v_ext_vector_mode_p (machine_mode);
 extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
+extern bool riscv_memmodel_needs_amo_acquire (enum memmodel);
+extern bool riscv_memmodel_needs_amo_release (enum memmodel);
 extern enum memmodel riscv_union_memmodels (enum memmodel, enum memmodel);
 
 /* Routines implemented in riscv-c.cc.  */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 061d2cf42b4..27d876ac44c 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4311,7 +4311,7 @@ riscv_union_memmodels (enum memmodel model1, enum 
memmodel model2)
 /* Return true if the .AQ suffix should be added to an AMO to implement the
acquire portion of memory model MODEL.  */
 
-static bool
+bool
 riscv_memmodel_needs_amo_acquire (enum memmodel model)
 {
   switch (model)
@@ -4334,7 +4334,7 @@ riscv_memmodel_needs_amo_acquire (enum memmodel model)
 /* Return true if the .RL suffix should be added to an AMO to implement the
release portion of memory model MODEL.  */
 
-static bool
+bool
 riscv_memmodel_needs_amo_release (enum memmodel model)
 {
   switch (model)
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index cdd227721e1..4204c956bd6 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -42,14 +42,25 @@
   DONE;
 })
 
-;; Until the RISC-V memory model (hence its mapping from C++) is finalized,
-;; conservatively emit a full FENCE.
 (define_insn "mem_thread_fence_1"
   [(set (match_operand:BLK 0 "" "")
(unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
(match_operand:SI 1 "const_int_operand" "")] ;; model
   ""
-  "fence\tiorw,iorw")
+  {
+enum memmodel model = (enum memmodel) INTVAL (operands[1]);
+model = memmodel_base (model);
+if (model == MEMMODEL_ACQ_REL)
+   return "fence.tso";
+else if (riscv_memmodel_needs_amo_acquire (model) &&
+riscv_memmodel_needs_amo_release (model))
+   return "fence\trw,rw";
+else if (riscv_memmodel_needs_amo_acquire (model))
+   return "fence\tr,rw";
+else if (riscv_memmodel_needs_amo_release (model))
+   return "fence\trw,w";
+  }
+  [(set (attr "length") (const_int 4))])
 
 ;; Atomic memory operations.
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c
new file mode 100644
index 000..833629bf2f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "fence\t" } } */
+
+int main() {
+  __atomic_thread_fence(__ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c
new file mode 100644
index 000..3395ee41dbb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler "fence\tr,rw" } } */
+
+int main() {
+  __atomic_thread_fence(__ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c 
b/gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c
new file mode 100644

[PATCH v2 7/8] RISCV: Weaken atomic stores

2023-04-05 Thread Patrick O'Neill
This change brings atomic stores in line with table A.6 of the ISA
manual.

2023-04-05 Patrick O'Neill 

PR target/89835
* sync.md (atomic_store): Use simple store instruction in
combination with a fence.
* pr89835.c: New test.

Signed-off-by: Patrick O'Neill 
---
 gcc/config/riscv/sync.md | 17 -
 gcc/testsuite/gcc.target/riscv/pr89835.c |  9 +
 2 files changed, 21 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr89835.c

diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index b1a12545a19..cdd227721e1 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -53,17 +53,24 @@
 
 ;; Atomic memory operations.
 
-;; Implement atomic stores with amoswap.  Fall back to fences for atomic loads.
+;; Implement atomic stores with a leading fence.  Fall back to fences for 
atomic loads.
 (define_insn "atomic_store"
   [(set (match_operand:GPR 0 "memory_operand" "=A")
 (unspec_volatile:GPR
   [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
(match_operand:SI 2 "const_int_operand")]  ;; model
   UNSPEC_ATOMIC_STORE))]
-  "TARGET_ATOMIC"
-  "amoswap.%A2 zero,%z1,%0"
-  [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 4))])
+  ""
+  {
+enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+model = memmodel_base (model);
+if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_RELEASE)
+  return "fence\tr,rw\;"
+"s\t%z1,%0";
+else
+  return "s\t%z1,%0\;";
+  }
+  [(set (attr "length") (const_int 8))])
 
 (define_insn "atomic_"
   [(set (match_operand:GPR 0 "memory_operand" "+A")
diff --git a/gcc/testsuite/gcc.target/riscv/pr89835.c 
b/gcc/testsuite/gcc.target/riscv/pr89835.c
new file mode 100644
index 000..ab190e11b60
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr89835.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* Verify that relaxed atomic stores use simple store instuctions.  */
+/* { dg-final { scan-assembler-not "amoswap" } } */
+
+void
+foo(int bar, int baz)
+{
+  __atomic_store_n(, baz, __ATOMIC_RELAXED);
+}
-- 
2.25.1



[PATCH v2 3/8] RISCV: Enforce atomic compare_exchange SEQ_CST

2023-04-05 Thread Patrick O'Neill
This patch enforces SEQ_CST for atomic compare_exchange ops.

Replace Fence/LR.aq/SC.aq pairs with strong SEQ_CST LR.aqrl/SC.rl pairs
recommended by table A.6 of the ISA manual.

2023-04-05 Patrick O'Neill 

* sync.md: Change FENCE/LR.aq/SC.aq into sequentially
consistent LR.aqrl/SC.rl pair.

Signed-off-by: Patrick O'Neill 
---
 gcc/config/riscv/sync.md | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index c932ef87b9d..de42245981b 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -115,9 +115,16 @@
 UNSPEC_COMPARE_AND_SWAP))
(clobber (match_scratch:GPR 6 "="))]
   "TARGET_ATOMIC"
-  "%F5 1: lr.%A5 %0,%1; bne %0,%z2,1f; sc.%A4 %6,%z3,%1; bnez %6,1b; 
1:"
+  {
+return "1:\;"
+  "lr..aqrl\t%0,%1\;"
+  "bne\t%0,%z2,1f\;"
+  "sc..rl\t%6,%z3,%1\;"
+  "bnez\t%6,1b\;"
+  "1:";
+  }
   [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 20))])
+   (set (attr "length") (const_int 16))])
 
 (define_expand "atomic_compare_and_swap"
   [(match_operand:SI 0 "register_operand" "")   ;; bool output
-- 
2.25.1



[PATCH v2 2/8] RISCV: Enforce Libatomic LR/SC SEQ_CST

2023-04-05 Thread Patrick O'Neill
Replace LR.aq/SC.rl pairs with the SEQ_CST LR.aqrl/SC.rl pairs
recommended by table A.6 of the ISA manual.

2023-04-05 Patrick O'Neill 

* atomic.c: Change LR.aq/SC.rl pairs into sequentially
consistent LR.aqrl/SC.rl pair.

Signed-off-by: Patrick O'Neill 
---
 libgcc/config/riscv/atomic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libgcc/config/riscv/atomic.c b/libgcc/config/riscv/atomic.c
index 69f53623509..5f895939b0b 100644
--- a/libgcc/config/riscv/atomic.c
+++ b/libgcc/config/riscv/atomic.c
@@ -39,7 +39,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 unsigned old, tmp1, tmp2;  \
\
 asm volatile ("1:\n\t" \
- "lr.w.aq %[old], %[mem]\n\t"  \
+ "lr.w.aqrl %[old], %[mem]\n\t"\
  #insn " %[tmp1], %[old], %[value]\n\t"\
  invert\
  "and %[tmp1], %[tmp1], %[mask]\n\t"   \
@@ -73,7 +73,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 unsigned old, tmp1;
\
\
 asm volatile ("1:\n\t" \
- "lr.w.aq %[old], %[mem]\n\t"  \
+ "lr.w.aqrl %[old], %[mem]\n\t"\
  "and %[tmp1], %[old], %[mask]\n\t"\
  "bne %[tmp1], %[o], 1f\n\t"   \
  "and %[tmp1], %[old], %[not_mask]\n\t"\
-- 
2.25.1



[PATCH v2 6/8] RISCV: Weaken compare_exchange LR/SC pairs

2023-04-05 Thread Patrick O'Neill
Introduce the %I and %J flags for setting the .aqrl bits on LR/SC pairs
as needed.

Atomic compare and exchange ops provide success and failure memory
models. C++17 and later place no restrictions on the relative strength
of each model, so ensure we cover both by using a model that enforces
the ordering of both given models.

This change brings compare_exchange LR/SC ops in line with table A.6 of the ISA
manual.

2023-04-05 Patrick O'Neill 

* riscv.cc: Add function to get the union of two
memmodels in sync.md.
* riscv-protos.h: Likewise.
* sync.md (atomic_cas_value_strong): Remove static
.aqrl bits on SC op/.rl bits on LR op and replace with
optimized %I, %J flags.
* compare-exchange-atomics-model-1.c: New test.
* compare-exchange-atomics-model-2.c: Likewise.
* compare-exchange-atomics-model-3.c: Likewise.
* compare-exchange-atomics-model-4.c: Likewise.
* compare-exchange-atomics-model-5.c: Likewise.
* compare-exchange-atomics-model-6.c: Likewise.

Signed-off-by: Patrick O'Neill 
---
 gcc/config/riscv/riscv-protos.h   |  3 ++
 gcc/config/riscv/riscv.cc | 44 +++
 gcc/config/riscv/sync.md  |  9 +++-
 .../riscv/compare-exchange-atomics-model-1.c  | 12 +
 .../riscv/compare-exchange-atomics-model-2.c  | 12 +
 .../riscv/compare-exchange-atomics-model-3.c  | 12 +
 .../riscv/compare-exchange-atomics-model-4.c  | 12 +
 .../riscv/compare-exchange-atomics-model-5.c  | 12 +
 8 files changed, 114 insertions(+), 2 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-1.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-2.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-3.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-4.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-5.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 4611447ddde..b03edc3e8a5 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_RISCV_PROTOS_H
 #define GCC_RISCV_PROTOS_H
 
+#include "memmodel.h"
+
 /* Symbol types we understand.  The order of this list must match that of
the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST.  */
 enum riscv_symbol_type {
@@ -79,6 +81,7 @@ extern void riscv_reinit (void);
 extern poly_uint64 riscv_regmode_natural_size (machine_mode);
 extern bool riscv_v_ext_vector_mode_p (machine_mode);
 extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
+extern enum memmodel riscv_union_memmodels (enum memmodel, enum memmodel);
 
 /* Routines implemented in riscv-c.cc.  */
 void riscv_cpu_cpp_builtins (cpp_reader *);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 6576e9ae524..061d2cf42b4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4278,6 +4278,36 @@ riscv_print_operand_reloc (FILE *file, rtx op, bool 
hi_reloc)
   fputc (')', file);
 }
 
+/* Return the memory model that encapuslates both given models.  */
+
+enum memmodel
+riscv_union_memmodels (enum memmodel model1, enum memmodel model2)
+{
+  model1 = memmodel_base (model1);
+  model2 = memmodel_base (model2);
+
+  enum memmodel weaker = model1 <= model2 ? model1: model2;
+  enum memmodel stronger = model1 > model2 ? model1: model2;
+
+  switch (stronger)
+{
+  case MEMMODEL_SEQ_CST:
+  case MEMMODEL_ACQ_REL:
+   return stronger;
+  case MEMMODEL_RELEASE:
+   if (weaker == MEMMODEL_ACQUIRE || weaker == MEMMODEL_CONSUME)
+ return MEMMODEL_ACQ_REL;
+   else
+ return stronger;
+  case MEMMODEL_ACQUIRE:
+  case MEMMODEL_CONSUME:
+  case MEMMODEL_RELAXED:
+   return stronger;
+  default:
+   gcc_unreachable ();
+}
+}
+
 /* Return true if the .AQ suffix should be added to an AMO to implement the
acquire portion of memory model MODEL.  */
 
@@ -4331,6 +4361,8 @@ riscv_memmodel_needs_amo_release (enum memmodel model)
'R' Print the low-part relocation associated with OP.
'C' Print the integer branch condition for comparison OP.
'A' Print the atomic operation suffix for memory model OP.
+   'I' Print the LR suffix for memory model OP.
+   'J' Print the SC suffix for memory model OP.
'z' Print x0 if OP is zero, otherwise print OP normally.
'i' Print i if the operand is not a register.
'S' Print shift-index of single-bit mask OP.
@@ -4500,6 +4532,18 @@ riscv_print_operand (FILE *file, rtx op, int letter)
fputs (".rl", file);
   break;
 
+case 'I':
+  if (model == MEMMODEL_SEQ_CST)
+   fputs (".aqrl", file);
+  else if (riscv_memmodel_needs_amo_acquire (model))
+   

[PATCH v2 5/8] RISCV: Eliminate AMO op fences

2023-04-05 Thread Patrick O'Neill
Atomic operations with the appropriate bits set already enfore release
semantics. Remove unnecessary release fences from atomic ops.

This change brings AMO ops in line with table A.6 of the ISA manual.

2023-04-05 Patrick O'Neill 

* riscv.cc (riscv_memmodel_needs_amo_acquire): Change function
name.
* riscv.cc (riscv_print_operand): Remove unneeded %F case.
* sync.md: Remove unneeded fences.

Signed-off-by: Patrick O'Neill 
---
 gcc/config/riscv/riscv.cc | 16 +---
 gcc/config/riscv/sync.md  | 16 
 2 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8ffee494fbe..6576e9ae524 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4301,11 +4301,11 @@ riscv_memmodel_needs_amo_acquire (enum memmodel model)
 }
 }
 
-/* Return true if a FENCE should be emitted to before a memory access to
-   implement the release portion of memory model MODEL.  */
+/* Return true if the .RL suffix should be added to an AMO to implement the
+   release portion of memory model MODEL.  */
 
 static bool
-riscv_memmodel_needs_release_fence (enum memmodel model)
+riscv_memmodel_needs_amo_release (enum memmodel model)
 {
   switch (model)
 {
@@ -4331,7 +4331,6 @@ riscv_memmodel_needs_release_fence (enum memmodel model)
'R' Print the low-part relocation associated with OP.
'C' Print the integer branch condition for comparison OP.
'A' Print the atomic operation suffix for memory model OP.
-   'F' Print a FENCE if the memory model requires a release.
'z' Print x0 if OP is zero, otherwise print OP normally.
'i' Print i if the operand is not a register.
'S' Print shift-index of single-bit mask OP.
@@ -4493,19 +4492,14 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 
 case 'A':
   if (riscv_memmodel_needs_amo_acquire (model) &&
- riscv_memmodel_needs_release_fence (model))
+ riscv_memmodel_needs_amo_release (model))
fputs (".aqrl", file);
   else if (riscv_memmodel_needs_amo_acquire (model))
fputs (".aq", file);
-  else if (riscv_memmodel_needs_release_fence (model))
+  else if (riscv_memmodel_needs_amo_release (model))
fputs (".rl", file);
   break;
 
-case 'F':
-  if (riscv_memmodel_needs_release_fence (model))
-   fputs ("fence iorw,ow; ", file);
-  break;
-
 case 'i':
   if (code != REG)
 fputs ("i", file);
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index de42245981b..1aa9ac81cee 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -61,9 +61,9 @@
(match_operand:SI 2 "const_int_operand")]  ;; model
   UNSPEC_ATOMIC_STORE))]
   "TARGET_ATOMIC"
-  "%F2amoswap.%A2 zero,%z1,%0"
+  "amoswap.%A2 zero,%z1,%0"
   [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 8))])
+   (set (attr "length") (const_int 4))])
 
 (define_insn "atomic_"
   [(set (match_operand:GPR 0 "memory_operand" "+A")
@@ -73,9 +73,9 @@
   (match_operand:SI 2 "const_int_operand")] ;; model
 UNSPEC_SYNC_OLD_OP))]
   "TARGET_ATOMIC"
-  "%F2amo.%A2 zero,%z1,%0"
+  "amo.%A2 zero,%z1,%0"
   [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 8))])
+   (set (attr "length") (const_int 4))])
 
 (define_insn "atomic_fetch_"
   [(set (match_operand:GPR 0 "register_operand" "=")
@@ -87,9 +87,9 @@
   (match_operand:SI 3 "const_int_operand")] ;; model
 UNSPEC_SYNC_OLD_OP))]
   "TARGET_ATOMIC"
-  "%F3amo.%A3 %0,%z2,%1"
+  "amo.%A3 %0,%z2,%1"
   [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 8))])
+   (set (attr "length") (const_int 4))])
 
 (define_insn "atomic_exchange"
   [(set (match_operand:GPR 0 "register_operand" "=")
@@ -100,9 +100,9 @@
(set (match_dup 1)
(match_operand:GPR 2 "register_operand" "0"))]
   "TARGET_ATOMIC"
-  "%F3amoswap.%A3 %0,%z2,%1"
+  "amoswap.%A3 %0,%z2,%1"
   [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 8))])
+   (set (attr "length") (const_int 4))])
 
 (define_insn "atomic_cas_value_strong"
   [(set (match_operand:GPR 0 "register_operand" "=")
-- 
2.25.1



[PATCH v2 4/8] RISCV: Add AMO release bits

2023-04-05 Thread Patrick O'Neill
This patch sets the relevant .rl bits on amo operations.

2023-04-05 Patrick O'Neill 

* riscv.cc (riscv_print_operand): change behavior of %A to
include release bits.

Signed-off-by: Patrick O'Neill 
---
 gcc/config/riscv/riscv.cc | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8f5636c93ed..8ffee494fbe 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4492,8 +4492,13 @@ riscv_print_operand (FILE *file, rtx op, int letter)
   break;
 
 case 'A':
-  if (riscv_memmodel_needs_amo_acquire (model))
+  if (riscv_memmodel_needs_amo_acquire (model) &&
+ riscv_memmodel_needs_release_fence (model))
+   fputs (".aqrl", file);
+  else if (riscv_memmodel_needs_amo_acquire (model))
fputs (".aq", file);
+  else if (riscv_memmodel_needs_release_fence (model))
+   fputs (".rl", file);
   break;
 
 case 'F':
-- 
2.25.1



[PATCH v2 1/8] RISCV: Eliminate SYNC memory models

2023-04-05 Thread Patrick O'Neill
Remove references to MEMMODEL_SYNC_* models by converting via
memmodel_base().

2023-04-05 Patrick O'Neill 

* atomic.c: Remove MEMMODEL_SYNC_* cases and sanitize memmodel 
input with memmodel_base

Signed-off-by: Patrick O'Neill 
---
 gcc/config/riscv/riscv.cc | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 76eee4a55e9..8f5636c93ed 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4288,14 +4288,11 @@ riscv_memmodel_needs_amo_acquire (enum memmodel model)
 {
   case MEMMODEL_ACQ_REL:
   case MEMMODEL_SEQ_CST:
-  case MEMMODEL_SYNC_SEQ_CST:
   case MEMMODEL_ACQUIRE:
   case MEMMODEL_CONSUME:
-  case MEMMODEL_SYNC_ACQUIRE:
return true;
 
   case MEMMODEL_RELEASE:
-  case MEMMODEL_SYNC_RELEASE:
   case MEMMODEL_RELAXED:
return false;
 
@@ -4314,14 +4311,11 @@ riscv_memmodel_needs_release_fence (enum memmodel model)
 {
   case MEMMODEL_ACQ_REL:
   case MEMMODEL_SEQ_CST:
-  case MEMMODEL_SYNC_SEQ_CST:
   case MEMMODEL_RELEASE:
-  case MEMMODEL_SYNC_RELEASE:
return true;
 
   case MEMMODEL_ACQUIRE:
   case MEMMODEL_CONSUME:
-  case MEMMODEL_SYNC_ACQUIRE:
   case MEMMODEL_RELAXED:
return false;
 
@@ -4360,6 +4354,7 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 }
   machine_mode mode = GET_MODE (op);
   enum rtx_code code = GET_CODE (op);
+  const enum memmodel model = memmodel_base (INTVAL (op));
 
   switch (letter)
 {
@@ -4497,12 +4492,12 @@ riscv_print_operand (FILE *file, rtx op, int letter)
   break;
 
 case 'A':
-  if (riscv_memmodel_needs_amo_acquire ((enum memmodel) INTVAL (op)))
+  if (riscv_memmodel_needs_amo_acquire (model))
fputs (".aq", file);
   break;
 
 case 'F':
-  if (riscv_memmodel_needs_release_fence ((enum memmodel) INTVAL (op)))
+  if (riscv_memmodel_needs_release_fence (model))
fputs ("fence iorw,ow; ", file);
   break;
 
-- 
2.25.1



[PATCH v2 0/8] RISCV: Implement ISA Manual Table A.6 Mappings

2023-04-05 Thread Patrick O'Neill
This patchset aims to bring the RISCV atomics implementation in line
with the recommended mapping present in table A.6 of the ISA manual.
  
https://github.com/riscv/riscv-isa-manual/blob/c7cf84547b3aefacab5463add1734c1602b67a49/src/memory.tex#L1083-L1157

The current mapping in GCC is not internally consistent. Andrea Parri
pointed this out here along with a litmus test:
  https://inbox.sourceware.org/gcc-patches/Y1GbJuhcBFpPGJQ0@andrea/

As a result, we have an opportunity to jump straight to the A.6
implementation (meaning we will be compatible with LLVM's mappings which
are A.6). Ideally we move to the A.6 mappings before more binaries are
built/distributed and it becomes more painful to switch.

Patch 1 simplifies the memmodel to ignore MEMMODEL_SYNC_* cases (legacy
cases that aren't handled differently for RISC-V).
Patches 2-4 make the mappings strictly stronger.
Patches 5-8 weaken the mappings to be in line with table A.6 of the ISA
manual.

Christoph Muellner also submitted a similar patchset here:
  https://gcc.gnu.org/pipermail/gcc-patches/2022-May/595712.html
I used my previous patchset as a starting point since it was easier for 
me.

LLVM mapping notes:
* LLVM emits corresponding fences for atomic_signal_fence instructions.
  This seems to be an oversight since AFAIK atomic_signal_fence acts as
  a compiler directive. GCC does not emit any fences for
  atomic_signal_fence instructions.

Remaining work:
* After this patchset, GCC still emits a full fence rw,rw after a
  SEQ_CST load (fence r,rw is recommended by table A.6).
  This can be relaxed in a future patch as it is strictly stronger than
  A.6's recommendation - I wanted to get this series out to be
  considered for GCC 13.

Patchset v1:
  https://gcc.gnu.org/pipermail/gcc-patches/2022-April/592950.html

Changes for v2:
* Use memmodel_base rather than a custom simplify_memmodel function
  (Inspired by Christoph Muellner's patch 1/9)
* Move instruction styling change from [v1 5/7] to [v2 3/8] to reduce
  [v2 6/8]'s complexity
* Eliminated %K flag for atomic store introduced in v1 in favor of
  if/else
* Rebase/test

* PR target/89835: The RISC-V target uses amoswap.w for relaxed stores

Patrick O'Neill (8):
  RISCV: Eliminate SYNC memory models
  RISCV: Enforce Libatomic LR/SC SEQ_CST
  RISCV: Enforce atomic compare_exchange SEQ_CST
  RISCV: Add AMO release bits
  RISCV: Eliminate AMO op fences
  RISCV: Weaken compare_exchange LR/SC pairs
  RISCV: Weaken atomic stores
  RISCV: Weaken mem_thread_fence

 gcc/config/riscv/riscv-protos.h   |  5 ++
 gcc/config/riscv/riscv.cc | 70 ++-
 gcc/config/riscv/sync.md  | 62 +++-
 .../gcc.target/riscv/amo-thread-fence-1.c |  6 ++
 .../gcc.target/riscv/amo-thread-fence-2.c |  6 ++
 .../gcc.target/riscv/amo-thread-fence-3.c |  6 ++
 .../gcc.target/riscv/amo-thread-fence-4.c |  6 ++
 .../gcc.target/riscv/amo-thread-fence-5.c |  6 ++
 .../riscv/compare-exchange-atomics-model-1.c  | 12 
 .../riscv/compare-exchange-atomics-model-2.c  | 12 
 .../riscv/compare-exchange-atomics-model-3.c  | 12 
 .../riscv/compare-exchange-atomics-model-4.c  | 12 
 .../riscv/compare-exchange-atomics-model-5.c  | 12 
 gcc/testsuite/gcc.target/riscv/pr89835.c  |  9 +++
 libgcc/config/riscv/atomic.c  |  4 +-
 15 files changed, 206 insertions(+), 34 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo-thread-fence-5.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-1.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-2.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-3.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-4.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/compare-exchange-atomics-model-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/pr89835.c

-- 
2.25.1



Re: [Patch, fortran] PR104272 - finalizer gets called during allocate

2023-04-05 Thread Paul Richard Thomas via Gcc-patches
Hi Harald,

Quite right - good spot. There was an 'else' that turned out to be
unnecessary.

Thanks

Paul


On Wed, 5 Apr 2023 at 19:50, Harald Anlauf  wrote:

> Hi Paul,
>
> On 4/5/23 08:53, Paul Richard Thomas via Gcc-patches wrote:
> > Hi All,
> >
> > This is a first in my recent experience - a very old bug that produces
> too
> > many finalizations! It results from a bit of a fix up, where class
> objects
> > are allocated using the derived typespec, rather than a source or mold
> > expression. This occurs upstream in resolve.cc, where the default
> > initializer is assigned to expr3 but no means are provided to identify
> what
> > it is. The patch applies a signaling bit-field to the ext field of
> > gfc_code, which then suppresses the deallocation of allocatable
> components
> > in the allocate expression. I have checked that this does not cause
> memory
> > leaks, even though the number of builtin_frees in class_result_8.f90 goes
> > down by one.
>
> can you have a look again at the logic in the hunk touching
> trans-stmt.cc (gfc_trans_allocate)?  I haven't checked in detail,
> but it seems possible that you get a stale tmp in the
> gfc_prepend_expr_to_block if (code->ext.alloc.expr3_not_explicit == 0).
> Wouldn't it make more sense to move this condition before the braces
> as part of the overall condition?
>
> > OK for mainline?
>
> Otherwise this LGTM.
>
> Thanks for the patch!
>
> Harald
>
> > Paul
> >
> > Fortran: Fix and excess finalization during allocation [PR104272]
> >
> > 2023-04-04  Paul Thomas  
> >
> > gcc/fortran
> > PR fortran/104272
> > * gfortran.h : Add expr3_not_explicit bit field to gfc_code.
> > * resolve.cc (resolve_allocate_expr): Set bit field when the
> > default initializer is applied to expr3.
> > * trans-stmt.cc (gfc_trans_allocate): If expr3_not_explicit is
> > set, do not deallocate expr3.
> >
> > gcc/testsuite/
> > PR fortran/104272
> > * gfortran.dg/class_result_8.f90 : Number of builtin_frees down
> > from 6 to 5 without memory leaks.
> > * gfortran.dg/finalize_52.f90: New test
>
>

-- 
"If you can't explain it simply, you don't understand it well enough" -
Albert Einstein


Re: [PATCH] c++: satisfaction and ARGUMENT_PACK_SELECT [PR105644]

2023-04-05 Thread Patrick Palka via Gcc-patches
On Mon, 3 Apr 2023, Jason Merrill wrote:

> On 4/3/23 10:49, Patrick Palka wrote:
> > This testcase demonstrates we can legitimately enter satisfaction with
> > an ARGUMENT_PACK_SELECT argument, which is problematic because we can't
> > store such arguments in the satisfaction cache (or any other hash table).
> > 
> > Since this appears to be possible only during constrained auto deduction
> > for a return-type-requirement, the most appropriate spot to fix this seems
> > to be from do_auto_deduction, by calling preserve_args to strip A_P_S args
> > before entering satisfaction.
> > 
> > +++ b/gcc/cp/pt.cc
> > @@ -30965,6 +30965,12 @@ do_auto_deduction (tree type, tree init, tree
> > auto_node,
> > return type;
> > }
> >   +  /* We can see an ARGUMENT_PACK_SELECT argument when evaluating
> > +a return-type-requirement.  Get rid of them before entering
> > +satisfaction, since the satisfaction cache can't handle them.  */
> > +  if (context == adc_requirement)
> > +   outer_targs = preserve_args (outer_targs);
> 
> I'd like to get do_auto_deduction out of the business of handling
> return-type-requirements, since there is no longer any actual deduction
> involved (as there was in the TS).  So I'd prefer not to add any more tweaks
> there.
> 
> Maybe this should happen higher up, in tsubst_requires_expr?  Maybe just
> before the call to add_extra_args?

Interestingly, calling preserve_args from tsubst_requires_expr breaks
cases where a requires-expression contains an inner pack expansion over
the same pack as the outer expansion, such as 'Ts... ts' in

  template
  concept C = (requires (Ts... ts) { Ts(); } && ...);

  static_assert(C);

and 'sizeof...(Ts)' in

  template struct A;

  template
  concept C = (requires { typename A; } && ...);

  static_assert(C);

because we need to hold on to the ARGUMENT_PACK_SELECT version of the
argument in order to properly substitute 'Ts... ts' and 'sizeof...(Ts)'
during each outer expansion, but calling preserve_args gets rid of
the A_P_S.

And on second thought, narrowly calling preserve_args from
do_auto_deduction (or type_deducible_p) isn't quite correct either,
consider:

  template
  concept C = __is_same(T, U) && N > 1;

  template
  concept D = (requires { { Ts() } -> C; } && ...);

  static_assert(D);

We need to hold on to the A_P_S in order to check the
return-type-requirement C, but the satisfaction
cache can't handle A_P_S!

The following non-requires-expr version of that example works:

  template
  concept C = __is_same(T, U) && N > 1;

  template
  concept D = (C && ...);

  static_assert(D);

because here we directly substitute into the concept-id
C, so we effectively end up checking
satisfaction of C and C directly
and never enter satisfaction with an A_P_S argument.

So ISTM the satisfaction cache might need to be able to cache A_P_S
arguments perhaps by changing preserve_args to instead make a copy of
each A_P_S and set a flag on this copy to indicate it's "stable"
and therefore suitable for hashing etc.



[PATCH] PR tree-optimization/109417 - Check if dependency is valid before using in may_recompute_p.

2023-04-05 Thread Andrew MacLeod via Gcc-patches
When a statement is first processed, any SSA_NAMEs that are dependencies 
are cached for quick future access.


if we ;later rewrite the statement (say propagate a constant into it), 
its possible the ssa-name in this cache is no longer active.   Normally 
this is not a problem, but the changed to may_recompute_p forgot to take 
that into account, and was checking a dependency from the cache that was 
in the SSA_NAME_FREE_LIST. It thus had no SSA_NAME_DEF_STMT when we were 
expecting one.


This patch simply rejects dependencies from consideration if they are in 
the free list.


Bootstrapping on x86_64-pc-linux-gnu  and presuming no regressio0ns, OK 
for trunk?


Andrew
commit ecd86e159e8499feb387bc4d99bd37a5fd6a0d68
Author: Andrew MacLeod 
Date:   Wed Apr 5 15:59:38 2023 -0400

Check if dependency is valid before using in may_recompute_p.

When the IL is rewritten after a statement has been processed and
dependencies cached, its possible that an ssa-name in the dependency
cache is no longer in the IL.  Check this before trying to recompute.

PR tree-optimization/109417
gcc/
* gimple-range-gori.cc (gori_compute::may_recompute_p): Check if
dependency is in SSA_NAME_FREE_LIST.

gcc/testsuite/
* gcc.dg/pr109417.c: New.

diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 5f4313b27dd..6e2f9533038 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -1314,7 +1314,9 @@ gori_compute::may_recompute_p (tree name, basic_block bb, int depth)
   tree dep2 = depend2 (name);
 
   // If the first dependency is not set, there is no recomputation.
-  if (!dep1)
+  // Dependencies reflect original IL, not current state.   Check if the
+  // SSA_NAME is still valid as well.
+  if (!dep1 || SSA_NAME_IN_FREE_LIST (dep1))
 return false;
 
   // Don't recalculate PHIs or statements with side_effects.
diff --git a/gcc/testsuite/gcc.dg/pr109417.c b/gcc/testsuite/gcc.dg/pr109417.c
new file mode 100644
index 000..15711dbbafe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr109417.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+int printf(const char *, ...);
+int c, d, *e, f[1][2], g;
+int main() {
+  int h = 0, *a = , **b[1] = {};
+  while (e)
+while (g) {
+L:
+  for (h = 0; h < 2; h++) {
+while (d)
+  for (*e = 0; *e < 1;)
+printf("0");
+while (c)
+  ;
+f[g][h] = 0;
+  }
+}
+  if (h)
+goto L;
+  return 0;
+}
+


Re: [RFA][Bug target/108892 ][13 regression] Force re-recognition after changing RTL structure of an insn

2023-04-05 Thread Segher Boessenkool
Hi again,

On Wed, Apr 05, 2023 at 11:43:30AM -0600, Jeff Law wrote:
> On 4/5/23 11:38, Segher Boessenkool wrote:
> >Right.  But it seems to me it has been there all those years?  Does the
> >new testcase fail on older branches?  Even if not, it seems clear it is
> >wrong on the older branches as well!
> I bet if I put the special pattern into an old branch, then ran the 
> testcase it'd probably trigger.
> 
> >But if you think it is too dangerous to backport, let's not.
> It should be crazy safe.  Not a tall worried about it being dangerous. 
> More a case of not seeing a lot of value given how narrow the problem is.

Please just do the usual then?  git cherry-pick -x $some_hash  on the
release branches, and push it if that works flawlessly?  And if it
doesn't, *that* is a good reason to skip backporting it, sure :-)


Segher


Re: [Patch, fortran] PR104272 - finalizer gets called during allocate

2023-04-05 Thread Harald Anlauf via Gcc-patches

On 4/5/23 20:50, Harald Anlauf via Gcc-patches wrote:

can you have a look again at the logic in the hunk touching
trans-stmt.cc (gfc_trans_allocate)?  I haven't checked in detail,
but it seems possible that you get a stale tmp in the
gfc_prepend_expr_to_block if (code->ext.alloc.expr3_not_explicit == 0).


Oops, I meant if (code->ext.alloc.expr3_not_explicit != 0)


Wouldn't it make more sense to move this condition before the braces
as part of the overall condition?


OK for mainline?


Otherwise this LGTM.

Thanks for the patch!

Harald





Re: [Patch, fortran] PR104272 - finalizer gets called during allocate

2023-04-05 Thread Harald Anlauf via Gcc-patches

Hi Paul,

On 4/5/23 08:53, Paul Richard Thomas via Gcc-patches wrote:

Hi All,

This is a first in my recent experience - a very old bug that produces too
many finalizations! It results from a bit of a fix up, where class objects
are allocated using the derived typespec, rather than a source or mold
expression. This occurs upstream in resolve.cc, where the default
initializer is assigned to expr3 but no means are provided to identify what
it is. The patch applies a signaling bit-field to the ext field of
gfc_code, which then suppresses the deallocation of allocatable components
in the allocate expression. I have checked that this does not cause memory
leaks, even though the number of builtin_frees in class_result_8.f90 goes
down by one.


can you have a look again at the logic in the hunk touching
trans-stmt.cc (gfc_trans_allocate)?  I haven't checked in detail,
but it seems possible that you get a stale tmp in the
gfc_prepend_expr_to_block if (code->ext.alloc.expr3_not_explicit == 0).
Wouldn't it make more sense to move this condition before the braces
as part of the overall condition?


OK for mainline?


Otherwise this LGTM.

Thanks for the patch!

Harald


Paul

Fortran: Fix and excess finalization during allocation [PR104272]

2023-04-04  Paul Thomas  

gcc/fortran
PR fortran/104272
* gfortran.h : Add expr3_not_explicit bit field to gfc_code.
* resolve.cc (resolve_allocate_expr): Set bit field when the
default initializer is applied to expr3.
* trans-stmt.cc (gfc_trans_allocate): If expr3_not_explicit is
set, do not deallocate expr3.

gcc/testsuite/
PR fortran/104272
* gfortran.dg/class_result_8.f90 : Number of builtin_frees down
from 6 to 5 without memory leaks.
* gfortran.dg/finalize_52.f90: New test




Re: [RFA][Bug target/108892 ][13 regression] Force re-recognition after changing RTL structure of an insn

2023-04-05 Thread Jeff Law




On 4/5/23 11:38, Segher Boessenkool wrote:

On Wed, Apr 05, 2023 at 09:07:30AM -0600, Jeff Law wrote:

On 4/5/23 08:21, Segher Boessenkool wrote:

On Wed, Mar 29, 2023 at 07:48:00AM -0600, Jeff Law wrote:

So as mentioned in the PR the underlying issue here is combine changes
the form of an existing insn, but fails to force re-recognition.  As a
result other parts of the compiler blow up.


[snip]


The fix is trivial, reset the INSN_CODE to force re-recognition in the
case where try_combine fails.


Thanks for the clear explanation!  Okay for trunk.  Also okay for all
backports (after a week or so on trunk).

Thanks.  I haven't seen this on any of the release branches, so no
strong opinions on backporting at this time.  It's a pretty narrow bug
(no surprise given its been latent for something like 10 years).


Right.  But it seems to me it has been there all those years?  Does the
new testcase fail on older branches?  Even if not, it seems clear it is
wrong on the older branches as well!
I bet if I put the special pattern into an old branch, then ran the 
testcase it'd probably trigger.




But if you think it is too dangerous to backport, let's not.
It should be crazy safe.  Not a tall worried about it being dangerous. 
More a case of not seeing a lot of value given how narrow the problem is.


jeff


Re: [RFA][Bug target/108892 ][13 regression] Force re-recognition after changing RTL structure of an insn

2023-04-05 Thread Segher Boessenkool
On Wed, Apr 05, 2023 at 09:07:30AM -0600, Jeff Law wrote:
> On 4/5/23 08:21, Segher Boessenkool wrote:
> >On Wed, Mar 29, 2023 at 07:48:00AM -0600, Jeff Law wrote:
> >>So as mentioned in the PR the underlying issue here is combine changes
> >>the form of an existing insn, but fails to force re-recognition.  As a
> >>result other parts of the compiler blow up.
> >
> >[snip]
> >
> >>The fix is trivial, reset the INSN_CODE to force re-recognition in the
> >>case where try_combine fails.
> >
> >Thanks for the clear explanation!  Okay for trunk.  Also okay for all
> >backports (after a week or so on trunk).
> Thanks.  I haven't seen this on any of the release branches, so no 
> strong opinions on backporting at this time.  It's a pretty narrow bug 
> (no surprise given its been latent for something like 10 years).

Right.  But it seems to me it has been there all those years?  Does the
new testcase fail on older branches?  Even if not, it seems clear it is
wrong on the older branches as well!

But if you think it is too dangerous to backport, let's not.

Thanks,


Segher


Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-05 Thread Andrew Pinski via Gcc-patches
On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
 wrote:
>
> On Wed, 5 Apr 2023, Patrick Palka wrote:
>
> > r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
> > non-types during the lookup, unless the TYPENAME_TYPE in question was
> > followed by the :: scope resolution operator.  But there is another
> > exception to this rule: we need to ignore non-types during the lookup
> > also if the TYPENAME_TYPE was named with a tag other than 'typename',
> > such as 'struct' or 'enum', as per [dcl.type.elab]/5.
> >
> > This patch implements this additional exception.  It occurred to me that
> > the tf_qualifying_scope flag is probably unnecessary if we'd use the
> > scope_type tag more thoroughly, but that requires parser changes that
> > are probably too risky at this stage.  (I'm working on addressing the
> > FIXME/TODOs here for GCC 14.)
> >
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > trunk?
> >
> >   PR c++/109420
> >
> > gcc/cp/ChangeLog:
> >
> >   * decl.cc (make_typename_type): Also ignore non-types during
> >   the lookup if tag_type is something other than none_type or
> >   typename_type.
> >   * pt.cc (tsubst) : Pass class_type or
> >   enum_type as tag_type to make_typename_type as appropriate
> >   instead of always passing typename_type.
> >
> > gcc/testsuite/ChangeLog:
> >
> >   * g++.dg/template/typename27.C: New test.
> > ---
> >  gcc/cp/decl.cc |  9 -
> >  gcc/cp/pt.cc   |  9 -
> >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> >  3 files changed, 35 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> >
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index 5369714f9b3..a0a20c5accc 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
> > tag_types tag_type,
> >   lookup will stop when we hit a dependent base.  */
> >if (!dependent_scope_p (context))
> >  {
> > -  bool want_type = (complain & tf_qualifying_scope);
> > +  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore 
> > non-types if
> > +  the tag corresponds to a class-key or 'enum' (or is scope_type), or 
> > if
> > +  this typename is followed by :: as per [basic.lookup.qual.general]/1.
> > +  TODO: If we'd set the scope_type tag accurately on all TYPENAME_TYPEs
> > +  that are followed by :: then we wouldn't need the tf_qualifying_scope
> > +  flag.  */
> > +  bool want_type = (tag_type != none_type && tag_type != typename_type)
> > + || (complain & tf_qualifying_scope);
>
> Here's v2 which just slightly improves this comment.  I reckon 
> [basic.lookup.elab]
> is a better reference than [dcl.type.elab]/5 for justifying why the
> lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.
>
> -- >8 --
>
> PR c++/109420
>
> gcc/cp/ChangeLog:
>
> * decl.cc (make_typename_type): Also ignore non-types during the
> lookup if tag_type corresponds to an elaborated-type-specifier.
> * pt.cc (tsubst) : Pass class_type or
> enum_type as tag_type to make_typename_type as appropriate
> instead of always passing typename_type.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/template/typename27.C: New test.
> ---
>  gcc/cp/decl.cc | 12 +++-
>  gcc/cp/pt.cc   |  9 -
>  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
>  3 files changed, 38 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
>
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 5369714f9b3..772c059dc2c 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
> tag_types tag_type,
>   lookup will stop when we hit a dependent base.  */
>if (!dependent_scope_p (context))
>  {
> -  bool want_type = (complain & tf_qualifying_scope);
> +  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
> +(as per [temp.res.general]/3), unless
> +  - the tag corresponds to a class-key or 'enum' so
> +[basic.lookup.elab] applies, or
> +  - the tag corresponds to scope_type or tf_qualifying_scope is
> +set so [basic.lookup.qual]/1 applies.
> +TODO: If we'd set/track the scope_type tag thoroughly on all
> +TYPENAME_TYPEs that are followed by :: then we wouldn't need the
> +tf_qualifying_scope flag.  */
> +  bool want_type = (tag_type != none_type && tag_type != typename_type)
> +   || (complain & tf_qualifying_scope);
>t = lookup_member (context, name, /*protect=*/2, want_type, complain);
>  }
>else
> diff --git a/gcc/cp/pt.cc 

Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-05 Thread Patrick Palka via Gcc-patches
On Wed, 5 Apr 2023, Patrick Palka wrote:

> r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
> non-types during the lookup, unless the TYPENAME_TYPE in question was
> followed by the :: scope resolution operator.  But there is another
> exception to this rule: we need to ignore non-types during the lookup
> also if the TYPENAME_TYPE was named with a tag other than 'typename',
> such as 'struct' or 'enum', as per [dcl.type.elab]/5.
> 
> This patch implements this additional exception.  It occurred to me that
> the tf_qualifying_scope flag is probably unnecessary if we'd use the
> scope_type tag more thoroughly, but that requires parser changes that
> are probably too risky at this stage.  (I'm working on addressing the
> FIXME/TODOs here for GCC 14.)
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
>   PR c++/109420
> 
> gcc/cp/ChangeLog:
> 
>   * decl.cc (make_typename_type): Also ignore non-types during
>   the lookup if tag_type is something other than none_type or
>   typename_type.
>   * pt.cc (tsubst) : Pass class_type or
>   enum_type as tag_type to make_typename_type as appropriate
>   instead of always passing typename_type.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/template/typename27.C: New test.
> ---
>  gcc/cp/decl.cc |  9 -
>  gcc/cp/pt.cc   |  9 -
>  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
>  3 files changed, 35 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> 
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 5369714f9b3..a0a20c5accc 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
> tag_types tag_type,
>   lookup will stop when we hit a dependent base.  */
>if (!dependent_scope_p (context))
>  {
> -  bool want_type = (complain & tf_qualifying_scope);
> +  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore non-types 
> if
> +  the tag corresponds to a class-key or 'enum' (or is scope_type), or if
> +  this typename is followed by :: as per [basic.lookup.qual.general]/1.
> +  TODO: If we'd set the scope_type tag accurately on all TYPENAME_TYPEs
> +  that are followed by :: then we wouldn't need the tf_qualifying_scope
> +  flag.  */
> +  bool want_type = (tag_type != none_type && tag_type != typename_type)
> + || (complain & tf_qualifying_scope);

Here's v2 which just slightly improves this comment.  I reckon 
[basic.lookup.elab]
is a better reference than [dcl.type.elab]/5 for justifying why the
lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.

-- >8 --

PR c++/109420

gcc/cp/ChangeLog:

* decl.cc (make_typename_type): Also ignore non-types during the
lookup if tag_type corresponds to an elaborated-type-specifier.
* pt.cc (tsubst) : Pass class_type or
enum_type as tag_type to make_typename_type as appropriate
instead of always passing typename_type.

gcc/testsuite/ChangeLog:

* g++.dg/template/typename27.C: New test.
---
 gcc/cp/decl.cc | 12 +++-
 gcc/cp/pt.cc   |  9 -
 gcc/testsuite/g++.dg/template/typename27.C | 19 +++
 3 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/typename27.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 5369714f9b3..772c059dc2c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
  lookup will stop when we hit a dependent base.  */
   if (!dependent_scope_p (context))
 {
-  bool want_type = (complain & tf_qualifying_scope);
+  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
+(as per [temp.res.general]/3), unless
+  - the tag corresponds to a class-key or 'enum' so
+[basic.lookup.elab] applies, or
+  - the tag corresponds to scope_type or tf_qualifying_scope is
+set so [basic.lookup.qual]/1 applies.
+TODO: If we'd set/track the scope_type tag thoroughly on all
+TYPENAME_TYPEs that are followed by :: then we wouldn't need the
+tf_qualifying_scope flag.  */
+  bool want_type = (tag_type != none_type && tag_type != typename_type)
+   || (complain & tf_qualifying_scope);
   t = lookup_member (context, name, /*protect=*/2, want_type, complain);
 }
   else
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 821e0035c08..09559c88f29 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16580,9 +16580,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
  return error_mark_node;
  }
 
+   /* FIXME: TYPENAME_IS_CLASS_P conflates 'union' vs 

Re: [PATCH] dse: Handle SUBREGs of word REGs differently for WORD_REGISTER_OPERATIONS targets [PR109040]

2023-04-05 Thread Jeff Law via Gcc-patches




On 4/5/23 10:48, Jakub Jelinek wrote:

On Wed, Apr 05, 2023 at 10:17:59AM -0600, Jeff Law wrote:

It is true that an instruction like
(insn 8 7 9 2 (set (reg:HI 141)
  (subreg:HI (reg:SI 142) 0)) "aauu.c":6:18 181 {*movhi_internal}
   (nil))
can appear in the IL on WORD_REGISTER_OPERATIONS target, but I think the
upper bits shouldn't be random garbage in that case, it should be zero
extended or sign extended.

Well, that's one of the core questions here.  What are the state of the
upper 16 bits of (reg:HI 141)?  The WORD_REGISTER_OPERATIONS docs aren't
100% clear as we're not really doing any operation.

So again, I think we need to decide if the DSE transformation is correct or
not.  I *think* we can aggree that insn 39 is OK.  It's really the semantics
of insn 47 that I think we need to agree on.  What is the state of the upper
16 bits of (reg:HI 175) after insn 47?


I'm afraid I don't know the answers here, I think Eric is
WORD_REGISTER_OPERATIONS expert here I think these days (most of the major
targets are !WORD_REGISTER_OPERATIONS).

Hopefully he'll chime in.


Intuitively, WORD_REGISTER_OPERATIONS from the description would be
that
(insn 47 35 39 2 (set (reg:HI 175)
 (subreg:HI (reg:SI 166) 0)) "pr109040.c":9:11 179 {*movhi_internal}
  (expr_list:REG_DEAD (reg:SI 166)
 (nil)))
would copy not just the low 16-bits of pseudo 166 to 175, but also the upper
16-bits.  

I've gone back and forth repeatedly on this.

Originally I didn't really see this as an operation.  But the more and 
more I ponder it feels like it's an operation and thus should be subject 
to WORD_REGISTER_OPERATIONS.


While it's not really binding on RTL semantics, if we look at how some 
architectures implement reg->reg copies, they're actually implemented 
with an ADD or IOR -- so a real operation under the hood.


If we accept a subreg copy as an operation and thus subject to 
WORD_REGISTER_OPERATIONS then that would seem to imply the combine is 
the real problem here.  Otherwise dse is the culprit.








But if that is so, then something is broken in the code below.

Some archeology shows that we were doing that on all arches initially
and then
Wed May 13 17:38:35 1998  Richard Kenner  

* combine.c (simplify_comparison, case AND): Don't commute AND
with SUBREG if constant is whole mode and don't do if lowpart
and not WORD_REGISTER_OPERATIONS.
restricted that to WORD_REGISTER_OPERATIONS only.
The whole optimization is then likely
Wed Mar 18 05:54:25 1998  Richard Kenner  

* combine.c (gen_binary): Don't make AND that does nothing.
(simplify_comparison, case AND): Commute AND and SUBREG.
* i386.h (CONST_CONSTS, case CONST_INT): One-byte integers are cost 0.
but the code has been tweaked further many times since then.
Sigh.  1998 and probably directly from Kenner's tree at the time.  So no 
public discussion, likely no testcases either.  Off to my private 
archives.  Yup, no discussion of Kenner's patch or testcase.


Interestingly enough I did stumble across Andreas Schwab reporting a bug 
in Kenner's change, though on the m68k and unrelated to 
WORD_REGISTER_OPERATIONS



jeff


[PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-05 Thread Patrick Palka via Gcc-patches
r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
non-types during the lookup, unless the TYPENAME_TYPE in question was
followed by the :: scope resolution operator.  But there is another
exception to this rule: we need to ignore non-types during the lookup
also if the TYPENAME_TYPE was named with a tag other than 'typename',
such as 'struct' or 'enum', as per [dcl.type.elab]/5.

This patch implements this additional exception.  It occurred to me that
the tf_qualifying_scope flag is probably unnecessary if we'd use the
scope_type tag more thoroughly, but that requires parser changes that
are probably too risky at this stage.  (I'm working on addressing the
FIXME/TODOs here for GCC 14.)

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

PR c++/109420

gcc/cp/ChangeLog:

* decl.cc (make_typename_type): Also ignore non-types during
the lookup if tag_type is something other than none_type or
typename_type.
* pt.cc (tsubst) : Pass class_type or
enum_type as tag_type to make_typename_type as appropriate
instead of always passing typename_type.

gcc/testsuite/ChangeLog:

* g++.dg/template/typename27.C: New test.
---
 gcc/cp/decl.cc |  9 -
 gcc/cp/pt.cc   |  9 -
 gcc/testsuite/g++.dg/template/typename27.C | 19 +++
 3 files changed, 35 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/typename27.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 5369714f9b3..a0a20c5accc 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
  lookup will stop when we hit a dependent base.  */
   if (!dependent_scope_p (context))
 {
-  bool want_type = (complain & tf_qualifying_scope);
+  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore non-types if
+the tag corresponds to a class-key or 'enum' (or is scope_type), or if
+this typename is followed by :: as per [basic.lookup.qual.general]/1.
+TODO: If we'd set the scope_type tag accurately on all TYPENAME_TYPEs
+that are followed by :: then we wouldn't need the tf_qualifying_scope
+flag.  */
+  bool want_type = (tag_type != none_type && tag_type != typename_type)
+   || (complain & tf_qualifying_scope);
   t = lookup_member (context, name, /*protect=*/2, want_type, complain);
 }
   else
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 821e0035c08..1e778e6e786 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16580,9 +16580,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
  return error_mark_node;
  }
 
+   /* FIXME: TYPENAME_IS_CLASS_P conflates 'union' vs 'struct' vs 'class'
+  tags.  TYPENAME_TYPE should probably remember the exact tag that
+  was used.  */
+   enum tag_types tag
+ = TYPENAME_IS_CLASS_P (t) ? class_type
+ : TYPENAME_IS_ENUM_P (t) ? enum_type
+ : typename_type;
tsubst_flags_t tcomplain = complain | tf_keep_type_decl;
tcomplain |= tst_ok_flag | qualifying_scope_flag;
-   f = make_typename_type (ctx, f, typename_type, tcomplain);
+   f = make_typename_type (ctx, f, tag, tcomplain);
if (f == error_mark_node)
  return f;
if (TREE_CODE (f) == TYPE_DECL)
diff --git a/gcc/testsuite/g++.dg/template/typename27.C 
b/gcc/testsuite/g++.dg/template/typename27.C
new file mode 100644
index 000..61b3efd998e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typename27.C
@@ -0,0 +1,19 @@
+// PR c++/109420
+
+struct A {
+  struct X { };
+  int X;
+};
+
+struct B {
+  enum E { };
+  enum F { E };
+};
+
+template
+void f() {
+  struct T::X x; // OK, lookup ignores the data member 'int A::X'
+  enum U::E e;   // OK, lookup ignores the enumerator 'B::F::E'
+}
+
+template void f();
-- 
2.40.0.153.g6369acd968



Ping: [PATCH, V3] PR target/105325, Make load/cmp fusion know about prefixed loads

2023-04-05 Thread Michael Meissner via Gcc-patches
Ping patch:

| Date: Mon, 27 Mar 2023 23:19:55 -0400
| From: Michael Meissner 
| Subject: [PATCH, V3] PR target/105325, Make load/cmp fusion know about 
prefixed loads
| Message-ID: 

-- 
Michael Meissner, IBM
PO Box 98, Ayer, Massachusetts, USA, 01432
email: meiss...@linux.ibm.com


Re: [PATCH] dse: Handle SUBREGs of word REGs differently for WORD_REGISTER_OPERATIONS targets [PR109040]

2023-04-05 Thread Jakub Jelinek via Gcc-patches
On Wed, Apr 05, 2023 at 10:17:59AM -0600, Jeff Law wrote:
> > It is true that an instruction like
> > (insn 8 7 9 2 (set (reg:HI 141)
> >  (subreg:HI (reg:SI 142) 0)) "aauu.c":6:18 181 {*movhi_internal}
> >   (nil))
> > can appear in the IL on WORD_REGISTER_OPERATIONS target, but I think the
> > upper bits shouldn't be random garbage in that case, it should be zero
> > extended or sign extended.
> Well, that's one of the core questions here.  What are the state of the
> upper 16 bits of (reg:HI 141)?  The WORD_REGISTER_OPERATIONS docs aren't
> 100% clear as we're not really doing any operation.
> 
> So again, I think we need to decide if the DSE transformation is correct or
> not.  I *think* we can aggree that insn 39 is OK.  It's really the semantics
> of insn 47 that I think we need to agree on.  What is the state of the upper
> 16 bits of (reg:HI 175) after insn 47?

I'm afraid I don't know the answers here, I think Eric is
WORD_REGISTER_OPERATIONS expert here I think these days (most of the major
targets are !WORD_REGISTER_OPERATIONS).
Intuitively, WORD_REGISTER_OPERATIONS from the description would be
that
(insn 47 35 39 2 (set (reg:HI 175)  

  
(subreg:HI (reg:SI 166) 0)) "pr109040.c":9:11 179 {*movhi_internal} 

  
 (expr_list:REG_DEAD (reg:SI 166)   

  
(nil))) 

  
would copy not just the low 16-bits of pseudo 166 to 175, but also the upper
16-bits.  But if that is so, then something is broken in the code below.
Some archeology shows that we were doing that on all arches initially
and then
Wed May 13 17:38:35 1998  Richard Kenner  

* combine.c (simplify_comparison, case AND): Don't commute AND
with SUBREG if constant is whole mode and don't do if lowpart
and not WORD_REGISTER_OPERATIONS.
restricted that to WORD_REGISTER_OPERATIONS only.
The whole optimization is then likely
Wed Mar 18 05:54:25 1998  Richard Kenner  

* combine.c (gen_binary): Don't make AND that does nothing.
(simplify_comparison, case AND): Commute AND and SUBREG.
* i386.h (CONST_CONSTS, case CONST_INT): One-byte integers are cost 0.
but the code has been tweaked further many times since then.

> > We substitute that
> > (leu:SI (and:SI (subreg:SI (reg:HI 175) 0)
> >  (const_int 2124 [0x84c]))
> >  (const_int 5 [0x5]))
> > but then trigger the WORD_REGISTER_OPERATIONS block in simplify_comparison:
> >/* If this is (and:M1 (subreg:M1 X:M2 0) (const_int C1)) where C1
> >   fits in both M1 and M2 and the SUBREG is either paradoxical
> >   or represents the low part, permute the SUBREG and the AND
> >   and try again.  */
> >if (GET_CODE (XEXP (op0, 0)) == SUBREG
> >&& CONST_INT_P (XEXP (op0, 1)))
> >  {
> >unsigned HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1));
> >/* Require an integral mode, to avoid creating something like
> >   (AND:SF ...).  */
> >if ((is_a 
> > (GET_MODE (SUBREG_REG (XEXP (op0, 0))), ))
> >/* It is unsafe to commute the AND into the SUBREG if the
> >   SUBREG is paradoxical and WORD_REGISTER_OPERATIONS is
> >   not defined.  As originally written the upper bits
> >   have a defined value due to the AND operation.
> >   However, if we commute the AND inside the SUBREG then
> >   they no longer have defined values and the meaning of
> >   the code has been changed.
> >   Also C1 should not change value in the smaller mode,
> >   see PR67028 (a positive C1 can become negative in the
> >   smaller mode, so that the AND does no longer mask the
> >   upper bits).  */
> >&& ((WORD_REGISTER_OPERATIONS
> > && mode_width > GET_MODE_PRECISION (tmode)
> > && mode_width <= BITS_PER_WORD
> > && trunc_int_for_mode (c1, tmode) == 
> > (HOST_WIDE_INT) c1)
> >|| (mode_width <= GET_MODE_PRECISION (tmode)
> >&& subreg_lowpart_p (XEXP (op0, 0
> >&& mode_width <= HOST_BITS_PER_WIDE_INT
> >&& HWI_COMPUTABLE_MODE_P (tmode)
> > 

Re: [PATCH] dse: Handle SUBREGs of word REGs differently for WORD_REGISTER_OPERATIONS targets [PR109040]

2023-04-05 Thread Jeff Law via Gcc-patches




On 4/5/23 08:51, Jakub Jelinek wrote:

On Wed, Apr 05, 2023 at 07:14:23AM -0600, Jeff Law wrote:

The following testcase is miscompiled on riscv since the addition
of *mvconst_internal define_insn_and_split.
I believe the bug is in DSE.  We have:
(insn 36 35 39 2 (set (mem/c:SI (plus:SI (reg/f:SI 65 frame)
  (const_int -64 [0xffc0])) [2  S4 A128])
  (reg:SI 166)) "pr109040.c":9:11 178 {*movsi_internal}
   (expr_list:REG_DEAD (reg:SI 166)
  (nil)))
(insn 39 36 40 2 (set (reg:SI 171)
  (zero_extend:SI (mem/c:HI (plus:SI (reg/f:SI 65 frame)
  (const_int -64 [0xffc0])) [0  S2 A128]))) 
"pr109040.c":9:11 111 {*zero_extendhisi2}
   (nil))
and RTL DSE's replace_read since r0-86337-g18b526e806ab6455 handles
even different modes like in the above case, and so it optimizes it into:
(insn 47 35 39 2 (set (reg:HI 175)
  (subreg:HI (reg:SI 166) 0)) "pr109040.c":9:11 179 {*movhi_internal}
   (expr_list:REG_DEAD (reg:SI 166)
  (nil)))
(insn 39 47 40 2 (set (reg:SI 171)
  (zero_extend:SI (reg:HI 175))) "pr109040.c":9:11 111 
{*zero_extendhisi2}
   (expr_list:REG_DEAD (reg:HI 175)
  (nil)))
Pseudo 166 is result of AND with 0x8084c constant (forced into a register).

Right.  But do we agree that the two above are equivalent?  If they are then
changing DSE just papers over the combine issue downstream.


It is true that an instruction like
(insn 8 7 9 2 (set (reg:HI 141)
 (subreg:HI (reg:SI 142) 0)) "aauu.c":6:18 181 {*movhi_internal}
  (nil))
can appear in the IL on WORD_REGISTER_OPERATIONS target, but I think the
upper bits shouldn't be random garbage in that case, it should be zero
extended or sign extended.
Well, that's one of the core questions here.  What are the state of the 
upper 16 bits of (reg:HI 141)?  The WORD_REGISTER_OPERATIONS docs aren't 
100% clear as we're not really doing any operation.


So again, I think we need to decide if the DSE transformation is correct 
or not.  I *think* we can aggree that insn 39 is OK.  It's really the 
semantics of insn 47 that I think we need to agree on.  What is the 
state of the upper 16 bits of (reg:HI 175) after insn 47?







What happens in combine is we enter combine.cc (simplify_set) with
(set (reg:HI 175)
 (subreg:HI (and:SI (reg:SI 167 [ m ])
 (reg:SI 168)) 0))
and there trigger the
   /* If we have (set x (subreg:m1 (op:m2 ...) 0)) with OP being some operation,
  and X being a REG or (subreg (reg)), we may be able to convert this to
  (set (subreg:m2 x) (op)).

  We can always do this if M1 is narrower than M2 because that means that
  we only care about the low bits of the result.

  However, on machines without WORD_REGISTER_OPERATIONS defined, we cannot
  perform a narrower operation than requested since the high-order bits will
  be undefined.  On machine where it is defined, this transformation is safe
  as long as M1 and M2 have the same number of words.  */
transformation into:
(set (subreg:SI (reg:HI 175) 0)
 (and:SI (reg:SI 167 [ m ])
 (reg:SI 168)))

I think we're OK a this point.



Though, it is !paradoxical_subreg_p (src) in that case, so it is done
regardless of WORD_REGISTER_OPERATIONS I think.

Then after that try_combine we do:
13325   record_value_for_reg (dest, record_dead_insn,
13326 WORD_REGISTER_OPERATIONS
13327 && word_register_operation_p (SET_SRC 
(setter))
13328 && paradoxical_subreg_p (SET_DEST 
(setter))
13329 ? SET_SRC (setter)
13330 : gen_lowpart (GET_MODE (dest),
13331SET_SRC (setter)));
and the 3 conditions are true here and so record value of the whole setter.
That then records among other things nonzero_bits as 0x8084c.

Next when trying to combine
(insn 39 47 40 2 (set (reg:SI 171)
 (zero_extend:SI (reg:HI 175))) "pr109040.c":10:11 111 
{*zero_extendhisi2}
  (expr_list:REG_DEAD (reg:HI 175)
 (nil)))
into
(insn 40 39 43 2 (set (reg:SI 172)
 (leu:SI (reg:SI 171)
 (const_int 5 [0x5]))) "pr109040.c":10:11 291 {*sleu_sisi}
  (expr_list:REG_DEAD (reg:SI 171)
 (nil)))
we i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0, 0);
and that correctly simplifies it into
(and:SI (subreg:SI (reg:HI 175) 0)
 (const_int 2124 [0x84c]))

Right.  Still seems sane at this point.



We substitute that
(leu:SI (and:SI (subreg:SI (reg:HI 175) 0)
 (const_int 2124 [0x84c]))
 (const_int 5 [0x5]))
but then trigger the WORD_REGISTER_OPERATIONS block in simplify_comparison:
   /* If this is (and:M1 (subreg:M1 X:M2 0) (const_int C1)) where C1
  fits in both M1 and M2 and the SUBREG is either paradoxical
  or represents the low part, permute the SUBREG 

[committed] hppa: Fix 22_locale/locale/cons/12658_thread-2.cc on hppa

2023-04-05 Thread John David Anglin
Committed to trunk.

Dave
---

Fix 22_locale/locale/cons/12658_thread-2.cc on hppa.

2023-04-05  John David Anglin  

libstdc++-v3/ChangeLog:

* testsuite/22_locale/locale/cons/12658_thread-2.cc: Double
timeout factor on hppa*-*-*.

diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc 
b/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc
index 1ce85b7475d..d198a0ac304 100644
--- a/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/12658_thread-2.cc
@@ -3,6 +3,7 @@
 // { dg-require-effective-target pthread }
 // { dg-require-namedlocale "en_US.ISO8859-1" }
 // { dg-require-namedlocale "fr_FR.ISO8859-15" }
+// { dg-timeout-factor 2.0 { target hppa*-*-* } }
 
 // Copyright (C) 2004-2023 Free Software Foundation, Inc.
 //



signature.asc
Description: PGP signature


Re: [RFA][Bug target/108892 ][13 regression] Force re-recognition after changing RTL structure of an insn

2023-04-05 Thread Jeff Law




On 4/5/23 08:21, Segher Boessenkool wrote:

Hi!

On Wed, Mar 29, 2023 at 07:48:00AM -0600, Jeff Law wrote:

So as mentioned in the PR the underlying issue here is combine changes
the form of an existing insn, but fails to force re-recognition.  As a
result other parts of the compiler blow up.


[snip]


The fix is trivial, reset the INSN_CODE to force re-recognition in the
case where try_combine fails.


Thanks for the clear explanation!  Okay for trunk.  Also okay for all
backports (after a week or so on trunk).
Thanks.  I haven't seen this on any of the release branches, so no 
strong opinions on backporting at this time.  It's a pretty narrow bug 
(no surprise given its been latent for something like 10 years).





* combine.cc (combine_instructions): Force re-recognition when
potentially changing the underlying RTL structure of an insn.


When returning the original, might be clearer?

Yea.  I'll update the ChangeLog entry.

Thanks,
Jeff



[committed] hppa: Add assember CFI directives to millicode division and remainder routines

2023-04-05 Thread John David Anglin
Committed to trunk after testing on hppa-unknown-linux-gnu.

Dave
---

Add assember CFI directives to millicode division and remainder routines.

The millicode division and remainder routines trap division by zero.
The unwinder needs these directives to unwind divide by zero traps.

2023-04-05  John David Anglin  

libgcc/ChangeLog:

PR target/109374
* config/pa/milli64.S (RETURN_COLUMN): Define.
($$divI): Add CFI directives.
($$divU): Likewise.
($$remI): Likewise.
($$remU): Likewise.

diff --git a/libgcc/config/pa/milli64.S b/libgcc/config/pa/milli64.S
index 2316f797354..e1c84f48d25 100644
--- a/libgcc/config/pa/milli64.S
+++ b/libgcc/config/pa/milli64.S
@@ -105,8 +105,10 @@ sar:   .reg%cr11   /* Shift Amount Register */
 rp:.regr2  /* return pointer */
 #ifdef pa64
 mrp:   .regr2  /* millicode return pointer */
+#define RETURN_COLUMN  2
 #else
 mrp:   .regr31 /* millicode return pointer */
+#define RETURN_COLUMN  31
 #endif
 ret0:  .regr28 /* return value */
 ret1:  .regr29 /* return value (high part of double) */
@@ -313,6 +315,8 @@ RDEFINE(temp1,arg0)
.import $$divI_15,millicode
.export $$divI,millicode
.export $$divoI,millicode
+   .cfi_startproc
+   .cfi_return_column RETURN_COLUMN
.proc
.callinfo   millicode
.entry
@@ -484,6 +488,7 @@ LSYM(negative1)
addoarg0,arg1,r0/*  trap iff dividend==0x8000 && 
divisor==-1 */
.exit
.procend
+   .cfi_endproc
.end
 #endif
 
@@ -543,6 +548,8 @@ RDEFINE(temp1,arg0)
.import $$divU_12,millicode
.import $$divU_14,millicode
.import $$divU_15,millicode
+   .cfi_startproc
+   .cfi_return_column RETURN_COLUMN
.proc
.callinfo   millicode
.entry
@@ -706,6 +713,7 @@ LSYM(big_divisor)
addcr0,r0,retreg
.exit
.procend
+   .cfi_endproc
.end
 #endif
 
@@ -750,6 +758,8 @@ RDEFINE(retreg,ret1)
 
SUBSPA_MILLI
ATTR_MILLI
+   .cfi_startproc
+   .cfi_return_column RETURN_COLUMN
.proc
.callinfo millicode
.entry
@@ -875,6 +885,7 @@ LSYM(finish)
nop
.exit
.procend
+   .cfi_endproc
 #ifdef milliext
.origin 0x0200
 #endif
@@ -922,6 +933,8 @@ RDEFINE(rmndr,ret1) /*  r29 */
SUBSPA_MILLI
ATTR_MILLI
.export $$remU,millicode
+   .cfi_startproc
+   .cfi_return_column RETURN_COLUMN
.proc
.callinfo   millicode
.entry
@@ -1013,6 +1026,7 @@ LSYM(special_case)
nop
.exit
.procend
+   .cfi_endproc
.end
 #endif
 


signature.asc
Description: PGP signature


Re: [PATCH] dse: Handle SUBREGs of word REGs differently for WORD_REGISTER_OPERATIONS targets [PR109040]

2023-04-05 Thread Jakub Jelinek via Gcc-patches
On Wed, Apr 05, 2023 at 07:14:23AM -0600, Jeff Law wrote:
> > The following testcase is miscompiled on riscv since the addition
> > of *mvconst_internal define_insn_and_split.
> > I believe the bug is in DSE.  We have:
> > (insn 36 35 39 2 (set (mem/c:SI (plus:SI (reg/f:SI 65 frame)
> >  (const_int -64 [0xffc0])) [2  S4 A128])
> >  (reg:SI 166)) "pr109040.c":9:11 178 {*movsi_internal}
> >   (expr_list:REG_DEAD (reg:SI 166)
> >  (nil)))
> > (insn 39 36 40 2 (set (reg:SI 171)
> >  (zero_extend:SI (mem/c:HI (plus:SI (reg/f:SI 65 frame)
> >  (const_int -64 [0xffc0])) [0  S2 A128]))) 
> > "pr109040.c":9:11 111 {*zero_extendhisi2}
> >   (nil))
> > and RTL DSE's replace_read since r0-86337-g18b526e806ab6455 handles
> > even different modes like in the above case, and so it optimizes it into:
> > (insn 47 35 39 2 (set (reg:HI 175)
> >  (subreg:HI (reg:SI 166) 0)) "pr109040.c":9:11 179 {*movhi_internal}
> >   (expr_list:REG_DEAD (reg:SI 166)
> >  (nil)))
> > (insn 39 47 40 2 (set (reg:SI 171)
> >  (zero_extend:SI (reg:HI 175))) "pr109040.c":9:11 111 
> > {*zero_extendhisi2}
> >   (expr_list:REG_DEAD (reg:HI 175)
> >  (nil)))
> > Pseudo 166 is result of AND with 0x8084c constant (forced into a register).
> Right.  But do we agree that the two above are equivalent?  If they are then
> changing DSE just papers over the combine issue downstream.

It is true that an instruction like
(insn 8 7 9 2 (set (reg:HI 141)
(subreg:HI (reg:SI 142) 0)) "aauu.c":6:18 181 {*movhi_internal}
 (nil))
can appear in the IL on WORD_REGISTER_OPERATIONS target, but I think the
upper bits shouldn't be random garbage in that case, it should be zero
extended or sign extended.

What happens in combine is we enter combine.cc (simplify_set) with
(set (reg:HI 175)
(subreg:HI (and:SI (reg:SI 167 [ m ])
(reg:SI 168)) 0))
and there trigger the
  /* If we have (set x (subreg:m1 (op:m2 ...) 0)) with OP being some operation,
 and X being a REG or (subreg (reg)), we may be able to convert this to
 (set (subreg:m2 x) (op)).

 We can always do this if M1 is narrower than M2 because that means that
 we only care about the low bits of the result.

 However, on machines without WORD_REGISTER_OPERATIONS defined, we cannot
 perform a narrower operation than requested since the high-order bits will
 be undefined.  On machine where it is defined, this transformation is safe
 as long as M1 and M2 have the same number of words.  */
transformation into:
(set (subreg:SI (reg:HI 175) 0)
(and:SI (reg:SI 167 [ m ])
(reg:SI 168)))
Though, it is !paradoxical_subreg_p (src) in that case, so it is done
regardless of WORD_REGISTER_OPERATIONS I think.

Then after that try_combine we do:
13325   record_value_for_reg (dest, record_dead_insn,
13326 WORD_REGISTER_OPERATIONS
13327 && word_register_operation_p (SET_SRC 
(setter))
13328 && paradoxical_subreg_p (SET_DEST 
(setter))
13329 ? SET_SRC (setter)
13330 : gen_lowpart (GET_MODE (dest),
13331SET_SRC (setter)));
and the 3 conditions are true here and so record value of the whole setter.
That then records among other things nonzero_bits as 0x8084c.

Next when trying to combine
(insn 39 47 40 2 (set (reg:SI 171)
(zero_extend:SI (reg:HI 175))) "pr109040.c":10:11 111 
{*zero_extendhisi2}
 (expr_list:REG_DEAD (reg:HI 175)
(nil)))
into
(insn 40 39 43 2 (set (reg:SI 172)
(leu:SI (reg:SI 171)
(const_int 5 [0x5]))) "pr109040.c":10:11 291 {*sleu_sisi}
 (expr_list:REG_DEAD (reg:SI 171)
(nil)))
we i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0, 0);
and that correctly simplifies it into
(and:SI (subreg:SI (reg:HI 175) 0)
(const_int 2124 [0x84c]))
We substitute that
(leu:SI (and:SI (subreg:SI (reg:HI 175) 0)
(const_int 2124 [0x84c]))
(const_int 5 [0x5]))
but then trigger the WORD_REGISTER_OPERATIONS block in simplify_comparison:
  /* If this is (and:M1 (subreg:M1 X:M2 0) (const_int C1)) where C1
 fits in both M1 and M2 and the SUBREG is either paradoxical
 or represents the low part, permute the SUBREG and the AND
 and try again.  */
  if (GET_CODE (XEXP (op0, 0)) == SUBREG
  && CONST_INT_P (XEXP (op0, 1)))
{
  unsigned HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1));
  /* Require an integral mode, to avoid creating something like
 (AND:SF ...).  */
  if ((is_a 
   (GET_MODE (SUBREG_REG (XEXP (op0, 0))), ))
  /* It is unsafe to commute the AND into the SUBREG if the
 SUBREG is paradoxical and 

Re: [RFA][Bug target/108892 ][13 regression] Force re-recognition after changing RTL structure of an insn

2023-04-05 Thread Segher Boessenkool
Hi!

On Wed, Mar 29, 2023 at 07:48:00AM -0600, Jeff Law wrote:
> So as mentioned in the PR the underlying issue here is combine changes 
> the form of an existing insn, but fails to force re-recognition.  As a 
> result other parts of the compiler blow up.

[snip]

> The fix is trivial, reset the INSN_CODE to force re-recognition in the 
> case where try_combine fails.

Thanks for the clear explanation!  Okay for trunk.  Also okay for all
backports (after a week or so on trunk).

>   * combine.cc (combine_instructions): Force re-recognition when
>   potentially changing the underlying RTL structure of an insn.

When returning the original, might be clearer?

Thanks,


Segher


[committed 86/88] gccrs: Added AST Node AST::InlineAsm

2023-04-05 Thread arthur . cohen
From: M V V S Manoj Kumar 

Addresses #1567
Created a AST node InlineAsm similar to the one found in rustc.
As there is no Symbol struct/class in gccrs I have made every instance
of Symbol a string.

gcc/rust/ChangeLog:

* ast/rust-ast-full-decls.h (class InlineAsm):Added class declaration.
* ast/rust-expr.h (class InlineAsm):Added class definition.

Signed-off-by: M V V S Manoj Kumar 
---
 gcc/rust/ast/rust-ast-full-decls.h |   1 +
 gcc/rust/ast/rust-expr.h   | 138 +
 2 files changed, 139 insertions(+)

diff --git a/gcc/rust/ast/rust-ast-full-decls.h 
b/gcc/rust/ast/rust-ast-full-decls.h
index 9d7b00ac5a2..64341d32641 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -149,6 +149,7 @@ struct MatchCase;
 class MatchExpr;
 class AwaitExpr;
 class AsyncBlockExpr;
+class InlineAsm;
 
 // rust-stmt.h
 class EmptyStmt;
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 3ed1885d5af..f5461848009 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -4634,6 +4634,144 @@ protected:
 return new AsyncBlockExpr (*this);
   }
 };
+
+// Inline Assembly Node
+class InlineAsm : public ExprWithoutBlock
+{
+  // Inline-assembly specific options
+  enum InlineAsmOptions
+  {
+PURE = 1 << 0,
+NOMEM = 1 << 1,
+READONLY = 1 << 2,
+PRESERVES_FLAGS = 1 << 3,
+NORETURN = 1 << 4,
+NOSTACK = 1 << 5,
+ATT_SYNTAX = 1 << 6,
+RAW = 1 << 7,
+MAY_UNWIND = 1 << 8,
+  };
+
+  struct AnonConst
+  {
+NodeId id;
+std::unique_ptr value;
+  };
+
+  struct InlineAsmRegOrRegClass
+  {
+enum Type
+{
+  Reg,
+  RegClass,
+};
+
+struct Reg
+{
+  std::string Symbol;
+};
+
+struct RegClass
+{
+  std::string Symbol;
+};
+
+Identifier name;
+Location locus;
+  };
+
+  struct InlineAsmOperand
+  {
+enum RegisterType
+{
+  In,
+  Out,
+  InOut,
+  SplitInOut,
+  Const,
+  Sym,
+};
+
+struct In
+{
+  InlineAsmRegOrRegClass reg;
+  std::unique_ptr expr;
+};
+
+struct Out
+{
+  InlineAsmRegOrRegClass reg;
+  bool late;
+  std::unique_ptr expr; // can be null
+};
+
+struct InOut
+{
+  InlineAsmRegOrRegClass reg;
+  bool late;
+  std::unique_ptr expr; // this can't be null
+};
+
+struct SplitInOut
+{
+  InlineAsmRegOrRegClass reg;
+  bool late;
+  std::unique_ptr in_expr;
+  std::unique_ptr out_expr; // could be null
+};
+
+struct Const
+{
+  AnonConst anon_const;
+};
+
+struct Sym
+{
+  std::unique_ptr sym;
+};
+Location locus;
+  };
+
+  struct InlineAsmPlaceHolder
+  {
+size_t operand_idx;
+char modifier; // can be null
+Location locus;
+  };
+
+  struct InlineAsmTemplatePiece
+  {
+bool is_placeholder;
+union
+{
+  std::string string;
+  InlineAsmPlaceHolder placeholder;
+};
+  };
+
+  struct TupleClobber
+  {
+// as gccrs still doesen't contain a symbol class I have put them as 
strings
+std::string symbol;
+Location loc;
+  };
+
+  struct TupleTemplateStr
+  {
+// as gccrs still doesen't contain a symbol class I have put them as 
strings
+std::string symbol;
+std::string optional_symbol;
+Location loc;
+  };
+
+public:
+  std::vector template_;
+  std::vector template_strs;
+  std::vector operands;
+  TupleClobber clobber_abi;
+  InlineAsmOptions options;
+  std::vector line_spans;
+};
 } // namespace AST
 } // namespace Rust
 
-- 
2.40.0



[committed 88/88] gccrs: Fix issue with parsing unsafe block expression statements

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h
(Parser::parse_stmt): Handle unsafe expression statements.

gcc/testsuite/ChangeLog:

* rust/compile/issue-1422.rs: New test.

Signed-off-by: Owen Avery 
---
 gcc/rust/parse/rust-parse-impl.h | 10 +-
 gcc/testsuite/rust/compile/issue-1422.rs |  7 +++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-1422.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 1e5b2dc85ed..db32803ddbe 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6131,7 +6131,15 @@ Parser::parse_stmt 
(ParseRestrictions restrictions)
   /* if any of these (should be all possible VisItem prefixes), parse a
* VisItem can't parse item because would require reparsing outer
* attributes */
-  return parse_vis_item (std::move (outer_attrs));
+  // may also be unsafe block
+  if (lexer.peek_token (1)->get_id () == LEFT_CURLY)
+   {
+ return parse_expr_stmt (std::move (outer_attrs), restrictions);
+   }
+  else
+   {
+ return parse_vis_item (std::move (outer_attrs));
+   }
   break;
 case SUPER:
 case SELF:
diff --git a/gcc/testsuite/rust/compile/issue-1422.rs 
b/gcc/testsuite/rust/compile/issue-1422.rs
new file mode 100644
index 000..b178cda185e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1422.rs
@@ -0,0 +1,7 @@
+macro_rules! test {
+() => { unsafe {} };
+}
+
+fn main() {
+test!();
+}
-- 
2.40.0



[committed 83/88] gccrs: add test case to show our query-type system is working

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Fixes #1361

Signed-off-by: Philip Herron 

gcc/testsuite/ChangeLog:

* rust/compile/issue-1361.rs: New test.
---
 gcc/testsuite/rust/compile/issue-1361.rs | 8 
 1 file changed, 8 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-1361.rs

diff --git a/gcc/testsuite/rust/compile/issue-1361.rs 
b/gcc/testsuite/rust/compile/issue-1361.rs
new file mode 100644
index 000..f8909727216
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1361.rs
@@ -0,0 +1,8 @@
+// { dg-options "-w" }
+fn foo() -> S {
+S { a: 15 }
+}
+
+struct S {
+a: i32,
+}
-- 
2.40.0



[committed 87/88] gccrs: Address unsafe with/without block handling ambiguity

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h
(Parser::parse_expr_stmt): Remove hypothetical unsafe + 
expr_stmt_without_block handling.

Signed-off-by: Owen Avery 
---
 gcc/rust/parse/rust-parse-impl.h | 15 +++
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 6a98bcce654..1e5b2dc85ed 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7188,18 +7188,9 @@ Parser::parse_expr_stmt 
(AST::AttrVec outer_attrs,
  }
   }
   case UNSAFE: {
-   /* FIXME: are there any expressions without blocks that can have
-* unsafe as their first token? Or is unsafe the only one? */
-   // safe side for now
-   if (lexer.peek_token (1)->get_id () == LEFT_CURLY)
- {
-   return parse_expr_stmt_with_block (std::move (outer_attrs));
- }
-   else
- {
-   return parse_expr_stmt_without_block (std::move (outer_attrs),
- restrictions);
- }
+   // unsafe block
+   // https://doc.rust-lang.org/reference/unsafe-keyword.html
+   return parse_expr_stmt_with_block (std::move (outer_attrs));
   }
 default:
   // not a parse expr with block, so must be expr without block
-- 
2.40.0



[committed 75/88] gccrs: Support for Sized builtin marker trait

2023-04-05 Thread arthur . cohen
From: Philip Herron 

When implementing general bounds checking as part of unify calls, we did
not check associated types on bounds which lead to alot of missed error
checking. This now recursively checks the bounds and the associated types
with a decent error message. This also required us to implement the Sized
marker trait to keep existing test-cases happy.

Fixes #1725

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-reference.cc 
(TraitReference::clear_associated_types): make const
(TraitReference::clear_associated_type_projections): new interface
* typecheck/rust-hir-trait-reference.h:
* typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): 
refactor
(TraitItemReference::associated_type_reset): reset projections
* typecheck/rust-hir-type-bounds.h:
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): fix 
bounds
* typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::TypeBoundsProbe): 
refactor into cc file
(TypeBoundsProbe::Probe): refactor
(TypeBoundsProbe::is_bound_satisfied_for_type): likewise
(TypeBoundsProbe::assemble_sized_builtin): add builtin for Sized
(TypeCheckBase::get_predicate_from_bound): refactor
(TypeBoundPredicate::lookup_associated_type): refactor
* typecheck/rust-tyty-subst.cc (SubstitutionRef::lookup_associated_impl)
(SubstitutionRef::prepare_higher_ranked_bounds): new interface to clear 
hanging bounds
(SubstitutionRef::monomorphize): refactor
* typecheck/rust-tyty-subst.h:
* typecheck/rust-tyty.cc (BaseType::get_locus): helper
(BaseType::satisfies_bound): ensure bounds are satisfied and assoicated 
types
(ParamType::ParamType): new field in constructor
(ParamType::clone): update clone
(ParamType::set_implicit_self_trait): new interface
(ParamType::is_implicit_self_trait): likewise
* typecheck/rust-tyty.h: cleanup
* util/rust-hir-map.cc (Mappings::Mappings): builtin marker
(Mappings::~Mappings): delete marker
(Mappings::lookup_builtin_marker): lookup
* util/rust-hir-map.h: update header

gcc/testsuite/ChangeLog:

* rust/compile/issue-1725-1.rs: New test.
* rust/compile/issue-1725-2.rs: New test.
---
 .../typecheck/rust-hir-trait-reference.cc |  18 +-
 gcc/rust/typecheck/rust-hir-trait-reference.h |   6 +-
 gcc/rust/typecheck/rust-hir-trait-resolve.cc  |  27 +-
 gcc/rust/typecheck/rust-hir-type-bounds.h |  34 +-
 .../typecheck/rust-hir-type-check-expr.cc |   6 +
 gcc/rust/typecheck/rust-tyty-bounds.cc| 111 ++-
 gcc/rust/typecheck/rust-tyty-subst.cc | 291 ++
 gcc/rust/typecheck/rust-tyty-subst.h  |  12 +-
 gcc/rust/typecheck/rust-tyty.cc   |  82 -
 gcc/rust/typecheck/rust-tyty.h|   8 +-
 gcc/rust/util/rust-hir-map.cc |  17 +-
 gcc/rust/util/rust-hir-map.h  |   3 +
 gcc/testsuite/rust/compile/issue-1725-1.rs|  19 ++
 gcc/testsuite/rust/compile/issue-1725-2.rs|  28 ++
 14 files changed, 476 insertions(+), 186 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-1725-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1725-2.rs

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc 
b/gcc/rust/typecheck/rust-hir-trait-reference.cc
index 8574988fb0b..a1229adc06c 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -343,14 +343,26 @@ TraitReference::on_resolved ()
 }
 
 void
-TraitReference::clear_associated_types ()
+TraitReference::clear_associated_types () const
 {
-  for (auto  : item_refs)
+  for (const auto  : item_refs)
+{
+  bool is_assoc_type = item.get_trait_item_type ()
+  == TraitItemReference::TraitItemType::TYPE;
+  if (is_assoc_type)
+   item.associated_type_reset (false);
+}
+}
+
+void
+TraitReference::clear_associated_type_projections () const
+{
+  for (const auto  : item_refs)
 {
   bool is_assoc_type = item.get_trait_item_type ()
   == TraitItemReference::TraitItemType::TYPE;
   if (is_assoc_type)
-   item.associated_type_reset ();
+   item.associated_type_reset (true);
 }
 }
 
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h 
b/gcc/rust/typecheck/rust-hir-trait-reference.h
index f3703efcced..d20b2952e5b 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -106,7 +106,7 @@ public:
 
   void associated_type_set (TyTy::BaseType *ty) const;
 
-  void associated_type_reset () const;
+  void associated_type_reset (bool only_projections) const;
 
   bool is_object_safe () const;
 
@@ -212,7 +212,9 @@ public:
 
   void on_resolved ();
 
-  void clear_associated_types ();
+  void clear_associated_types () const;
+
+  

[committed 82/88] gccrs: rename rust-hir-full-tests.cc

2023-04-05 Thread arthur . cohen
From: SainiAditya1 

gcc/rust/Changelog:

* hir/tree/rust-hir-full-test.cc: Moved to...
* hir/tree/rust-hir.cc: ...here.
* Make-lang.in: Rename rust-hir-full-test.

Signed-off-by: SainiAditya1 
---
 gcc/rust/Make-lang.in| 2 +-
 gcc/rust/hir/tree/{rust-hir-full-test.cc => rust-hir.cc} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename gcc/rust/hir/tree/{rust-hir-full-test.cc => rust-hir.cc} (100%)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 06f64a01dce..3ed0c09e0e7 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -86,7 +86,7 @@ GRS_OBJS = \
 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.o \
 rust/rust-hir-map.o \
 rust/rust-attributes.o \
 rust/rust-abi.o \
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc 
b/gcc/rust/hir/tree/rust-hir.cc
similarity index 100%
rename from gcc/rust/hir/tree/rust-hir-full-test.cc
rename to gcc/rust/hir/tree/rust-hir.cc
-- 
2.40.0



[committed 85/88] gccrs: diagnostic: Refactor Error class

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

The class now allows for more variants including a `Hint` one which
then gets emitted by calling `rust_inform`. This allows us to display
hints/tips/notes in backtracking contexts such as the parser.

gcc/rust/ChangeLog:

* rust-diagnostics.h (struct Error): Add new Kind enum and various new
static constructors to allow for hints as well.
* rust-diagnostics.cc (Error::Error): Use new `kind` field properly.
* checks/errors/privacy/rust-visibility-resolver.cc
(VisibilityResolver::resolve_module_path): Use new Error API.
* expand/rust-macro-builtins.cc (MacroBuiltin::include_handler): 
Likewise.
* expand/rust-macro-expand.cc (parse_many): Likewise.
(transcribe_type): Likewise.
* parse/rust-parse-impl.h (Parser::parse_crate): Likewise.
* rust-session-manager.cc (Session::handle_crate_name): Likewise.
* ast/rust-ast.cc (Module::load_items): Likewise.
---
 gcc/rust/ast/rust-ast.cc  |  2 +-
 .../privacy/rust-visibility-resolver.cc   |  4 +-
 gcc/rust/expand/rust-macro-builtins.cc|  2 +-
 gcc/rust/expand/rust-macro-expand.cc  |  4 +-
 gcc/rust/parse/rust-parse-impl.h  |  2 +-
 gcc/rust/rust-diagnostics.cc  | 43 --
 gcc/rust/rust-diagnostics.h   | 56 ---
 gcc/rust/rust-session-manager.cc  |  6 +-
 8 files changed, 98 insertions(+), 21 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 07983b7da06..68a7dfdc662 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -4084,7 +4084,7 @@ Module::load_items ()
   inner_attrs = parser.parse_inner_attributes ();
   auto parsed_items = parser.parse_items ();
   for (const auto  : parser.get_errors ())
-error.emit_error ();
+error.emit ();
 
   items = std::move (parsed_items);
   kind = ModuleKind::LOADED;
diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc 
b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
index becb9fd93a7..30afaf9174e 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
@@ -63,7 +63,7 @@ VisibilityResolver::resolve_module_path (const 
HIR::SimplePath ,
   NodeId ref_node_id = UNKNOWN_NODEID;
   if (!resolver.lookup_resolved_name (ast_node_id, _node_id))
 {
-  invalid_path.emit_error ();
+  invalid_path.emit ();
   return false;
 }
   // FIXME: Add a hint here if we can find the path in another scope, such as
@@ -77,7 +77,7 @@ VisibilityResolver::resolve_module_path (const 
HIR::SimplePath ,
   auto module = mappings.lookup_module (ref);
   if (!module)
 {
-  invalid_path.emit_error ();
+  invalid_path.emit ();
   return false;
 }
 
diff --git a/gcc/rust/expand/rust-macro-builtins.cc 
b/gcc/rust/expand/rust-macro-builtins.cc
index 97594921dec..cf90b384cb5 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -736,7 +736,7 @@ MacroBuiltin::include_handler (Location invoc_locus, 
AST::MacroInvocData )
   bool has_error = !parser.get_errors ().empty ();
 
   for (const auto  : parser.get_errors ())
-error.emit_error ();
+error.emit ();
 
   if (has_error)
 {
diff --git a/gcc/rust/expand/rust-macro-expand.cc 
b/gcc/rust/expand/rust-macro-expand.cc
index 4b494490424..71aafef85b0 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -848,7 +848,7 @@ parse_many (Parser , TokenId 
,
   if (node.is_error ())
{
  for (auto err : parser.get_errors ())
-   err.emit_error ();
+   err.emit ();
 
  return AST::Fragment::create_error ();
}
@@ -991,7 +991,7 @@ transcribe_type (Parser )
 
   auto type = parser.parse_type (true);
   for (auto err : parser.get_errors ())
-err.emit_error ();
+err.emit ();
 
   auto end = lexer.get_offs ();
 
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index cc5436cff63..6a98bcce654 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -444,7 +444,7 @@ Parser::parse_crate ()
 
   // emit all errors
   for (const auto  : error_table)
-error.emit_error ();
+error.emit ();
 
   return std::unique_ptr (
 new AST::Crate (std::move (items), std::move (inner_attrs)));
diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc
index c0f02c2831e..4e5c2ececd4 100644
--- a/gcc/rust/rust-diagnostics.cc
+++ b/gcc/rust/rust-diagnostics.cc
@@ -231,14 +231,49 @@ rust_debug_loc (const Location location, const char *fmt, 
...)
 }
 
 namespace Rust {
-Error::Error (const Location location, const char *fmt, ...) : locus (location)
+
+/**
+ * This function takes ownership of `args` and calls `va_end` on it
+ */
+static Error
+va_constructor (Error::Kind kind, Location 

[committed 79/88] gccrs: Fix formatting

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* ast/rust-pattern.h: Fix formatting.

Signed-off-by: Owen Avery 
---
 gcc/rust/ast/rust-pattern.h | 70 ++---
 1 file changed, 34 insertions(+), 36 deletions(-)

diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index cf5d2ead10d..0e2f56e3216 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -763,7 +763,7 @@ struct StructPatternElements
 {
 private:
   // bool has_struct_pattern_fields;
-  std::vector > fields;
+  std::vector> fields;
 
   bool has_struct_pattern_etc;
   std::vector struct_pattern_etc_attrs;
@@ -788,7 +788,7 @@ public:
 
   // Constructor for StructPatternElements with both (potentially)
   StructPatternElements (
-std::vector > fields,
+std::vector> fields,
 std::vector etc_attrs)
 : fields (std::move (fields)), has_struct_pattern_etc (true),
   struct_pattern_etc_attrs (std::move (etc_attrs))
@@ -796,7 +796,7 @@ public:
 
   // Constructor for StructPatternElements with no StructPatternEtc
   StructPatternElements (
-std::vector > fields)
+std::vector> fields)
 : fields (std::move (fields)), has_struct_pattern_etc (false),
   struct_pattern_etc_attrs ()
   {}
@@ -832,18 +832,17 @@ public:
   static StructPatternElements create_empty ()
   {
 return StructPatternElements (
-  std::vector > ());
+  std::vector> ());
   }
 
   std::string as_string () const;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector > &
-  get_struct_pattern_fields ()
+  std::vector> _struct_pattern_fields 
()
   {
 return fields;
   }
-  const std::vector > &
+  const std::vector> &
   get_struct_pattern_fields () const
   {
 return fields;
@@ -956,10 +955,10 @@ protected:
 // Class for non-ranged tuple struct pattern patterns
 class TupleStructItemsNoRange : public TupleStructItems
 {
-  std::vector > patterns;
+  std::vector> patterns;
 
 public:
-  TupleStructItemsNoRange (std::vector > patterns)
+  TupleStructItemsNoRange (std::vector> patterns)
 : patterns (std::move (patterns))
   {}
 
@@ -991,8 +990,8 @@ public:
   void accept_vis (ASTVisitor ) override;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector > _patterns () { return patterns; }
-  const std::vector > _patterns () const
+  std::vector> _patterns () { return patterns; }
+  const std::vector> _patterns () const
   {
 return patterns;
   }
@@ -1011,12 +1010,12 @@ protected:
 // Class for ranged tuple struct pattern patterns
 class TupleStructItemsRange : public TupleStructItems
 {
-  std::vector > lower_patterns;
-  std::vector > upper_patterns;
+  std::vector> lower_patterns;
+  std::vector> upper_patterns;
 
 public:
-  TupleStructItemsRange (std::vector > lower_patterns,
-std::vector > upper_patterns)
+  TupleStructItemsRange (std::vector> lower_patterns,
+std::vector> upper_patterns)
 : lower_patterns (std::move (lower_patterns)),
   upper_patterns (std::move (upper_patterns))
   {}
@@ -1056,21 +1055,21 @@ public:
   void accept_vis (ASTVisitor ) override;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector > _lower_patterns ()
+  std::vector> _lower_patterns ()
   {
 return lower_patterns;
   }
-  const std::vector > _lower_patterns () const
+  const std::vector> _lower_patterns () const
   {
 return lower_patterns;
   }
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector > _upper_patterns ()
+  std::vector> _upper_patterns ()
   {
 return upper_patterns;
   }
-  const std::vector > _upper_patterns () const
+  const std::vector> _upper_patterns () const
   {
 return upper_patterns;
   }
@@ -1233,10 +1232,10 @@ TuplePatternItemsSingle(*this);
 // Class representing TuplePattern patterns where there are multiple patterns
 class TuplePatternItemsMultiple : public TuplePatternItems
 {
-  std::vector > patterns;
+  std::vector> patterns;
 
 public:
-  TuplePatternItemsMultiple (std::vector > patterns)
+  TuplePatternItemsMultiple (std::vector> patterns)
 : patterns (std::move (patterns))
   {}
 
@@ -1268,8 +1267,8 @@ public:
   void accept_vis (ASTVisitor ) override;
 
   // TODO: seems kinda dodgy. Think of better way.
-  std::vector > _patterns () { return patterns; }
-  const std::vector > _patterns () const
+  std::vector> _patterns () { return patterns; }
+  const std::vector> _patterns () const
   {
 return patterns;
   }
@@ -1291,13 +1290,12 @@ protected:
 // Class representing TuplePattern patterns where there are a range of patterns
 class TuplePatternItemsRanged : public TuplePatternItems
 {
-  std::vector > lower_patterns;
-  std::vector > upper_patterns;
+  std::vector> lower_patterns;
+  std::vector> upper_patterns;
 
 public:
-  TuplePatternItemsRanged (
-std::vector > lower_patterns,
-std::vector > upper_patterns)
+  TuplePatternItemsRanged (std::vector> 
lower_patterns,
+  

[committed 80/88] gccrs: Add AST::AltPattern class

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* ast/rust-ast-dump.cc
(Dump::visit): Add AltPattern visitor.
* ast/rust-ast-dump.h:
(Dump::visit): Add AltPattern visitor.
* ast/rust-ast-full-decls.h
(class AltPattern): Add declaration.
* ast/rust-ast-visitor.h:
(ASTVisitor::visit): Add AltPattern visitor.
* ast/rust-ast.cc
(AltPattern::as_string): Add definition.
(AltPattern::accept_vis): Add definition.
* ast/rust-pattern.h
(class AltPattern): Add declaration.
* checks/errors/rust-feature-gate.h:
(FeatureGate::visit) Add AltPattern visitor
* expand/rust-attribute-visitor.cc
(AttrVisitor::visit): Add AltPattern visitor.
* expand/rust-attribute-visitor.h:
(AttrVisitor::visit): Add AltPattern visitor.
* hir/rust-ast-lower-base.cc
(ASTLoweringBase::visit): Add AltPattern visitor.
* hir/rust-ast-lower-base.h:
(ASTLoweringBase::visit): Add AltPattern visitor.
* resolve/rust-ast-resolve-base.cc
(ResolverBase::visit): Add AltPattern visitor.
* resolve/rust-ast-resolve-base.h:
(ResolverBase::visit): Add AltPattern visitor.
* resolve/rust-early-name-resolver.cc
(EarlyNameResolver::visit): Add AltPattern visitor.
* resolve/rust-early-name-resolver.h:
(EarlyNameResolver::visit): Add AltPattern visitor.
* util/rust-attributes.cc
(AttributeChecker::visit): Add AltPattern visitor.
* util/rust-attributes.h:
(AttributeChecker::visit): Add AltPattern visitor.

Signed-off-by: Owen Avery 
---
 gcc/rust/ast/rust-ast-dump.cc|  4 ++
 gcc/rust/ast/rust-ast-dump.h |  1 +
 gcc/rust/ast/rust-ast-full-decls.h   |  1 +
 gcc/rust/ast/rust-ast-visitor.h  |  1 +
 gcc/rust/ast/rust-ast.cc | 17 +
 gcc/rust/ast/rust-pattern.h  | 66 
 gcc/rust/checks/errors/rust-feature-gate.h   |  1 +
 gcc/rust/expand/rust-attribute-visitor.cc| 14 +
 gcc/rust/expand/rust-attribute-visitor.h |  1 +
 gcc/rust/hir/rust-ast-lower-base.cc  |  3 +
 gcc/rust/hir/rust-ast-lower-base.h   |  1 +
 gcc/rust/resolve/rust-ast-resolve-base.cc|  4 ++
 gcc/rust/resolve/rust-ast-resolve-base.h |  1 +
 gcc/rust/resolve/rust-early-name-resolver.cc |  7 +++
 gcc/rust/resolve/rust-early-name-resolver.h  |  1 +
 gcc/rust/util/rust-attributes.cc |  4 ++
 gcc/rust/util/rust-attributes.h  |  1 +
 17 files changed, 128 insertions(+)

diff --git a/gcc/rust/ast/rust-ast-dump.cc b/gcc/rust/ast/rust-ast-dump.cc
index 58eb35ad1db..10fb313c2c7 100644
--- a/gcc/rust/ast/rust-ast-dump.cc
+++ b/gcc/rust/ast/rust-ast-dump.cc
@@ -1678,6 +1678,10 @@ void
 Dump::visit (SlicePattern &)
 {}
 
+void
+Dump::visit (AltPattern &)
+{}
+
 // rust-stmt.h
 void
 Dump::visit (EmptyStmt &)
diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h
index 56918f5fc98..dfe6db0dd96 100644
--- a/gcc/rust/ast/rust-ast-dump.h
+++ b/gcc/rust/ast/rust-ast-dump.h
@@ -293,6 +293,7 @@ private:
   void visit (TuplePattern );
   void visit (GroupedPattern );
   void visit (SlicePattern );
+  void visit (AltPattern );
 
   // rust-stmt.h
   void visit (EmptyStmt );
diff --git a/gcc/rust/ast/rust-ast-full-decls.h 
b/gcc/rust/ast/rust-ast-full-decls.h
index 58b12a1be0e..9d7b00ac5a2 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -249,6 +249,7 @@ class TuplePatternItemsRanged;
 class TuplePattern;
 class GroupedPattern;
 class SlicePattern;
+class AltPattern;
 
 // rust-type.h
 class TraitBound;
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index aa59a115ee6..1083e834770 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -203,6 +203,7 @@ public:
   virtual void visit (TuplePattern ) = 0;
   virtual void visit (GroupedPattern ) = 0;
   virtual void visit (SlicePattern ) = 0;
+  virtual void visit (AltPattern ) = 0;
 
   // rust-stmt.h
   virtual void visit (EmptyStmt ) = 0;
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 972cba2e7bb..07983b7da06 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -2704,6 +2704,17 @@ SlicePattern::as_string () const
   return str;
 }
 
+std::string
+AltPattern::as_string () const
+{
+  std::string str ("AltPattern: ");
+
+  for (const auto  : alts)
+str += "\n " + pattern->as_string ();
+
+  return str;
+}
+
 std::string
 TuplePatternItemsMultiple::as_string () const
 {
@@ -5649,6 +5660,12 @@ SlicePattern::accept_vis (ASTVisitor )
   vis.visit (*this);
 }
 
+void
+AltPattern::accept_vis (ASTVisitor )
+{
+  vis.visit (*this);
+}
+
 void
 EmptyStmt::accept_vis (ASTVisitor )
 {
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 0e2f56e3216..a62e9b98d93 100644
--- 

[committed 84/88] gccrs: ast: Refactor TraitItem to keep Location info

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* ast/rust-ast.h: Keep location in TraitItem base class
* ast/rust-item.h (class TraitItemFunc): Use base class location 
instead.
(class TraitItemMethod): Likewise.
(class TraitItemConst): Likewise.
(class TraitItemType): Likewise.
* ast/rust-macro.h: Likewise.
---
 gcc/rust/ast/rust-ast.h   |  6 +-
 gcc/rust/ast/rust-item.h  | 44 ++-
 gcc/rust/ast/rust-macro.h | 10 -
 3 files changed, 26 insertions(+), 34 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index d986fdf9368..585bdb09e68 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1358,12 +1358,15 @@ protected:
 class TraitItem
 {
 protected:
-  TraitItem () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
+  TraitItem (Location locus)
+: node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
+  {}
 
   // Clone function implementation as pure virtual method
   virtual TraitItem *clone_trait_item_impl () const = 0;
 
   NodeId node_id;
+  Location locus;
 
 public:
   virtual ~TraitItem () {}
@@ -1382,6 +1385,7 @@ public:
   virtual bool is_marked_for_strip () const = 0;
 
   NodeId get_node_id () const { return node_id; }
+  Location get_locus () const { return locus; }
 };
 
 /* Abstract base class for items used within an inherent impl block (the impl
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 51ed815c700..16209613881 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -2908,7 +2908,6 @@ class TraitItemFunc : public TraitItem
   std::vector outer_attrs;
   TraitFunctionDecl decl;
   std::unique_ptr block_expr;
-  Location locus;
 
 public:
   // Returns whether function has a definition or is just a declaration.
@@ -2916,14 +2915,14 @@ public:
 
   TraitItemFunc (TraitFunctionDecl decl, std::unique_ptr block_expr,
 std::vector outer_attrs, Location locus)
-: TraitItem (), outer_attrs (std::move (outer_attrs)),
-  decl (std::move (decl)), block_expr (std::move (block_expr)),
-  locus (locus)
+: TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+  decl (std::move (decl)), block_expr (std::move (block_expr))
   {}
 
   // Copy constructor with clone
   TraitItemFunc (TraitItemFunc const )
-: outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus)
+: TraitItem (other.locus), outer_attrs (other.outer_attrs),
+  decl (other.decl)
   {
 node_id = other.node_id;
 
@@ -2956,8 +2955,6 @@ public:
 
   std::string as_string () const override;
 
-  Location get_locus () const { return locus; }
-
   void accept_vis (ASTVisitor ) override;
 
   // Invalid if trait decl is empty, so base stripping on that.
@@ -3128,7 +3125,6 @@ class TraitItemMethod : public TraitItem
   std::vector outer_attrs;
   TraitMethodDecl decl;
   std::unique_ptr block_expr;
-  Location locus;
 
 public:
   // Returns whether method has a definition or is just a declaration.
@@ -3136,14 +3132,14 @@ public:
 
   TraitItemMethod (TraitMethodDecl decl, std::unique_ptr block_expr,
   std::vector outer_attrs, Location locus)
-: TraitItem (), outer_attrs (std::move (outer_attrs)),
-  decl (std::move (decl)), block_expr (std::move (block_expr)),
-  locus (locus)
+: TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+  decl (std::move (decl)), block_expr (std::move (block_expr))
   {}
 
   // Copy constructor with clone
   TraitItemMethod (TraitItemMethod const )
-: outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus)
+: TraitItem (other.locus), outer_attrs (other.outer_attrs),
+  decl (other.decl)
   {
 node_id = other.node_id;
 
@@ -3176,8 +3172,6 @@ public:
 
   std::string as_string () const override;
 
-  Location get_locus () const { return locus; }
-
   void accept_vis (ASTVisitor ) override;
 
   // Invalid if trait decl is empty, so base stripping on that.
@@ -3219,8 +3213,6 @@ class TraitItemConst : public TraitItem
   // bool has_expression;
   std::unique_ptr expr;
 
-  Location locus;
-
 public:
   // Whether the constant item has an associated expression.
   bool has_expression () const { return expr != nullptr; }
@@ -3228,14 +3220,14 @@ public:
   TraitItemConst (Identifier name, std::unique_ptr type,
  std::unique_ptr expr,
  std::vector outer_attrs, Location locus)
-: TraitItem (), outer_attrs (std::move (outer_attrs)),
-  name (std::move (name)), type (std::move (type)), expr (std::move 
(expr)),
-  locus (locus)
+: TraitItem (locus), outer_attrs (std::move (outer_attrs)),
+  name (std::move (name)), type (std::move (type)), expr (std::move (expr))
   {}
 
   // Copy constructor with clones
   TraitItemConst (TraitItemConst const )
-: outer_attrs (other.outer_attrs), name (other.name), locus (other.locus)
+ 

[committed 76/88] gccrs: Fix regression in testcase

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Fixes #776

Signed-off-by: Philip Herron 

gcc/testsuite/ChangeLog:

* rust/compile/torture/traits10.rs: Fix test-case
---
 .../rust/compile/torture/traits10.rs  | 64 ++-
 1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/rust/compile/torture/traits10.rs 
b/gcc/testsuite/rust/compile/torture/traits10.rs
index a02927007b3..4cf36e3c6f1 100644
--- a/gcc/testsuite/rust/compile/torture/traits10.rs
+++ b/gcc/testsuite/rust/compile/torture/traits10.rs
@@ -1,5 +1,65 @@
-trait Foo // where
-// Self: Sized,
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+fn clone() -> Self;
+
+fn clone_from( self, source: ) {
+*self = source.clone()
+}
+}
+
+mod impls {
+use super::Clone;
+
+macro_rules! impl_clone {
+($($t:ty)*) => {
+$(
+impl Clone for $t {
+fn clone() -> Self {
+*self
+}
+}
+)*
+}
+}
+
+impl_clone! {
+usize u8 u16 u32 u64 // u128
+isize i8 i16 i32 i64 // i128
+f32 f64
+bool char
+}
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+// Empty.
+}
+
+mod copy_impls {
+use super::Copy;
+
+macro_rules! impl_copy {
+($($t:ty)*) => {
+$(
+impl Copy for $t {}
+)*
+}
+}
+
+impl_copy! {
+usize u8 u16 u32 u64 // u128
+isize i8 i16 i32 i64 // i128
+f32 f64
+bool char
+}
+}
+
+trait Foo
+where
+Self: Sized,
 {
 fn get(self) -> i32;
 
-- 
2.40.0



[committed 77/88] gccrs: Add trailing newline

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* checks/errors/rust-feature-gate.h: Add trailing newline before EOF.

Signed-off-by: Owen Avery 
---
 gcc/rust/checks/errors/rust-feature-gate.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/checks/errors/rust-feature-gate.h 
b/gcc/rust/checks/errors/rust-feature-gate.h
index 6768c4c2498..05789cf4751 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/rust-feature-gate.h
@@ -193,4 +193,4 @@ private:
   std::set valid_features;
 };
 } // namespace Rust
-#endif
\ No newline at end of file
+#endif
-- 
2.40.0



[committed 78/88] gccrs: builtins: Return empty list of tokens instead of nullptr

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* expand/rust-macro-builtins.cc (MacroBuiltin::include_handler): Do not
return nullptr token in expansion of `include!()`

gcc/testsuite/ChangeLog:

* rust/compile/empty.in: New test.
* rust/compile/include_empty.rs: New test.
---
 gcc/rust/expand/rust-macro-builtins.cc  | 15 +--
 gcc/testsuite/rust/compile/empty.in |  1 +
 gcc/testsuite/rust/compile/include_empty.rs |  8 
 3 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/empty.in
 create mode 100644 gcc/testsuite/rust/compile/include_empty.rs

diff --git a/gcc/rust/expand/rust-macro-builtins.cc 
b/gcc/rust/expand/rust-macro-builtins.cc
index 3b6f69bbd69..97594921dec 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -752,8 +752,19 @@ MacroBuiltin::include_handler (Location invoc_locus, 
AST::MacroInvocData )
   nodes.push_back (node);
 }
 
-  // FIXME: Do not return an empty token vector here
-  return AST::Fragment (nodes, nullptr);
+  // FIXME: This returns an empty vector of tokens and works fine, but is that
+  // the expected behavior? `include` macros are a bit harder to reason about
+  // since they include tokens. Furthermore, our lexer has no easy way to 
return
+  // a slice of tokens like the MacroInvocLexer. So it gets even harder to
+  // extrac tokens from here. For now, let's keep it that way and see if it
+  // eventually breaks, but I don't expect it to cause many issues since the
+  // list of tokens is only used when a macro invocation mixes eager
+  // macro invocations and already expanded tokens. Think
+  // `concat!(a!(), 15, b!())`. We need to be able to expand a!(), expand b!(),
+  // and then insert the `15` token in between. In the case of `include!()`, we
+  // only have one argument. So it's either going to be a macro invocation or a
+  // string literal.
+  return AST::Fragment (nodes, std::vector> ());
 }
 
 AST::Fragment
diff --git a/gcc/testsuite/rust/compile/empty.in 
b/gcc/testsuite/rust/compile/empty.in
new file mode 100644
index 000..8b137891791
--- /dev/null
+++ b/gcc/testsuite/rust/compile/empty.in
@@ -0,0 +1 @@
+
diff --git a/gcc/testsuite/rust/compile/include_empty.rs 
b/gcc/testsuite/rust/compile/include_empty.rs
new file mode 100644
index 000..28e940fa0ac
--- /dev/null
+++ b/gcc/testsuite/rust/compile/include_empty.rs
@@ -0,0 +1,8 @@
+#[rustc_builtin_macro]
+macro_rules! include {
+() => {};
+}
+
+include!("empty.in");
+
+fn main() {}
-- 
2.40.0



[committed 73/88] gccrs: Extract query_type from TypeCheckBase to be a simple extern

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* Make-lang.in: add new dependancy
* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::query_type): 
refactor
* typecheck/rust-hir-type-check-base.h: refactor
* typecheck/rust-hir-type-check.h (RUST_HIR_TYPE_CHECK): refactor
* typecheck/rust-type-util.cc: New file.
* typecheck/rust-type-util.h: New file.
---
 gcc/rust/Make-lang.in |   1 +
 .../typecheck/rust-hir-type-check-base.cc |  73 
 gcc/rust/typecheck/rust-hir-type-check-base.h |   2 -
 gcc/rust/typecheck/rust-hir-type-check.h  |   1 +
 gcc/rust/typecheck/rust-type-util.cc  | 108 ++
 gcc/rust/typecheck/rust-type-util.h   |  38 ++
 6 files changed, 148 insertions(+), 75 deletions(-)
 create mode 100644 gcc/rust/typecheck/rust-type-util.cc
 create mode 100644 gcc/rust/typecheck/rust-type-util.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 09bbe450bd5..06f64a01dce 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -134,6 +134,7 @@ GRS_OBJS = \
 rust/rust-hir-type-check-implitem.o \
 rust/rust-hir-dot-operator.o \
 rust/rust-hir-path-probe.o \
+rust/rust-type-util.o \
 rust/rust-coercion.o \
 rust/rust-casts.o \
 rust/rust-unify.o \
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc 
b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 6e42b7b7b23..e302e27f4ab 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -483,78 +483,5 @@ TypeCheckBase::resolve_generic_params (
 }
 }
 
-bool
-TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
-{
-  if (context->query_in_progress (reference))
-return false;
-
-  if (context->lookup_type (reference, result))
-return true;
-
-  context->insert_query (reference);
-
-  HIR::Item *item = mappings->lookup_hir_item (reference);
-  if (item != nullptr)
-{
-  rust_debug_loc (item->get_locus (), "resolved item {%u} to", reference);
-  *result = TypeCheckItem::Resolve (*item);
-  context->query_completed (reference);
-  return true;
-}
-
-  HirId parent_impl_id = UNKNOWN_HIRID;
-  HIR::ImplItem *impl_item
-= mappings->lookup_hir_implitem (reference, _impl_id);
-  if (impl_item != nullptr)
-{
-  HIR::ImplBlock *impl_block
-   = mappings->lookup_hir_impl_block (parent_impl_id);
-  rust_assert (impl_block != nullptr);
-
-  // found an impl item
-  rust_debug_loc (impl_item->get_locus (), "resolved impl-item {%u} to",
- reference);
-
-  *result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item);
-  context->query_completed (reference);
-  return true;
-}
-
-  // is it an impl_type?
-  HIR::ImplBlock *impl_block_by_type = nullptr;
-  bool found_impl_block_type
-= mappings->lookup_impl_block_type (reference, _block_by_type);
-  if (found_impl_block_type)
-{
-  *result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type);
-  context->query_completed (reference);
-  return true;
-}
-
-  // is it an extern item?
-  HirId parent_extern_block_id = UNKNOWN_HIRID;
-  HIR::ExternalItem *extern_item
-= mappings->lookup_hir_extern_item (reference, _extern_block_id);
-  if (extern_item != nullptr)
-{
-  HIR::ExternBlock *block
-   = mappings->lookup_hir_extern_block (parent_extern_block_id);
-  rust_assert (block != nullptr);
-
-  *result = TypeCheckTopLevelExternItem::Resolve (extern_item, *block);
-  context->query_completed (reference);
-  return true;
-}
-
-  // more?
-  Location possible_locus = mappings->lookup_location (reference);
-  rust_debug_loc (possible_locus, "query system failed to resolve: [%u]",
- reference);
-  context->query_completed (reference);
-
-  return false;
-}
-
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h 
b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 335014339f3..b8ff2cf6dc9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -69,8 +69,6 @@ protected:
 const std::vector> _params,
 std::vector );
 
-  bool query_type (HirId reference, TyTy::BaseType **result);
-
   Analysis::Mappings *mappings;
   Resolver *resolver;
   TypeCheckContext *context;
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h 
b/gcc/rust/typecheck/rust-hir-type-check.h
index 512453947a6..6d4b9b8a62f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -19,6 +19,7 @@
 #ifndef RUST_HIR_TYPE_CHECK
 #define RUST_HIR_TYPE_CHECK
 
+#include "rust-type-util.h"
 #include "rust-hir-full-decls.h"
 #include "rust-hir-map.h"
 #include "rust-tyty.h"
diff --git a/gcc/rust/typecheck/rust-type-util.cc 

[committed 72/88] gccrs: Implemented UTF-8 checking for include_str!()

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* expand/rust-macro-builtins.cc
(MacroBuiltin::include_str_handler): Add check for valid UTF-8.

gcc/testsuite/ChangeLog:

* rust/compile/builtin_macro_include_str.rs:
Include test of invalid UTF-8.
* rust/compile/invalid_utf8: File with invalid UTF-8.

Signed-off-by: Owen Avery 
---
 gcc/rust/expand/rust-macro-builtins.cc| 51 ++-
 .../rust/compile/builtin_macro_include_str.rs |  1 +
 gcc/testsuite/rust/compile/invalid_utf8   |  1 +
 3 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/invalid_utf8

diff --git a/gcc/rust/expand/rust-macro-builtins.cc 
b/gcc/rust/expand/rust-macro-builtins.cc
index e594a2500d0..3b6f69bbd69 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -389,8 +389,55 @@ MacroBuiltin::include_str_handler (Location invoc_locus,
 
   std::vector bytes = load_file_bytes (target_filename.c_str ());
 
-  /* FIXME: Enforce that the file contents are valid UTF-8.  */
-  std::string str ((const char *) [0], bytes.size ());
+  /* FIXME: reuse lexer */
+  int expect_single = 0;
+  for (uint8_t b : bytes)
+{
+  if (expect_single)
+   {
+ if ((b & 0xC0) != 0x80)
+   /* character was truncated, exit with expect_single != 0 */
+   break;
+ expect_single--;
+   }
+  else if (b & 0x80)
+   {
+ if (b >= 0xF8)
+   {
+ /* more than 4 leading 1s */
+ expect_single = 1;
+ break;
+   }
+ else if (b >= 0xF0)
+   {
+ /* 4 leading 1s */
+ expect_single = 3;
+   }
+ else if (b >= 0xE0)
+   {
+ /* 3 leading 1s */
+ expect_single = 2;
+   }
+ else if (b >= 0xC0)
+   {
+ /* 2 leading 1s */
+ expect_single = 1;
+   }
+ else
+   {
+ /* only 1 leading 1 */
+ expect_single = 1;
+ break;
+   }
+   }
+}
+
+  std::string str;
+  if (expect_single)
+rust_error_at (invoc_locus, "%s was not a valid utf-8 file",
+  target_filename.c_str ());
+  else
+str = std::string ((const char *) [0], bytes.size ());
 
   auto node = AST::SingleASTNode (make_string (invoc_locus, str));
   auto str_tok = make_token (Token::make_string (invoc_locus, std::move 
(str)));
diff --git a/gcc/testsuite/rust/compile/builtin_macro_include_str.rs 
b/gcc/testsuite/rust/compile/builtin_macro_include_str.rs
index 38f5e3b7334..8092193195d 100644
--- a/gcc/testsuite/rust/compile/builtin_macro_include_str.rs
+++ b/gcc/testsuite/rust/compile/builtin_macro_include_str.rs
@@ -10,4 +10,5 @@ fn main () {
   include_str! ("foo.txt", "bar.txt"); // { dg-error "macro takes 1 argument" 
"" }
   include_str! ("builtin_macro_include_str.rs"); // ok
   include_str! ("builtin_macro_include_str.rs",); // trailing comma ok
+  include_str! ("invalid_utf8"); // { dg-error "invalid_utf8 was not a valid 
utf-8 file" "" }
 }
diff --git a/gcc/testsuite/rust/compile/invalid_utf8 
b/gcc/testsuite/rust/compile/invalid_utf8
new file mode 100644
index 000..29e181ebb88
--- /dev/null
+++ b/gcc/testsuite/rust/compile/invalid_utf8
@@ -0,0 +1 @@
+�
-- 
2.40.0



[committed 68/88] gccrs: Simplify WildcardPattern let statement handling

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* backend/rust-compile-pattern.cc
(CompilePatternLet::visit): Simplify WildcardPattern compilation for 
let statements.
* backend/rust-compile-var-decl.h:
(CompileVarDecl::visit): Remove variable declaration for 
WildcardPattern.
* resolve/rust-ast-resolve-pattern.h:
(PatternDeclaration::visit): Remove name resolution for WildcardPattern.

Signed-off-by: Owen Avery 
---
 gcc/rust/backend/rust-compile-pattern.cc| 28 +
 gcc/rust/backend/rust-compile-var-decl.h| 16 +---
 gcc/rust/resolve/rust-ast-resolve-pattern.h |  7 --
 3 files changed, 7 insertions(+), 44 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index cb4b082f9c8..d98f7beb0e8 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -361,30 +361,14 @@ CompilePatternLet::visit (HIR::IdentifierPattern )
 void
 CompilePatternLet::visit (HIR::WildcardPattern )
 {
-  Bvariable *var = nullptr;
-  rust_assert (
-ctx->lookup_var_decl (pattern.get_pattern_mappings ().get_hirid (), ));
-
-  auto fnctx = ctx->peek_fn ();
-  if (ty->is_unit ())
-{
-  ctx->add_statement (init_expr);
+  tree init_stmt = NULL;
+  tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
 
-  tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
+  ctx->get_backend ()->temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
+  stmt_type, init_expr, false,
+  pattern.get_locus (), _stmt);
 
-  auto unit_type_init_expr
-   = ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
-  rval_locus);
-  auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
-   unit_type_init_expr);
-  ctx->add_statement (s);
-}
-  else
-{
-  auto s
-   = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init_expr);
-  ctx->add_statement (s);
-}
+  ctx->add_statement (init_stmt);
 }
 
 void
diff --git a/gcc/rust/backend/rust-compile-var-decl.h 
b/gcc/rust/backend/rust-compile-var-decl.h
index 9e07999f273..13b429d41e1 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -53,21 +53,6 @@ public:
 locals.push_back (var);
   }
 
-  void visit (HIR::WildcardPattern ) override
-  {
-translated_type = ctx->get_backend ()->immutable_type (translated_type);
-
-Bvariable *var
-  = ctx->get_backend ()->local_variable (fndecl, "_", translated_type,
-NULL /*decl_var*/,
-pattern.get_locus ());
-
-HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
-ctx->insert_var_decl (stmt_id, var);
-
-locals.push_back (var);
-  }
-
   // Empty visit for unused Pattern HIR nodes.
   void visit (HIR::LiteralPattern &) override {}
   void visit (HIR::PathInExpression &) override {}
@@ -78,6 +63,7 @@ public:
   void visit (HIR::StructPattern &) override {}
   void visit (HIR::TuplePattern &) override {}
   void visit (HIR::TupleStructPattern &) override {}
+  void visit (HIR::WildcardPattern &) override {}
 
 private:
   CompileVarDecl (Context *ctx, tree fndecl, tree translated_type,
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h 
b/gcc/rust/resolve/rust-ast-resolve-pattern.h
index 3e74f0a4cc6..4c7d13a16d0 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.h
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h
@@ -70,13 +70,6 @@ public:
   pattern.get_node_id (), pattern.get_locus (), type);
   }
 
-  void visit (AST::WildcardPattern ) override
-  {
-resolver->get_name_scope ().insert (
-  CanonicalPath::new_seg (pattern.get_node_id (), "_"),
-  pattern.get_node_id (), pattern.get_locus (), type);
-  }
-
   void visit (AST::GroupedPattern ) override
   {
 pattern.get_pattern_in_parens ()->accept_vis (*this);
-- 
2.40.0



[committed 71/88] gccrs: Add support for parsing empty tuple patterns.

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h
(Parser::parse_grouped_or_tuple_pattern): Add support for empty tuple 
patterns.

gcc/testsuite/ChangeLog:

* rust/compile/parse_empty_tuple_pattern.rs: New test.

Signed-off-by: Owen Avery 
---
 gcc/rust/parse/rust-parse-impl.h| 9 +
 gcc/testsuite/rust/compile/parse_empty_tuple_pattern.rs | 3 +++
 2 files changed, 12 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/parse_empty_tuple_pattern.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 4ceb978f7f4..cc5436cff63 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -10926,6 +10926,15 @@ 
Parser::parse_grouped_or_tuple_pattern ()
   return std::unique_ptr (
new AST::TuplePattern (std::move (items), paren_locus));
 }
+  else if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+{
+  skip_token (RIGHT_PAREN);
+  auto items = std::unique_ptr (
+   new AST::TuplePatternItemsMultiple (
+ std::vector> ()));
+  return std::unique_ptr (
+   new AST::TuplePattern (std::move (items), paren_locus));
+}
 
   // parse initial pattern (required)
   std::unique_ptr initial_pattern = parse_pattern ();
diff --git a/gcc/testsuite/rust/compile/parse_empty_tuple_pattern.rs 
b/gcc/testsuite/rust/compile/parse_empty_tuple_pattern.rs
new file mode 100644
index 000..d974d31b8ba
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_empty_tuple_pattern.rs
@@ -0,0 +1,3 @@
+fn main() {
+let () = ();
+}
-- 
2.40.0



[committed 67/88] gccrs: Add test

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/testsuite/ChangeLog:

* rust/compile/variadic.rs: New test.

Signed-off-by: Owen Avery 
---
 gcc/testsuite/rust/compile/variadic.rs | 8 
 1 file changed, 8 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/variadic.rs

diff --git a/gcc/testsuite/rust/compile/variadic.rs 
b/gcc/testsuite/rust/compile/variadic.rs
new file mode 100644
index 000..886341b088c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/variadic.rs
@@ -0,0 +1,8 @@
+extern "C" {
+fn printf(s: *const i8, ...);
+}
+
+fn main() {
+// { dg-error "expected .c_int. variadic argument" "" { target *-*-* } .+1 
}
+printf("%d\n" as *const str as *const i8, 1i8);
+}
-- 
2.40.0



[committed 65/88] gccrs: Add feature gate for "rust-intrinsic".

2023-04-05 Thread arthur . cohen
From: mxlol233 

This commit implemented a feature gate to check `intrinsics`.

gcc/rust/ChangeLog:

* checks/errors/rust-feature-gate.cc: Add implementation for
`void FeatureGate::visit (AST::ExternBlock )`. Add `valid_feature`
construction process in `FeatureGate::check`.
* checks/errors/rust-feature-gate.h: Add declaration for
`void FeatureGate::visit (AST::ExternBlock )`. Add private
variable `valid_feature`.
* checks/errors/rust-feature.h: Change `issue` to `m_issue`.

gcc/testsuite/ChangeLog:

* rust/compile/const-issue1440.rs: Add crate feature: `intrinsics`.
* rust/compile/feature_intrinsics.rs: New file.
* rust/compile/issue-1031.rs: Add crate feature: `intrinsics`.
* rust/compile/issue-1130.rs: Add crate feature: `intrinsics`.
* rust/compile/issue-1131.rs: Add crate feature: `intrinsics`.
* rust/compile/issue-1237.rs: Add crate feature: `intrinsics`.
* rust/compile/issue-1289.rs: Add crate feature: `intrinsics`.
* rust/compile/rust-const-blog-issue.rs: Add crate feature: 
`intrinsics`.
* rust/compile/torture/intrinsics-3.rs: Add crate feature: `intrinsics`.
* rust/compile/torture/intrinsics-4.rs: Add crate feature: `intrinsics`.
* rust/compile/torture/intrinsics-5.rs: Add crate feature: `intrinsics`.
* rust/compile/torture/intrinsics-6.rs: Add crate feature: `intrinsics`.
* rust/compile/torture/intrinsics-7.rs: Add crate feature: `intrinsics`.
* rust/compile/torture/issue-1024.rs: Add crate feature: `intrinsics`.
* rust/compile/torture/issue-1075.rs: Add crate feature: `intrinsics`.
* rust/compile/torture/issue-1432.rs: Add crate feature: `intrinsics`.
* rust/compile/unsafe10.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/atomic_load.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/atomic_store.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/copy_nonoverlapping1.rs: Add crate feature:
`intrinsics`.
* rust/execute/torture/issue-1120.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/issue-1133.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/issue-1232.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/slice-magic.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/slice-magic2.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/str-layout1.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/transmute1.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/wrapping_op1.rs: Add crate feature: `intrinsics`.
* rust/execute/torture/wrapping_op2.rs: Add crate feature: `intrinsics`.

Signed-off-by: Xiao Ma 
---
 gcc/rust/checks/errors/rust-feature-gate.cc   | 61 ---
 gcc/rust/checks/errors/rust-feature-gate.h|  7 ++-
 gcc/rust/checks/errors/rust-feature.h |  5 +-
 gcc/testsuite/rust/compile/const-issue1440.rs |  1 +
 .../rust/compile/feature_intrinsics.rs|  7 +++
 gcc/testsuite/rust/compile/issue-1031.rs  |  2 +
 gcc/testsuite/rust/compile/issue-1130.rs  |  2 +
 gcc/testsuite/rust/compile/issue-1131.rs  |  2 +
 gcc/testsuite/rust/compile/issue-1237.rs  |  2 +
 gcc/testsuite/rust/compile/issue-1289.rs  |  2 +
 .../rust/compile/rust-const-blog-issue.rs |  2 +
 .../rust/compile/torture/intrinsics-3.rs  |  2 +
 .../rust/compile/torture/intrinsics-4.rs  |  2 +
 .../rust/compile/torture/intrinsics-5.rs  |  2 +
 .../rust/compile/torture/intrinsics-6.rs  |  2 +
 .../rust/compile/torture/intrinsics-7.rs  |  2 +
 .../rust/compile/torture/issue-1024.rs|  2 +
 .../rust/compile/torture/issue-1075.rs|  2 +
 .../rust/compile/torture/issue-1432.rs|  1 +
 gcc/testsuite/rust/compile/unsafe10.rs|  2 +
 .../rust/execute/torture/atomic_load.rs   |  2 +
 .../rust/execute/torture/atomic_store.rs  |  2 +
 .../execute/torture/copy_nonoverlapping1.rs   |  2 +
 .../rust/execute/torture/issue-1120.rs|  2 +
 .../rust/execute/torture/issue-1133.rs|  2 +
 .../rust/execute/torture/issue-1232.rs|  2 +
 .../rust/execute/torture/slice-magic.rs   |  2 +
 .../rust/execute/torture/slice-magic2.rs  |  2 +
 .../rust/execute/torture/str-layout1.rs   |  2 +
 .../rust/execute/torture/transmute1.rs|  1 +
 .../rust/execute/torture/wrapping_op1.rs  |  2 +
 .../rust/execute/torture/wrapping_op2.rs  |  2 +
 32 files changed, 122 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/feature_intrinsics.rs

diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc 
b/gcc/rust/checks/errors/rust-feature-gate.cc
index 31ce3679ee1..bd01b52c7ff 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/rust-feature-gate.cc
@@ -17,14 +17,15 @@
 // 

[committed 64/88] gccrs: Update copyright years.

2023-04-05 Thread arthur . cohen
From: Thomas Schwinge 

gcc/rust/ChangeLog:

* ast/rust-ast-fragment.cc: Update copyright years.
* ast/rust-ast-fragment.h: Likewise.
* ast/rust-macro.cc: Likewise.
* checks/errors/rust-feature-gate.cc: Likewise.
* checks/errors/rust-feature-gate.h: Likewise.
* checks/errors/rust-feature.cc: Likewise.
* checks/errors/rust-feature.h: Likewise.
* hir/rust-ast-lower-expr.cc: Likewise.
* hir/rust-ast-lower-type.cc: Likewise.
* resolve/rust-early-name-resolver.cc: Likewise.
* resolve/rust-early-name-resolver.h: Likewise.
* rust-gcc.h: Likewise.
* typecheck/rust-hir-path-probe.cc: Likewise.
* typecheck/rust-hir-trait-reference.cc: Likewise.
* typecheck/rust-tyty-bounds.h: Likewise.
* typecheck/rust-tyty-subst.cc: Likewise.
* typecheck/rust-tyty-subst.h: Likewise.
* typecheck/rust-tyty-util.cc: Likewise.
* typecheck/rust-tyty-util.h: Likewise.
* typecheck/rust-unify.cc: Likewise.
* typecheck/rust-unify.h: Likewise.
* util/rust-inline-visitor.h: Likewise.
---
 gcc/rust/ast/rust-ast-fragment.cc  | 2 +-
 gcc/rust/ast/rust-ast-fragment.h   | 2 +-
 gcc/rust/ast/rust-macro.cc | 2 +-
 gcc/rust/checks/errors/rust-feature-gate.cc| 2 +-
 gcc/rust/checks/errors/rust-feature-gate.h | 2 +-
 gcc/rust/checks/errors/rust-feature.cc | 2 +-
 gcc/rust/checks/errors/rust-feature.h  | 2 +-
 gcc/rust/hir/rust-ast-lower-expr.cc| 2 +-
 gcc/rust/hir/rust-ast-lower-type.cc| 2 +-
 gcc/rust/resolve/rust-early-name-resolver.cc   | 2 +-
 gcc/rust/resolve/rust-early-name-resolver.h| 2 +-
 gcc/rust/rust-gcc.h| 2 +-
 gcc/rust/typecheck/rust-hir-path-probe.cc  | 2 +-
 gcc/rust/typecheck/rust-hir-trait-reference.cc | 2 +-
 gcc/rust/typecheck/rust-tyty-bounds.h  | 2 +-
 gcc/rust/typecheck/rust-tyty-subst.cc  | 2 +-
 gcc/rust/typecheck/rust-tyty-subst.h   | 2 +-
 gcc/rust/typecheck/rust-tyty-util.cc   | 2 +-
 gcc/rust/typecheck/rust-tyty-util.h| 2 +-
 gcc/rust/typecheck/rust-unify.cc   | 2 +-
 gcc/rust/typecheck/rust-unify.h| 2 +-
 gcc/rust/util/rust-inline-visitor.h| 2 +-
 22 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-fragment.cc 
b/gcc/rust/ast/rust-ast-fragment.cc
index fba629c0119..a9dc4747d51 100644
--- a/gcc/rust/ast/rust-ast-fragment.cc
+++ b/gcc/rust/ast/rust-ast-fragment.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
 
 // This file is part of GCC.
 
diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h
index 22e99090b25..41f5a287756 100644
--- a/gcc/rust/ast/rust-ast-fragment.h
+++ b/gcc/rust/ast/rust-ast-fragment.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
 
 // This file is part of GCC.
 
diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-macro.cc
index b90cc15898e..b6f8f6c059a 100644
--- a/gcc/rust/ast/rust-macro.cc
+++ b/gcc/rust/ast/rust-macro.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
 
 // This file is part of GCC.
 
diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc 
b/gcc/rust/checks/errors/rust-feature-gate.cc
index cd26f8a17f5..31ce3679ee1 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/rust-feature-gate.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
 
 // This file is part of GCC.
 
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h 
b/gcc/rust/checks/errors/rust-feature-gate.h
index 080c15ccd23..dc95c6b3879 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/rust-feature-gate.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
 
 // This file is part of GCC.
 
diff --git a/gcc/rust/checks/errors/rust-feature.cc 
b/gcc/rust/checks/errors/rust-feature.cc
index b87b4ca38ef..81689d9302b 100644
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
 
 // This file is part of GCC.
 
diff --git a/gcc/rust/checks/errors/rust-feature.h 
b/gcc/rust/checks/errors/rust-feature.h
index bf93b090af5..1425e26cd9a 100644
--- a/gcc/rust/checks/errors/rust-feature.h
+++ b/gcc/rust/checks/errors/rust-feature.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+// Copyright (C) 

[committed 63/88] gccrs: cli: Update safety warning message

2023-04-05 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

The compiler's warning message about the safety flag did not match
cargo-gccrs environment variable name anymore.

gcc/rust/ChangeLog:

* rust-session-manager.cc (Session::compile_crate): Update the
environment variable name.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/rust-session-manager.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 0f460e2d2f4..a086f83a3d0 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -441,7 +441,7 @@ Session::compile_crate (const char *filename)
   "defining the following environment variable (any value will "
   "do)\n\nGCCRS_INCOMPLETE_AND_EXPERIMENTAL_COMPILER_DO_NOT_USE\n\nFor "
   "cargo-gccrs, this means passing\n\n"
-  "GCCRS_EXTRA_FLAGS=\"-frust-incomplete-and-experimental-compiler-do-not-"
+  "GCCRS_EXTRA_ARGS=\"-frust-incomplete-and-experimental-compiler-do-not-"
   "use\"\n\nas an environment variable.");
 
   RAIIFile file_wrap (filename);
-- 
2.40.0



[committed 60/88] gccrs: macros: Perform macro expansion in a fixed-point fashion.

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

This commit changes our macro expansion system from an eager and recursive
macro expansion to a fixed-point like system. Instead of, when seeing
a macro invocation, expanding it and all of the macros within it, we
now perform multiple passes of expansion on the entire crate.

This, however, leads to a problem. Rust macros are expanded lazily, but
Rust builtin macros should be expanded eagerly. Due to this, we must
work around the lazy expansion in builtin macros and perform eager
expansion for each pass of the fixed-point, before finally expanding
the builtin when there are no longer any inner macro invocations.

To perform proper macro scoping, the ENR now keeps track of the current
scope (`current_scope` member) and resolves macros accordingly.

This is done through the use of the `scoped` method, which creates a new
scope, runs a specified lambda and then exits the scope. This prevents
pushing/popping errors that we've seen happen already in similar
contexts.

We might think about generalizing it to other classes, providing a
`Scoped` class or similar

gcc/rust/ChangeLog:

* ast/rust-macro.cc: New file.
* Make-lang.in: Add `rust-macro.o` object
* ast/rust-ast-fragment.cc (Fragment::Fragment): Change API around
the construction of AST fragments.
(Fragment::operator=): Correct `Fragment::operator=` to take into
account the fragment tokens.
(Fragment::create_error): Use new constructor.
(Fragment::complete): Remove in favor of new constructor.
(Fragment::unexpanded): Remove as that Fragment type is no longer used
or possible.
(Fragment::get_tokens): Add helper to access a fragment's tokens.
* ast/rust-ast-fragment.h (enum class): Remove `FragmentKind::Unused`
* ast/rust-ast.cc (MacroInvocation::as_string): Display
builtin macro invocations properly.
* ast/rust-ast.h: Fix `DelimTokenTree` class copy constructors and
handling of its token vector.
* ast/rust-macro.h (class MacroMatcher): Format.
(class MetaItemSeq): Likewise.
(builtin_macro_from_string): Get a `BuiltinMacroKind` from a given
string, i.e the name of the macro (`assert!`, `cfg!` and so on).
* expand/rust-attribute-visitor.cc (AttrVisitor::visit): Do not expand
macros recursively anymore.
(AttrVisitor::maybe_expand_expr): Likewise.
(AttrVisitor::maybe_expand_type): Likewise.
* expand/rust-attribute-visitor.h: Likewise, and remove
`expand_macro_fragment_recursively` function.
* expand/rust-macro-builtins.cc (make_token): Add shorthand for
returning `std::unique_ptr`s.
(make_macro_invocation): Add shorthand for returning fragments
containing builtin macro invocations.
(try_expand_macro_expression): Do not expand macros recursively.
(try_expand_single_string_literal): Likewise.
(try_expand_many_expr): Likewise.
(parse_single_string_literal): Error out more appropriately.
(MacroBuiltin::compile_error_handler): Add explanation for eager
invocation
(MacroBuiltin::file_handler): Return the proper tokens associated with
macro invocation, and builtin macros in the case of necessary eager
expansion.
(MacroBuiltin::column_handler): Likewise.
(MacroBuiltin::include_bytes_handler): Likewise.
(MacroBuiltin::include_str_handler): Likewise.
(MacroBuiltin::concat_handler): Likewise.
(MacroBuiltin::env_handler): Likewise.
(MacroBuiltin::cfg_handler): Likewise.
(MacroBuiltin::include_handler): Likewise.
(MacroBuiltin::line_handler): Likewise.
* expand/rust-macro-expand.cc (MacroExpander::expand_eager_invocations):
Add function to expand eager invocations *once* in the fixed point
pipeline.
(MacroExpander::expand_invoc): Call into `expand_eager_invocations` for
builtin macro invocations.
(MacroExpander::expand_crate): Use new `AttrVisitor` API.
(parse_many): Return tokens in `AST::Fragment`.
(transcribe_expression): Likewise.
(transcribe_type): Likewise.
* expand/rust-macro-expand.h (struct MacroExpander): Add `has_changed`
flag for fixed point checking.
* resolve/rust-early-name-resolver.cc 
(EarlyNameResolver::EarlyNameResolver):
Keep track of the current macro scope.
(EarlyNameResolver::go): Use `scoped` API.
(EarlyNameResolver::visit): Likewise.
* resolve/rust-early-name-resolver.h: Add `scoped` API.
* rust-session-manager.cc (Session::expansion): Perform macro expansion
in a fixed-point fashion.

gcc/testsuite/ChangeLog:

* rust/compile/macro17.rs: Fix testsuite for new recursion errors.
* rust/compile/macro44.rs: Fix invalid testcase assertions.
* rust/compile/builtin_macro_recurse.rs: Fix invalid test.
 

[committed 62/88] gccrs: typecheck: Refactor rust-hir-trait-reference.h

2023-04-05 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Move function body to their own cc file instead of keeping them in the
header file.

gcc/rust/ChangeLog:

* Make-lang.in: Add `rust-hir-trait-reference.o`.
* typecheck/rust-hir-trait-reference.h: Remove multiple function body.
* typecheck/rust-hir-trait-reference.cc: Add multiple function body.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/Make-lang.in |   1 +
 .../typecheck/rust-hir-trait-reference.cc | 463 ++
 gcc/rust/typecheck/rust-hir-trait-reference.h | 343 ++---
 3 files changed, 510 insertions(+), 297 deletions(-)
 create mode 100644 gcc/rust/typecheck/rust-hir-trait-reference.cc

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index d9bc40945c3..09bbe450bd5 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -123,6 +123,7 @@ GRS_OBJS = \
 rust/rust-tyty-bounds.o \
 rust/rust-hir-type-check-util.o \
 rust/rust-hir-trait-resolve.o \
+rust/rust-hir-trait-reference.o \
 rust/rust-hir-type-check-item.o \
 rust/rust-hir-type-check-type.o \
 rust/rust-hir-type-check-struct.o \
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc 
b/gcc/rust/typecheck/rust-hir-trait-reference.cc
new file mode 100644
index 000..651c55abc82
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -0,0 +1,463 @@
+// 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-hir-trait-reference.h"
+
+namespace Rust {
+namespace Resolver {
+
+std::string
+TraitItemReference::as_string () const
+{
+  return "(" + trait_item_type_as_string (type) + " " + identifier + " " + ")";
+}
+
+bool
+TraitItemReference::is_error () const
+{
+  return type == ERROR;
+}
+
+bool
+TraitItemReference::is_optional () const
+{
+  return optional_flag;
+};
+
+std::string
+TraitItemReference::get_identifier () const
+{
+  return identifier;
+}
+
+TraitItemReference::TraitItemType
+TraitItemReference::get_trait_item_type () const
+{
+  return type;
+}
+
+HIR::TraitItem *
+TraitItemReference::get_hir_trait_item () const
+{
+  return hir_trait_item;
+}
+
+Location
+TraitItemReference::get_locus () const
+{
+  return locus;
+}
+
+const Analysis::NodeMapping
+TraitItemReference::get_mappings () const
+{
+  return hir_trait_item->get_mappings ();
+}
+
+TyTy::BaseType *
+TraitItemReference::get_tyty () const
+{
+  rust_assert (hir_trait_item != nullptr);
+
+  switch (type)
+{
+case CONST:
+  return get_type_from_constant (
+   static_cast (*hir_trait_item));
+  break;
+
+case TYPE:
+  return get_type_from_typealias (
+   static_cast (*hir_trait_item));
+
+case FN:
+  return get_type_from_fn (
+   static_cast (*hir_trait_item));
+  break;
+
+default:
+  return get_error ();
+}
+
+  gcc_unreachable ();
+  return get_error ();
+}
+
+TyTy::ErrorType *
+TraitItemReference::get_error () const
+{
+  return new TyTy::ErrorType (get_mappings ().get_hirid ());
+}
+
+TraitReference::TraitReference (
+  const HIR::Trait *hir_trait_ref, std::vector item_refs,
+  std::vector super_traits,
+  std::vector substs)
+  : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
+super_traits (super_traits)
+{
+  trait_substs.clear ();
+  trait_substs.reserve (substs.size ());
+  for (const auto  : substs)
+trait_substs.push_back (p.clone ());
+}
+
+TraitReference::TraitReference (TraitReference const )
+  : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
+super_traits (other.super_traits)
+{
+  trait_substs.clear ();
+  trait_substs.reserve (other.trait_substs.size ());
+  for (const auto  : other.trait_substs)
+trait_substs.push_back (p.clone ());
+}
+
+TraitReference &
+TraitReference::operator= (TraitReference const )
+{
+  hir_trait_ref = other.hir_trait_ref;
+  item_refs = other.item_refs;
+  super_traits = other.super_traits;
+
+  trait_substs.clear ();
+  trait_substs.reserve (other.trait_substs.size ());
+  for (const auto  : other.trait_substs)
+trait_substs.push_back (p.clone ());
+
+  return *this;
+}
+
+bool
+TraitReference::is_error () const
+{
+  return hir_trait_ref == nullptr;
+}
+
+Location
+TraitReference::get_locus () const
+{
+  return hir_trait_ref->get_locus ();
+}
+
+std::string

[committed 57/88] gccrs: rust-item: include rust-expr.h

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* ast/rust-item.h (class BlockExpr): Remove forward declaration of
class `BlockExpr`.
---
 gcc/rust/ast/rust-item.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 37ed2beabfc..51ed815c700 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -22,11 +22,11 @@
 #include "rust-ast.h"
 #include "rust-path.h"
 #include "rust-common.h"
+#include "rust-expr.h"
 
 namespace Rust {
 namespace AST {
 // forward decls
-class BlockExpr;
 class TypePath;
 
 // TODO: inline?
-- 
2.40.0



[committed 59/88] gccrs: expansion: Add `get_token_slice` to `MacroInvocLexer` class

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* expand/rust-macro-invoc-lexer.cc (MacroInvocLexer::get_token_slice):
Add API to retrieve token slices when lexing macro expansions.
* expand/rust-macro-invoc-lexer.h: Declare `get_token_slice`.
---
 gcc/rust/expand/rust-macro-invoc-lexer.cc | 14 ++
 gcc/rust/expand/rust-macro-invoc-lexer.h  |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/gcc/rust/expand/rust-macro-invoc-lexer.cc 
b/gcc/rust/expand/rust-macro-invoc-lexer.cc
index 8a43d29e0d1..321f0f97a76 100644
--- a/gcc/rust/expand/rust-macro-invoc-lexer.cc
+++ b/gcc/rust/expand/rust-macro-invoc-lexer.cc
@@ -26,4 +26,18 @@ MacroInvocLexer::split_current_token (TokenId new_left 
__attribute__ ((unused)),
   // FIXME
   gcc_unreachable ();
 }
+
+std::vector>
+MacroInvocLexer::get_token_slice (size_t start_idx, size_t end_idx) const
+{
+  std::vector> slice;
+
+  rust_assert (end_idx < token_stream.size ());
+
+  for (size_t i = start_idx; i < end_idx; i++)
+slice.emplace_back (token_stream[i]->clone_token ());
+
+  return slice;
+}
+
 } // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-invoc-lexer.h 
b/gcc/rust/expand/rust-macro-invoc-lexer.h
index a0d30164850..0923c18c84d 100644
--- a/gcc/rust/expand/rust-macro-invoc-lexer.h
+++ b/gcc/rust/expand/rust-macro-invoc-lexer.h
@@ -55,6 +55,9 @@ public:
 
   size_t get_offs () const { return offs; }
 
+  std::vector>
+  get_token_slice (size_t start_idx, size_t end_idx) const;
+
 private:
   size_t offs;
   std::vector> token_stream;
-- 
2.40.0



[committed 81/88] gccrs: Fix up DejaGnu directives in 'rust/compile/issue-1830_{bytes, str}.rs' test cases [#1838]

2023-04-05 Thread arthur . cohen
From: Thomas Schwinge 

'dg-excess-errors' "indicates that the test is expected to fail due to compiler
messages that are not handled by 'dg-error', [etc.]".  It's argument doesn't
specify the message to match but just just a comment.  Here, however, we'd like
to match specific compiler messages, so we should use 'dg-error', etc.  Use the
magic line number zero as the compiler error diagnostic doesn't tell which line
the error occurred on (separate issue to resolve).  This gives us:

-XFAIL: rust/compile/issue-1830_str.rs (test for excess errors)
+PASS: rust/compile/issue-1830_bytes.rs  at line 8 (test for errors, line )
+PASS: rust/compile/issue-1830_bytes.rs (test for excess errors)
-XFAIL: rust/compile/issue-1830_bytes.rs (test for excess errors)
+PASS: rust/compile/issue-1830_str.rs  at line 8 (test for errors, line )
+PASS: rust/compile/issue-1830_str.rs (test for excess errors)

Fix-up for recent GCC/Rust master branch #1838
commit cf9ed4001eec6a22686d19a13f7de8ac94f9cb2a
"testsuite: Add empty string macro test".

gcc/testsuite/
* rust/compile/issue-1830_bytes.rs: Fix up DejaGnu directives.
* rust/compile/issue-1830_str.rs: Likewise.
---
 gcc/testsuite/rust/compile/issue-1830_bytes.rs | 3 ++-
 gcc/testsuite/rust/compile/issue-1830_str.rs   | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/rust/compile/issue-1830_bytes.rs 
b/gcc/testsuite/rust/compile/issue-1830_bytes.rs
index dcc53b73b19..997d4ca0cdc 100644
--- a/gcc/testsuite/rust/compile/issue-1830_bytes.rs
+++ b/gcc/testsuite/rust/compile/issue-1830_bytes.rs
@@ -4,5 +4,6 @@ macro_rules! include_bytes {
 }
 
 fn main() {
-include_bytes!(""); // { dg-excess-errors "Is a directory" }
+include_bytes!("");
+// { dg-error {cannot open filename [^\n\r]+: Is a directory} {} { target 
*-*-* } 0 }
 }
diff --git a/gcc/testsuite/rust/compile/issue-1830_str.rs 
b/gcc/testsuite/rust/compile/issue-1830_str.rs
index 6cf835ba9bd..fcf2dc988d3 100644
--- a/gcc/testsuite/rust/compile/issue-1830_str.rs
+++ b/gcc/testsuite/rust/compile/issue-1830_str.rs
@@ -4,5 +4,6 @@ macro_rules! include_str {
 }
 
 fn main() {
-include_str!(""); // { dg-excess-errors "Is a directory" }
+include_str!("");
+// { dg-error {cannot open filename [^\n\r]+: Is a directory} {} { target 
*-*-* } 0 }
 }
-- 
2.40.0



[committed 58/88] gccrs: parser: Expose parse_macro_invocation as public API

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* parse/rust-parse.h: Move `parse_macro_invocation` to public API.
---
 gcc/rust/parse/rust-parse.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 2f767bb2a53..a4b65c50221 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -150,6 +150,8 @@ public:
   std::unique_ptr parse_token_tree ();
   AST::Attribute parse_attribute_body ();
   AST::AttrVec parse_inner_attributes ();
+  std::unique_ptr
+  parse_macro_invocation (AST::AttrVec outer_attrs);
 
 private:
   void skip_after_semicolon ();
@@ -201,8 +203,6 @@ private:
   parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs);
   std::unique_ptr
   parse_macro_invocation_semi (AST::AttrVec outer_attrs);
-  std::unique_ptr
-  parse_macro_invocation (AST::AttrVec outer_attrs);
   AST::MacroRule parse_macro_rule ();
   AST::MacroMatcher parse_macro_matcher ();
   std::unique_ptr parse_macro_match ();
-- 
2.40.0



[committed 55/88] gccrs: Add general TypeBounds checks

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Existing tests are updated to use libcore copy and clone implementation.

Addresses #1725

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-unify.cc (UnifyRules::go): ensure the bounds are 
checked

gcc/testsuite/ChangeLog:

* rust/compile/torture/intrinsics-4.rs: implement Copy trait
* rust/compile/torture/intrinsics-5.rs: likewise
* rust/execute/torture/atomic_load.rs: likewise
* rust/execute/torture/atomic_store.rs: likewise
* rust/bounds1.rs: New test.
---
 gcc/rust/typecheck/rust-unify.cc  | 11 
 gcc/testsuite/rust/bounds1.rs | 19 ++
 .../rust/compile/torture/intrinsics-4.rs  | 63 +-
 .../rust/compile/torture/intrinsics-5.rs  | 66 ++-
 .../rust/execute/torture/atomic_load.rs   | 59 -
 .../rust/execute/torture/atomic_store.rs  | 59 -
 6 files changed, 271 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/bounds1.rs

diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 072f76133bc..415ffcdc6ea 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -124,6 +124,17 @@ UnifyRules::go ()
   rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (),
  rtype->debug_str ().c_str ());
 
+  // check bounds
+  if (ltype->num_specified_bounds () > 0)
+{
+  if (!ltype->bounds_compatible (*rtype, locus, true))
+   {
+ // already emitted an error
+ emit_error = false;
+ return new TyTy::ErrorType (0);
+   }
+}
+
   switch (ltype->get_kind ())
 {
 case TyTy::INFER:
diff --git a/gcc/testsuite/rust/bounds1.rs b/gcc/testsuite/rust/bounds1.rs
new file mode 100644
index 000..665836088be
--- /dev/null
+++ b/gcc/testsuite/rust/bounds1.rs
@@ -0,0 +1,19 @@
+mod core {
+mod ops {
+#[lang = "add"]
+pub trait Add {
+type Output;
+
+fn add(self, rhs: Rhs) -> Self::Output;
+}
+}
+}
+
+pub fn foo>(a: T) -> i32 {
+// { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { 
target *-*-* } .-1 }
+a + a
+}
+
+pub fn main() {
+foo(123f32);
+}
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs 
b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
index 243d4460089..4e09f1089b0 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs
@@ -1,10 +1,67 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+fn clone() -> Self;
+
+fn clone_from( self, source: ) {
+*self = source.clone()
+}
+}
+
+mod impls {
+use super::Clone;
+
+macro_rules! impl_clone {
+($($t:ty)*) => {
+$(
+impl Clone for $t {
+fn clone() -> Self {
+*self
+}
+}
+)*
+}
+}
+
+impl_clone! {
+usize u8 u16 u32 u64 // u128
+isize i8 i16 i32 i64 // i128
+f32 f64
+bool char
+}
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+// Empty.
+}
+
+mod copy_impls {
+use super::Copy;
+
+macro_rules! impl_copy {
+($($t:ty)*) => {
+$(
+impl Copy for $t {}
+)*
+}
+}
+
+impl_copy! {
+usize u8 u16 u32 u64 // u128
+isize i8 i16 i32 i64 // i128
+f32 f64
+bool char
+}
+}
 
 extern "rust-intrinsic" {
 pub fn atomic_store_seqcst(dst: *mut T, val: T);
 pub fn atomic_store_release(dst: *mut T, val: T);
 pub fn atomic_store_relaxed(dst: *mut T, val: T);
-// pub fn atomic_store_unordered(dst: *mut T, val: T);
+pub fn atomic_store_unordered(dst: *mut T, val: T);
 }
 
 fn main() {
@@ -15,6 +72,6 @@ fn main() {
 atomic_store_seqcst( dst, new_value);
 atomic_store_release( dst, new_value);
 atomic_store_relaxed( dst, new_value);
-// atomic_store_unordered( dst, new_value);
+atomic_store_unordered( dst, new_value);
 }
 }
diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs 
b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
index 7fd84dcd635..ffad0bd3a85 100644
--- a/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
+++ b/gcc/testsuite/rust/compile/torture/intrinsics-5.rs
@@ -1,4 +1,61 @@
-trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "clone"]
+pub trait Clone: Sized {
+fn clone() -> Self;
+
+fn clone_from( self, source: ) {
+*self = source.clone()
+}
+}
+
+mod impls {
+use super::Clone;
+
+macro_rules! impl_clone {
+($($t:ty)*) => {
+$(
+impl Clone for $t {
+fn clone() -> Self {
+*self
+}
+   

[committed 50/88] gccrs: Refactor the type unification code

2023-04-05 Thread arthur . cohen
From: Philip Herron 

This refactors the unification systems to be a consistent interface using
switch statements and simple functions instead of the old clunky visitor
system. This is more maintainable as it is harder to miss cases when we
can take advantages of switch statements.

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* Make-lang.in: update names
* backend/rust-compile-expr.cc (CompileExpr::resolve_method_address):
update to use new interface
* typecheck/rust-coercion.cc 
(TypeCoercionRules::coerce_borrowed_pointer): likewise
* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::unify_site): 
likewise
* typecheck/rust-tyty.cc (BaseType::destructure): likewise
(InferType::unify): removed old unify interface
(ErrorType::unify): likewise
(ADTType::unify): likewise
(TupleType::unify): likewise
(FnType::unify): likewise
(FnPtr::unify): likewise
(ClosureType::unify): likewise
(ArrayType::unify): likewise
(SliceType::unify): likewise
(BoolType::unify): likewise
(IntType::unify): likewise
(UintType::unify): likewise
(FloatType::unify): likewise
(USizeType::unify): likewise
(ISizeType::unify): likewise
(CharType::unify): likewise
(ReferenceType::unify): likewise
(PointerType::unify): likewise
(ParamType::unify): likewise
(StrType::unify): likewise
(NeverType::unify): likewise
(PlaceholderType::unify): likewise
(ProjectionType::unify): likewise
(DynamicObjectType::unify): likewise
* typecheck/rust-tyty.h: update destructure interface
* typecheck/rust-tyty-rules.h: Removed.
* typecheck/rust-unify.cc: New file.
* typecheck/rust-unify.h: New file.

gcc/testsuite/ChangeLog:

* rust/compile/never_type_err1.rs: Moved to...
* rust/compile/never_type1.rs: ...here. It now works
---
 gcc/rust/Make-lang.in |1 +
 gcc/rust/backend/rust-compile-expr.cc |6 +-
 gcc/rust/typecheck/rust-coercion.cc   |6 +-
 .../typecheck/rust-hir-type-check-base.cc |   15 +-
 gcc/rust/typecheck/rust-tyty-rules.h  | 1406 --
 gcc/rust/typecheck/rust-tyty.cc   |  229 +--
 gcc/rust/typecheck/rust-tyty.h|   31 +-
 gcc/rust/typecheck/rust-unify.cc  | 1640 +
 gcc/rust/typecheck/rust-unify.h   |   91 +
 .../{never_type_err1.rs => never_type1.rs}|3 +-
 10 files changed, 1807 insertions(+), 1621 deletions(-)
 delete mode 100644 gcc/rust/typecheck/rust-tyty-rules.h
 create mode 100644 gcc/rust/typecheck/rust-unify.cc
 create mode 100644 gcc/rust/typecheck/rust-unify.h
 rename gcc/testsuite/rust/compile/{never_type_err1.rs => never_type1.rs} (52%)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 4752bb83562..1d2f34d7919 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -134,6 +134,7 @@ GRS_OBJS = \
 rust/rust-hir-path-probe.o \
 rust/rust-coercion.o \
 rust/rust-casts.o \
+rust/rust-unify.o \
 rust/rust-hir-type-check-base.o \
 rust/rust-autoderef.o \
 rust/rust-substitution-mapper.o \
diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index c26f6f440ec..d7945dbf26b 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -26,6 +26,7 @@
 #include "rust-compile-block.h"
 #include "rust-compile-implitem.h"
 #include "rust-constexpr.h"
+#include "rust-unify.h"
 #include "rust-gcc.h"
 
 #include "fold-const.h"
@@ -2006,7 +2007,10 @@ CompileExpr::resolve_method_address (TyTy::FnType 
*fntype, HirId ref,
{
  TyTy::BaseType *infer_impl_call
= candidate_call->infer_substitions (expr_locus);
- monomorphized = infer_impl_call->unify (fntype);
+ monomorphized = Resolver::UnifyRules::Resolve (
+   TyTy::TyWithLocation (infer_impl_call),
+   TyTy::TyWithLocation (fntype), expr_locus, true /* commit */,
+   true /* emit_errors */);
}
 
   return CompileInherentImplItem::Compile (impl_item, ctx, monomorphized);
diff --git a/gcc/rust/typecheck/rust-coercion.cc 
b/gcc/rust/typecheck/rust-coercion.cc
index fdf8eb95a33..bea40840fbf 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -18,6 +18,7 @@
 
 #include "rust-hir-type-check-base.h"
 #include "rust-coercion.h"
+#include "rust-unify.h"
 
 namespace Rust {
 namespace Resolver {
@@ -218,7 +219,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType 
*receiver,
// we might be able to replace this with a can_eq because we default
// back to a final unity anyway
rust_debug ("coerce_borrowed_pointer -- unify");
-   TyTy::BaseType *result = receiver->unify (expected);
+   

[committed 74/88] gccrs: Add new virtual function HIR::ImplItem::get_impl_item_name

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* hir/tree/rust-hir-item.h: implement virtual function
* hir/tree/rust-hir.h: add virtual function
---
 gcc/rust/hir/tree/rust-hir-item.h | 17 -
 gcc/rust/hir/tree/rust-hir.h  |  2 ++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/hir/tree/rust-hir-item.h 
b/gcc/rust/hir/tree/rust-hir-item.h
index f7bf1f879c8..03e1f71abb5 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -1226,6 +1226,11 @@ public:
 
   SelfParam _self_param () { return self; }
 
+  std::string get_impl_item_name () const override final
+  {
+return get_function_name ();
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1345,6 +1350,11 @@ public:
 return get_mappings ();
   };
 
+  std::string get_impl_item_name () const override final
+  {
+return get_new_type_name ();
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2116,7 +2126,7 @@ public:
 
   Expr *get_expr () { return const_expr.get (); }
 
-  std::string get_identifier () { return identifier; }
+  std::string get_identifier () const { return identifier; }
 
   Analysis::NodeMapping get_impl_mappings () const override
   {
@@ -2130,6 +2140,11 @@ public:
 
   ItemKind get_item_kind () const override { return ItemKind::Constant; }
 
+  std::string get_impl_item_name () const override final
+  {
+return get_identifier ();
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 314aafb32d3..28f1f21a6bb 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -839,6 +839,8 @@ public:
 
   virtual ImplItemType get_impl_item_type () const = 0;
 
+  virtual std::string get_impl_item_name () const = 0;
+
 protected:
   // Clone function implementation as pure virtual method
   virtual ImplItem *clone_inherent_impl_item_impl () const = 0;
-- 
2.40.0



[committed 56/88] gccrs: Add support for TuplePattern in let statements

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* hir/tree/rust-hir-pattern.h
(TuplePatternItemsRanged::get_lower_patterns): Add method.
(TuplePatternItemsRanged::get_upper_patterns): Add method.
* backend/rust-compile-pattern.cc
(CompilePatternLet::visit): Implement TuplePattern visitor.
* backend/rust-compile-pattern.h
(CompilePatternLet::visit): Move TuplePattern visitor out of header 
file.

gcc/testsuite/ChangeLog:

* rust/execute/torture/let-pattern-1.rs: New test.

Signed-off-by: Owen Avery 
---
 gcc/rust/backend/rust-compile-pattern.cc  | 87 +++
 gcc/rust/backend/rust-compile-pattern.h   |  7 +-
 gcc/rust/hir/tree/rust-hir-pattern.h  | 18 
 .../rust/execute/torture/let-pattern-1.rs |  4 +
 4 files changed, 110 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/let-pattern-1.rs

diff --git a/gcc/rust/backend/rust-compile-pattern.cc 
b/gcc/rust/backend/rust-compile-pattern.cc
index bad98be44d0..cb4b082f9c8 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -387,5 +387,92 @@ CompilePatternLet::visit (HIR::WildcardPattern )
 }
 }
 
+void
+CompilePatternLet::visit (HIR::TuplePattern )
+{
+  rust_assert (pattern.has_tuple_pattern_items ());
+
+  tree tuple_type = TyTyResolveCompile::compile (ctx, ty);
+  tree init_stmt;
+  Bvariable *tmp_var
+= ctx->get_backend ()->temporary_variable (ctx->peek_fn ().fndecl,
+  NULL_TREE, tuple_type, init_expr,
+  false, pattern.get_locus (),
+  _stmt);
+  tree access_expr
+= ctx->get_backend ()->var_expression (tmp_var, pattern.get_locus ());
+  ctx->add_statement (init_stmt);
+
+  switch (pattern.get_items ()->get_pattern_type ())
+{
+  case HIR::TuplePatternItems::TuplePatternItemType::RANGED: {
+   size_t tuple_idx = 0;
+   auto 
+ = static_cast (*pattern.get_items ());
+
+   auto _lower = items.get_lower_patterns ();
+   auto _upper = items.get_upper_patterns ();
+
+   for (auto  : items_lower)
+ {
+   TyTy::BaseType *ty_sub = nullptr;
+   HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+   bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, _sub);
+   rust_assert (ok);
+
+   tree sub_init = ctx->get_backend ()->struct_field_expression (
+ access_expr, tuple_idx, sub->get_locus ());
+   CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+   rval_locus, ctx);
+   tuple_idx++;
+ }
+
+   rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
+   tuple_idx = static_cast (*ty).num_fields ()
+   - items_upper.size ();
+
+   for (auto  : items_upper)
+ {
+   TyTy::BaseType *ty_sub = nullptr;
+   HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+   bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, _sub);
+   rust_assert (ok);
+
+   tree sub_init = ctx->get_backend ()->struct_field_expression (
+ access_expr, tuple_idx, sub->get_locus ());
+   CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+   rval_locus, ctx);
+   tuple_idx++;
+ }
+
+   return;
+  }
+  case HIR::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+   size_t tuple_idx = 0;
+   auto  = static_cast (
+ *pattern.get_items ());
+
+   for (auto  : items.get_patterns ())
+ {
+   TyTy::BaseType *ty_sub = nullptr;
+   HirId pattern_id = pattern.get_pattern_mappings ().get_hirid ();
+   bool ok = ctx->get_tyctx ()->lookup_type (pattern_id, _sub);
+   rust_assert (ok);
+
+   tree sub_init = ctx->get_backend ()->struct_field_expression (
+ access_expr, tuple_idx, sub->get_locus ());
+   CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
+   rval_locus, ctx);
+   tuple_idx++;
+ }
+
+   return;
+  }
+  default: {
+   gcc_unreachable ();
+  }
+}
+}
+
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-pattern.h 
b/gcc/rust/backend/rust-compile-pattern.h
index ddf5b14265e..8f44b7b5dbb 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -101,6 +101,7 @@ public:
 
   void visit (HIR::IdentifierPattern &) override;
   void visit (HIR::WildcardPattern &) override;
+  void visit (HIR::TuplePattern &) override;
 
   // check for unimplemented Pattern HIR nodes.
   void visit (HIR::LiteralPattern ) override
@@ -146,12 +147,6 @@ public:
   "struct pattern let statements not 

[committed 48/88] gccrs: Add missing param subst callback

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-tyty-subst.cc: add missing callback
---
 gcc/rust/typecheck/rust-tyty-subst.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc 
b/gcc/rust/typecheck/rust-tyty-subst.cc
index 0e181efb359..7f5bb22687d 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -141,6 +141,7 @@ SubstitutionParamMapping::fill_param_ty (
bound.handle_substitions (subst_mappings);
 
   param->set_ty_ref (type.get_ref ());
+  subst_mappings.on_param_subst (*param, arg);
 }
 
   return true;
-- 
2.40.0



[committed 54/88] gccrs: Remove bad error message on checking function arguments

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove error 
message

gcc/testsuite/ChangeLog:

* rust/compile/func3.rs: update test case
---
 gcc/rust/typecheck/rust-tyty-call.cc | 5 -
 gcc/testsuite/rust/compile/func3.rs  | 1 -
 2 files changed, 6 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-call.cc 
b/gcc/rust/typecheck/rust-tyty-call.cc
index 4c6442e2d82..67e2866cbce 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -140,8 +140,6 @@ TypeCheckCallExpr::visit (FnType )
argument->get_locus ());
  if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (argument->get_locus (),
-"Type Resolution failure on parameter");
  return;
}
}
@@ -193,8 +191,6 @@ TypeCheckCallExpr::visit (FnPtr )
TyWithLocation (argument_expr_tyty, arg_locus), argument->get_locus ());
   if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (argument->get_locus (),
-"Type Resolution failure on parameter");
  return;
}
 
@@ -301,7 +297,6 @@ TypeCheckMethodCallExpr::check (FnType )
TyWithLocation (argument_expr_tyty, arg_locus), arg_locus);
   if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
{
- rust_error_at (arg_locus, "Type Resolution failure on parameter");
  return new ErrorType (type.get_ref ());
}
 
diff --git a/gcc/testsuite/rust/compile/func3.rs 
b/gcc/testsuite/rust/compile/func3.rs
index 2a329476118..002e5c90ab5 100644
--- a/gcc/testsuite/rust/compile/func3.rs
+++ b/gcc/testsuite/rust/compile/func3.rs
@@ -5,5 +5,4 @@ fn test(a: i32, b: i32) -> i32 {
 fn main() {
 let a = test(1, true);
 // { dg-error "expected .i32. got .bool." "" { target *-*-* } .-1 }
-// { dg-error "Type Resolution failure on parameter" "" { target *-*-* } 
.-2 }
 }
-- 
2.40.0



[committed 70/88] gccrs: testsuite: Add empty string macro test

2023-04-05 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Add two new tests with empty string for include_str and include_bytes
macros.

gcc/testsuite/ChangeLog:

* rust/compile/issue-1830_bytes.rs: New test.
* rust/compile/issue-1830_str.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/issue-1830_bytes.rs | 8 
 gcc/testsuite/rust/compile/issue-1830_str.rs   | 8 
 2 files changed, 16 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-1830_bytes.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1830_str.rs

diff --git a/gcc/testsuite/rust/compile/issue-1830_bytes.rs 
b/gcc/testsuite/rust/compile/issue-1830_bytes.rs
new file mode 100644
index 000..dcc53b73b19
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1830_bytes.rs
@@ -0,0 +1,8 @@
+#[rustc_builtin_macro]
+macro_rules! include_bytes {
+() => {{}};
+}
+
+fn main() {
+include_bytes!(""); // { dg-excess-errors "Is a directory" }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1830_str.rs 
b/gcc/testsuite/rust/compile/issue-1830_str.rs
new file mode 100644
index 000..6cf835ba9bd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1830_str.rs
@@ -0,0 +1,8 @@
+#[rustc_builtin_macro]
+macro_rules! include_str {
+() => {{}};
+}
+
+fn main() {
+include_str!(""); // { dg-excess-errors "Is a directory" }
+}
-- 
2.40.0



[committed 53/88] gccrs: Fix higher ranked trait bounds computation of self

2023-04-05 Thread arthur . cohen
From: Philip Herron 

This updates the higher ranked trait bounds computation to handle ambigious
cases. When we have a slice for example:

  let slice = [1..3];

This works by reusing the Index operator overload from libcore, so when the
index range of 1..3 is computed, the type system needs to compute what the
types of index are; this works by integer inference variables
Range<> that need to be unified with the impl Index for
Range which computes the real type of usize for the index. This is
fine but what happens when we have the Copy and Clone traits bounds which
have implementations for all the primitive types i8, i16, i32, i64...
which is valid for any integer inference variable so the code prior to this
patch would have grabbed the first impl it would have found and used it
which is incorrect. When we have integer or float inference variables we
need to look for their respective defaults or emit an ambigious type bound
error.

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-reference.h: add const infterface
* typecheck/rust-tyty-subst.cc 
(SubstitutionParamMapping::get_generic_param): make const
(SubstitutionRef::monomorphize): fix issue
* typecheck/rust-tyty-subst.h: constify interface
---
 gcc/rust/typecheck/rust-hir-trait-reference.h |   1 +
 gcc/rust/typecheck/rust-tyty-subst.cc | 107 --
 gcc/rust/typecheck/rust-tyty-subst.h  |   2 +-
 3 files changed, 102 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h 
b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 9b4461b9f18..adb63b468d1 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -496,6 +496,7 @@ public:
   HIR::ImplBlock *get_impl_block () { return impl; }
 
   TyTy::BaseType *get_self () { return self; }
+  const TyTy::BaseType *get_self () const { return self; }
 
   TyTy::BaseType *
   setup_associated_types (const TyTy::BaseType *self,
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc 
b/gcc/rust/typecheck/rust-tyty-subst.cc
index 996bbf2d885..3dfe95873bc 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -65,7 +65,7 @@ SubstitutionParamMapping::get_param_ty () const
 }
 
 const HIR::TypeParam &
-SubstitutionParamMapping::get_generic_param ()
+SubstitutionParamMapping::get_generic_param () const
 {
   return generic;
 }
@@ -892,8 +892,7 @@ SubstitutionRef::monomorphize ()
  // setup any associated type mappings for the specified bonds and this
  // type
  auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
-
- Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
+ std::vector associated_impl_traits;
  for (auto _bound : candidates)
{
  const Resolver::TraitReference *bound_trait_ref
@@ -914,15 +913,109 @@ SubstitutionRef::monomorphize ()
= associated->get_self ()->can_eq (binding, false);
  if (found_trait && found_self)
{
- associated_impl_trait = associated;
- break;
+ associated_impl_traits.push_back (associated);
}
}
}
 
- if (associated_impl_trait != nullptr)
+ if (!associated_impl_traits.empty ())
{
- associated_impl_trait->setup_associated_types (binding, bound);
+ // This code is important when you look at slices for example when
+ // you have a slice such as:
+ //
+ // let slice = [1..3]
+ //
+ // the higher ranked bounds will end up having an Index trait
+ // implementation for Range so we need this code to resolve
+ // that we have an integer inference variable that needs to become
+ // a usize
+ //
+ // The other complicated issue is that we might have an intrinsic
+ // which requires the :Clone or Copy bound but the libcore adds
+ // implementations for all the integral types so when there are
+ // multiple candidates we need to resolve to the default
+ // implementation for that type otherwise its an error for
+ // ambiguous type bounds
+
+ if (associated_impl_traits.size () == 1)
+   {
+ Resolver::AssociatedImplTrait *associate_impl_trait
+   = associated_impl_traits.at (0);
+ associate_impl_trait->setup_associated_types (binding, bound);
+   }
+ else
+   {
+ // if we have a non-general inference variable we need to be
+ // careful about the selection here
+ bool is_infer_var
+   = binding->get_kind () == TyTy::TypeKind::INFER;
+

[committed 45/88] gccrs: Rename header rust-hir-trait-ref.h to rust-hir-trait-reference.h

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-ref.h: Moved to...
* typecheck/rust-hir-trait-reference.h: ...here.
* typecheck/rust-hir-trait-resolve.cc: refactor
* typecheck/rust-hir-trait-resolve.h (RUST_HIR_TRAIT_RESOLVE_H): 
likewise
* typecheck/rust-hir-type-check.h: likewise
* typecheck/rust-tyty.cc: likewise
---
 ...rust-hir-trait-ref.h => rust-hir-trait-reference.h} |  0
 gcc/rust/typecheck/rust-hir-trait-resolve.cc   | 10 ++
 gcc/rust/typecheck/rust-hir-trait-resolve.h|  9 +
 gcc/rust/typecheck/rust-hir-type-check.h   |  2 +-
 gcc/rust/typecheck/rust-tyty.cc|  2 +-
 5 files changed, 13 insertions(+), 10 deletions(-)
 rename gcc/rust/typecheck/{rust-hir-trait-ref.h => rust-hir-trait-reference.h} 
(100%)

diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h 
b/gcc/rust/typecheck/rust-hir-trait-reference.h
similarity index 100%
rename from gcc/rust/typecheck/rust-hir-trait-ref.h
rename to gcc/rust/typecheck/rust-hir-trait-reference.h
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 19f95ca4488..e2d0cf2d7a2 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -22,6 +22,16 @@
 namespace Rust {
 namespace Resolver {
 
+TraitItemReference
+ResolveTraitItemToRef::Resolve (
+  HIR::TraitItem , TyTy::BaseType *self,
+  std::vector substitutions)
+{
+  ResolveTraitItemToRef resolver (self, std::move (substitutions));
+  item.accept_vis (resolver);
+  return std::move (resolver.resolved);
+}
+
 void
 ResolveTraitItemToRef::visit (HIR::TraitItemType )
 {
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h 
b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index ca23d48c3dd..da8e2c0b838 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -19,9 +19,7 @@
 #ifndef RUST_HIR_TRAIT_RESOLVE_H
 #define RUST_HIR_TRAIT_RESOLVE_H
 
-#include "rust-hir-type-check-base.h"
 #include "rust-hir-type-check-type.h"
-#include "rust-hir-trait-ref.h"
 
 namespace Rust {
 namespace Resolver {
@@ -32,12 +30,7 @@ class ResolveTraitItemToRef : public TypeCheckBase,
 public:
   static TraitItemReference
   Resolve (HIR::TraitItem , TyTy::BaseType *self,
-  std::vector substitutions)
-  {
-ResolveTraitItemToRef resolver (self, std::move (substitutions));
-item.accept_vis (resolver);
-return std::move (resolver.resolved);
-  }
+  std::vector substitutions);
 
   void visit (HIR::TraitItemType ) override;
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h 
b/gcc/rust/typecheck/rust-hir-type-check.h
index d1eb750a621..512453947a6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -22,7 +22,7 @@
 #include "rust-hir-full-decls.h"
 #include "rust-hir-map.h"
 #include "rust-tyty.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
 #include "rust-autoderef.h"
 
 namespace Rust {
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 61c02a85c53..4c324c66c16 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -27,7 +27,7 @@
 #include "rust-linemap.h"
 
 #include "rust-substitution-mapper.h"
-#include "rust-hir-trait-ref.h"
+#include "rust-hir-trait-reference.h"
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
 #include "rust-tyty-rules.h"
-- 
2.40.0



[committed 69/88] gccrs: lex: Prevent directories in RAIIFile

2023-04-05 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

RAIIFile constructor was accepting directory filename. This lead to
unattended directory opening in some part of the code (load_file_bytes)
wich resulted in ice. Since RAIIFile are used for the lexer, removing
the ability to open directories with RAIIFile fixes those issues and
prevent future mistakes.

gcc/rust/ChangeLog:

* lex/rust-lex.h: Add file type check.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/lex/rust-lex.h | 28 ++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h
index 2dd60b365ef..50424713df9 100644
--- a/gcc/rust/lex/rust-lex.h
+++ b/gcc/rust/lex/rust-lex.h
@@ -38,13 +38,37 @@ private:
   fclose (file);
   }
 
+  static bool allowed_filetype (const struct stat )
+  {
+// The file could be either
+// - a regular file
+// - a char device (/dev/null...)
+return S_ISREG (statbuf.st_mode) || S_ISCHR (statbuf.st_mode);
+  }
+
 public:
   RAIIFile (const char *filename) : filename (filename)
   {
 if (strcmp (filename, "-") == 0)
-  file = stdin;
+  {
+   file = stdin;
+  }
 else
-  file = fopen (filename, "r");
+  {
+   struct stat statbuf;
+   if (!(file = fopen (filename, "r")))
+ {
+   return;
+ }
+
+   if (-1 == fstat (fileno (file), )
+   || !allowed_filetype (statbuf))
+ {
+   fclose (file);
+   file = nullptr;
+   errno = EISDIR;
+ }
+  }
   }
 
   /**
-- 
2.40.0



[committed 43/88] gccrs: Refactor all code out of the rust-tyty.h header

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-hir-type-check.h: refactor
* typecheck/rust-tyctx.cc (TypeCheckContext::iterate): refactor
(TypeCheckContext::have_loop_context): likewise
(TypeCheckContext::push_new_loop_context): likewise
(TypeCheckContext::push_new_while_loop_context): likewise
(TypeCheckContext::peek_loop_context): likewise
(TypeCheckContext::pop_loop_context): likewise
(TypeCheckContext::swap_head_loop_context): likewise
(TypeCheckContext::insert_trait_reference): likewise
(TypeCheckContext::lookup_trait_reference): likewise
(TypeCheckContext::insert_receiver): likewise
(TypeCheckContext::lookup_receiver): likewise
(TypeCheckContext::insert_associated_type_mapping): likewise
(TypeCheckContext::clear_associated_type_mapping): likewise
(TypeCheckContext::lookup_associated_type_mapping): likewise
(TypeCheckContext::insert_variant_definition): likewise
(TypeCheckContext::lookup_variant_definition): likewise
(TypeCheckContext::insert_operator_overload): likewise
(TypeCheckContext::lookup_operator_overload): likewise
(TypeCheckContext::insert_unconstrained_check_marker): likewise
(TypeCheckContext::have_checked_for_unconstrained): likewise
(TypeCheckContext::insert_resolved_predicate): likewise
(TypeCheckContext::lookup_predicate): likewise
(TypeCheckContext::insert_query): likewise
(TypeCheckContext::query_completed): likewise
(TypeCheckContext::query_in_progress): likewise
(TypeCheckContext::insert_trait_query): likewise
(TypeCheckContext::trait_query_completed): likewise
(TypeCheckContext::trait_query_in_progress): likewise
(TypeCheckContextItem::Item::Item): likewise
(TypeCheckContextItem::TypeCheckContextItem): likewise
(TypeCheckContextItem::get_item): likewise
(TypeCheckContextItem::get_impl_item): likewise
(TypeCheckContextItem::get_trait_item): likewise
(TypeCheckContextItem::get_type): likewise
* typecheck/rust-tyty.cc (StructFieldType::StructFieldType): likewise
(StructFieldType::get_ref): likewise
(StructFieldType::get_name): likewise
(StructFieldType::get_field_type): likewise
(StructFieldType::set_field_type): likewise
(StructFieldType::is_concrete): likewise
(StructFieldType::debug): likewise
(StructFieldType::get_locus): likewise
(VariantDef::variant_type_string): likewise
(VariantDef::VariantDef): likewise
(VariantDef::operator=): likewise
(VariantDef::get_error_node): likewise
(VariantDef::is_error): likewise
(VariantDef::get_id): likewise
(VariantDef::get_defid): likewise
(VariantDef::get_variant_type): likewise
(VariantDef::is_data_variant): likewise
(VariantDef::is_dataless_variant): likewise
(VariantDef::get_identifier): likewise
(VariantDef::num_fields): likewise
(VariantDef::get_field_at_index): likewise
(VariantDef::get_fields): likewise
(VariantDef::lookup_field): likewise
(VariantDef::get_discriminant): likewise
(VariantDef::as_string): likewise
(VariantDef::is_equal): likewise
(VariantDef::clone): likewise
(VariantDef::monomorphized_clone): likewise
(VariantDef::get_ident): likewise
(TupleType::TupleType): likewise
(TupleType::get_unit_type): likewise
(TupleType::is_unit): likewise
(TupleType::num_fields): likewise
(TupleType::is_concrete): likewise
(TupleType::get_fields): likewise
(BoolType::BoolType): likewise
(BoolType::get_name): likewise
(BoolType::is_concrete): likewise
(IntType::IntType): likewise
(IntType::get_name): likewise
(IntType::get_int_kind): likewise
(IntType::is_concrete): likewise
(UintType::UintType): likewise
(UintType::get_name): likewise
(UintType::get_uint_kind): likewise
(UintType::is_concrete): likewise
(FloatType::FloatType): likewise
(FloatType::get_name): likewise
(FloatType::get_float_kind): likewise
(FloatType::is_concrete): likewise
(USizeType::USizeType): likewise
(USizeType::get_name): likewise
(USizeType::is_concrete): likewise
(ISizeType::ISizeType): likewise
(ISizeType::get_name): likewise
(ISizeType::is_concrete): likewise
(CharType::CharType): likewise
(CharType::is_concrete): likewise
(CharType::get_name): likewise
(ReferenceType::ReferenceType): likewise
(ReferenceType::is_concrete): likewise
(ReferenceType::mutability): likewise
(ReferenceType::is_mutable): likewise
(ReferenceType::is_dyn_object): 

[committed 39/88] gccrs: Refactor all substitution mapper code implementation into its own CC file

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-substitution-mapper.cc (SubstMapper::SubstMapper): 
refactor
(SubstMapper::Resolve): likewise
(SubstMapper::InferSubst): likewise
(SubstMapper::have_generic_args): likewise
(SubstMapper::visit): likewise
(SubstMapperInternal::visit): likewise
(SubstMapperFromExisting::SubstMapperFromExisting): likewise
(SubstMapperFromExisting::Resolve): likewise
(SubstMapperFromExisting::visit): likewise
(GetUsedSubstArgs::GetUsedSubstArgs): likewise
(GetUsedSubstArgs::From): likewise
(GetUsedSubstArgs::visit): likewise
* typecheck/rust-substitution-mapper.h: refactor
* typecheck/rust-tyty-subst.cc 
(SubstitutionParamMapping::get_generic_param): likewise
---
 .../typecheck/rust-substitution-mapper.cc | 343 ++
 gcc/rust/typecheck/rust-substitution-mapper.h | 286 +++
 gcc/rust/typecheck/rust-tyty-subst.cc |   2 +-
 3 files changed, 387 insertions(+), 244 deletions(-)

diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc 
b/gcc/rust/typecheck/rust-substitution-mapper.cc
index e1d988818bb..dc93857e60f 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -22,6 +22,116 @@
 namespace Rust {
 namespace Resolver {
 
+SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics, Location 
locus)
+  : resolved (new TyTy::ErrorType (ref)), generics (generics), locus (locus)
+{}
+
+TyTy::BaseType *
+SubstMapper::Resolve (TyTy::BaseType *base, Location locus,
+ HIR::GenericArgs *generics)
+{
+  SubstMapper mapper (base->get_ref (), generics, locus);
+  base->accept_vis (mapper);
+  rust_assert (mapper.resolved != nullptr);
+  return mapper.resolved;
+}
+
+TyTy::BaseType *
+SubstMapper::InferSubst (TyTy::BaseType *base, Location locus)
+{
+  return SubstMapper::Resolve (base, locus, nullptr);
+}
+
+bool
+SubstMapper::have_generic_args () const
+{
+  return generics != nullptr;
+}
+
+void
+SubstMapper::visit (TyTy::FnType )
+{
+  TyTy::FnType *concrete = nullptr;
+  if (!have_generic_args ())
+{
+  TyTy::BaseType *substs = type.infer_substitions (locus);
+  rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
+  concrete = static_cast (substs);
+}
+  else
+{
+  TyTy::SubstitutionArgumentMappings mappings
+   = type.get_mappings_from_generic_args (*generics);
+  if (mappings.is_error ())
+   return;
+
+  concrete = type.handle_substitions (mappings);
+}
+
+  if (concrete != nullptr)
+resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::ADTType )
+{
+  TyTy::ADTType *concrete = nullptr;
+  if (!have_generic_args ())
+{
+  TyTy::BaseType *substs = type.infer_substitions (locus);
+  rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
+  concrete = static_cast (substs);
+}
+  else
+{
+  TyTy::SubstitutionArgumentMappings mappings
+   = type.get_mappings_from_generic_args (*generics);
+  if (mappings.is_error ())
+   return;
+
+  concrete = type.handle_substitions (mappings);
+}
+
+  if (concrete != nullptr)
+resolved = concrete;
+}
+
+void
+SubstMapper::visit (TyTy::PlaceholderType )
+{
+  rust_assert (type.can_resolve ());
+  resolved = SubstMapper::Resolve (type.resolve (), locus, generics);
+}
+
+void
+SubstMapper::visit (TyTy::ProjectionType )
+{
+  TyTy::ProjectionType *concrete = nullptr;
+  if (!have_generic_args ())
+{
+  TyTy::BaseType *substs = type.infer_substitions (locus);
+  rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
+  concrete = static_cast (substs);
+}
+  else
+{
+  TyTy::SubstitutionArgumentMappings mappings
+   = type.get_mappings_from_generic_args (*generics);
+  if (mappings.is_error ())
+   return;
+
+  concrete = type.handle_substitions (mappings);
+}
+
+  if (concrete != nullptr)
+resolved = concrete;
+}
+
+SubstMapperInternal::SubstMapperInternal (
+  HirId ref, TyTy::SubstitutionArgumentMappings )
+  : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
+{}
+
 TyTy::BaseType *
 SubstMapperInternal::Resolve (TyTy::BaseType *base,
  TyTy::SubstitutionArgumentMappings )
@@ -73,5 +183,238 @@ SubstMapperInternal::mappings_are_bound (
   return false;
 }
 
+void
+SubstMapperInternal::visit (TyTy::FnType )
+{
+  TyTy::SubstitutionArgumentMappings adjusted
+= type.adjust_mappings_for_this (mappings);
+  if (adjusted.is_error ())
+return;
+
+  TyTy::BaseType *concrete = type.handle_substitions (adjusted);
+  if (concrete != nullptr)
+resolved = concrete;
+}
+
+void
+SubstMapperInternal::visit (TyTy::ADTType )
+{
+  TyTy::SubstitutionArgumentMappings adjusted
+= type.adjust_mappings_for_this (mappings);
+  if (adjusted.is_error ())
+return;
+
+  

[committed 49/88] gccrs: Remove monomorphization hack to setup possible associated types

2023-04-05 Thread arthur . cohen
From: Philip Herron 

During CallExpr argument type checking we may be calling a default
implementation of a trait function this will require any possible
associated types to be resolved and setup. This monomoprhization call does
this but it will premtivly do extra unification of types which will throw
off type checking later on. This fix is required for my work into type
bounds checking.

Fixes #1773

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-reference.h: change interface to return self
* typecheck/rust-hir-trait-resolve.cc: likewise
* typecheck/rust-hir-type-check-path.cc 
(TypeCheckExpr::resolve_segments): likewise
* typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): remove 
monomorphization hack

gcc/testsuite/ChangeLog:

* rust/compile/issue-1773.rs: New test.
---
 gcc/rust/typecheck/rust-hir-trait-reference.h |  5 +--
 gcc/rust/typecheck/rust-hir-trait-resolve.cc  | 10 +++---
 .../typecheck/rust-hir-type-check-path.cc | 36 ++-
 gcc/rust/typecheck/rust-tyty-call.cc  |  1 -
 gcc/testsuite/rust/compile/issue-1773.rs  | 20 +++
 5 files changed, 56 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-1773.rs

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h 
b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 0df35265959..9b4461b9f18 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -497,8 +497,9 @@ public:
 
   TyTy::BaseType *get_self () { return self; }
 
-  void setup_associated_types (const TyTy::BaseType *self,
-  const TyTy::TypeBoundPredicate );
+  TyTy::BaseType *
+  setup_associated_types (const TyTy::BaseType *self,
+ const TyTy::TypeBoundPredicate );
 
   void reset_associated_types ();
 
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index e2d0cf2d7a2..6e23093eceb 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -377,13 +377,10 @@ TraitItemReference::associated_type_reset () const
   placeholder->clear_associated_type ();
 }
 
-void
+TyTy::BaseType *
 AssociatedImplTrait::setup_associated_types (
   const TyTy::BaseType *self, const TyTy::TypeBoundPredicate )
 {
-  if (!bound.contains_associated_types ())
-return;
-
   // compute the constrained impl block generic arguments based on self and the
   // higher ranked trait bound
   TyTy::BaseType *receiver = self->clone ();
@@ -486,6 +483,7 @@ AssociatedImplTrait::setup_associated_types (
 TyTy::TyWithLocation (receiver), TyTy::TyWithLocation (impl_self_infer),
 impl_predicate.get_locus ());
   rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+  TyTy::BaseType *self_result = result;
 
   // unify the bounds arguments
   std::vector hrtb_bound_arguments;
@@ -500,7 +498,7 @@ AssociatedImplTrait::setup_associated_types (
 }
 
   if (impl_trait_predicate_args.size () != hrtb_bound_arguments.size ())
-return;
+return self_result;
 
   for (size_t i = 0; i < impl_trait_predicate_args.size (); i++)
 {
@@ -554,6 +552,8 @@ AssociatedImplTrait::setup_associated_types (
 resolved_trait_item->associated_type_set (substituted);
   });
   iter.go ();
+
+  return self_result;
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc 
b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 6f1fd416c19..9d9b2949944 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -379,16 +379,36 @@ TypeCheckExpr::resolve_segments (NodeId 
root_resolved_node_id,
 
   if (associated_impl_block != nullptr)
{
- // get the type of the parent Self
- HirId impl_ty_id
-   = associated_impl_block->get_type ()->get_mappings ().get_hirid ();
+ // associated types
+ HirId impl_block_id
+   = associated_impl_block->get_mappings ().get_hirid ();
+
+ AssociatedImplTrait *associated = nullptr;
+ bool found_impl_trait
+   = context->lookup_associated_trait_impl (impl_block_id,
+);
  TyTy::BaseType *impl_block_ty = nullptr;
- bool ok = query_type (impl_ty_id, _block_ty);
- rust_assert (ok);
+ if (found_impl_trait)
+   {
+ TyTy::TypeBoundPredicate predicate (*associated->get_trait (),
+ seg.get_locus ());
+ impl_block_ty
+   = associated->setup_associated_types (prev_segment, predicate);
+   }
+ else
+   {
+ // get the type of the parent Self
+ HirId impl_ty_id = associated_impl_block->get_type ()
+  ->get_mappings ()
+ 

[committed 66/88] gccrs: Add variadic argument type checking

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* typecheck/rust-tyty-call.cc
(TypeCheckCallExpr::visit): Add variadic argument type checking.
(TypeCheckCallExpr::visit): Fix comment spelling ("varadic").

gcc/testsuite/ChangeLog:

* rust/execute/torture/overflow1.rs: Fix test.

Signed-off-by: Owen Avery 
---
 gcc/rust/typecheck/rust-tyty-call.cc  | 56 ++-
 .../rust/execute/torture/overflow1.rs |  2 +-
 2 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-call.cc 
b/gcc/rust/typecheck/rust-tyty-call.cc
index 67e2866cbce..f0846ae25ec 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -122,7 +122,7 @@ TypeCheckCallExpr::visit (FnType )
  return;
}
 
-  // it might be a varadic function
+  // it might be a variadic function
   if (i < type.num_params ())
{
  auto fnparam = type.param_at (i);
@@ -143,6 +143,60 @@ TypeCheckCallExpr::visit (FnType )
  return;
}
}
+  else
+   {
+ switch (argument_expr_tyty->get_kind ())
+   {
+   case TyTy::TypeKind::ERROR:
+ return;
+ case TyTy::TypeKind::INT: {
+   auto _ty
+ = static_cast (*argument_expr_tyty);
+   if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8)
+   || (int_ty.get_int_kind () == TyTy::IntType::IntKind::I16))
+ {
+   rust_error_at (arg_locus,
+  "expected % variadic argument");
+   return;
+ }
+   break;
+ }
+ case TyTy::TypeKind::UINT: {
+   auto _ty
+ = static_cast (*argument_expr_tyty);
+   if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8)
+   || (uint_ty.get_uint_kind ()
+   == TyTy::UintType::UintKind::U16))
+ {
+   rust_error_at (arg_locus,
+  "expected % variadic argument");
+   return;
+ }
+   break;
+ }
+ case TyTy::TypeKind::FLOAT: {
+   if (static_cast (*argument_expr_tyty)
+ .get_float_kind ()
+   == TyTy::FloatType::FloatKind::F32)
+ {
+   rust_error_at (arg_locus,
+  "expected % variadic argument");
+   return;
+ }
+   break;
+ }
+   case TyTy::TypeKind::BOOL:
+ rust_error_at (arg_locus, "expected % variadic argument");
+ return;
+   case TyTy::TypeKind::FNDEF:
+ rust_error_at (arg_locus,
+"unexpected function definition type as variadic "
+"argument - cast to function pointer");
+ return;
+   default:
+ break;
+   }
+   }
 
   i++;
 }
diff --git a/gcc/testsuite/rust/execute/torture/overflow1.rs 
b/gcc/testsuite/rust/execute/torture/overflow1.rs
index 57a0824ce0a..c4ccab1a133 100644
--- a/gcc/testsuite/rust/execute/torture/overflow1.rs
+++ b/gcc/testsuite/rust/execute/torture/overflow1.rs
@@ -16,5 +16,5 @@ fn main() {
 // { dg-final { scan-tree-dump ADD_OVERFLOW original } }
 let c = a + b;
 
-unsafe { printf("%d\n\0" as *const str as *const i8, c) }
+unsafe { printf("%d\n\0" as *const str as *const i8, c as i32) }
 }
-- 
2.40.0



[committed 47/88] gccrs: Clear the substitution callbacks when copying ArgumentMappings

2023-04-05 Thread arthur . cohen
From: Philip Herron 

When we set the callback on substitutions this is not safe to be copied
around since we store the used argument mappings and can reuse them in
different contexts. This clears the callback on copy's to make it safer.

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-tyty-subst.cc: update copy constructors
---
 gcc/rust/typecheck/rust-tyty-subst.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc 
b/gcc/rust/typecheck/rust-tyty-subst.cc
index a5d738744fc..0e181efb359 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -241,7 +241,7 @@ SubstitutionArgumentMappings::SubstitutionArgumentMappings (
 SubstitutionArgumentMappings::SubstitutionArgumentMappings (
   const SubstitutionArgumentMappings )
   : mappings (other.mappings), binding_args (other.binding_args),
-locus (other.locus), param_subst_cb (other.param_subst_cb),
+locus (other.locus), param_subst_cb (nullptr),
 trait_item_flag (other.trait_item_flag)
 {}
 
@@ -252,7 +252,7 @@ SubstitutionArgumentMappings::operator= (
   mappings = other.mappings;
   binding_args = other.binding_args;
   locus = other.locus;
-  param_subst_cb = other.param_subst_cb;
+  param_subst_cb = nullptr;
   trait_item_flag = other.trait_item_flag;
 
   return *this;
-- 
2.40.0



[committed 46/88] gccrs: Refactor handle_substitutions to take a reference

2023-04-05 Thread arthur . cohen
From: Philip Herron 

This patch changes the recusive substitution code to take a reference
instead of a copy. This is important as the callback field is going to be
made non-copyable in a future patch and this pipeline is for recursive
substitutions so its ok to reuse the same mappings here.

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-tyty-bounds.cc: refactor to take a reference
* typecheck/rust-tyty-subst.cc: likewise
(SubstitutionRef::get_substitution_arguments): likewise
(SubstitutionRef::infer_substitions): likewise
* typecheck/rust-tyty-subst.h: likewise
* typecheck/rust-tyty.cc (ADTType::handle_substitions): likewise
(TupleType::handle_substitions): likewise
(FnType::handle_substitions): likewise
(ClosureType::handle_substitions): likewise
(ArrayType::handle_substitions): likewise
(SliceType::handle_substitions): likewise
(ReferenceType::handle_substitions): likewise
(PointerType::handle_substitions): likewise
(ParamType::handle_substitions): likewise
(ProjectionType::handle_substitions): likewise
* typecheck/rust-tyty.h: likewise
---
 gcc/rust/typecheck/rust-tyty-bounds.cc |  2 +-
 gcc/rust/typecheck/rust-tyty-subst.cc  | 10 --
 gcc/rust/typecheck/rust-tyty-subst.h   |  5 +++--
 gcc/rust/typecheck/rust-tyty.cc| 21 +++--
 gcc/rust/typecheck/rust-tyty.h | 22 +++---
 5 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc 
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index e7eb9a760f5..b14e0c68e5a 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -444,7 +444,7 @@ TypeBoundPredicate::is_error () const
 
 BaseType *
 TypeBoundPredicate::handle_substitions (
-  SubstitutionArgumentMappings subst_mappings)
+  SubstitutionArgumentMappings _mappings)
 {
   for (auto  : get_substs ())
 {
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc 
b/gcc/rust/typecheck/rust-tyty-subst.cc
index aceed29ff03..a5d738744fc 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -488,7 +488,13 @@ SubstitutionRef::was_substituted () const
   return !needs_substitution ();
 }
 
-SubstitutionArgumentMappings
+SubstitutionArgumentMappings &
+SubstitutionRef::get_substitution_arguments ()
+{
+  return used_arguments;
+}
+
+const SubstitutionArgumentMappings &
 SubstitutionRef::get_substitution_arguments () const
 {
   return used_arguments;
@@ -697,7 +703,7 @@ SubstitutionRef::infer_substitions (Location locus)
   SubstitutionArgumentMappings infer_arguments (std::move (args),
{} /* binding_arguments */,
locus);
-  return handle_substitions (std::move (infer_arguments));
+  return handle_substitions (infer_arguments);
 }
 
 SubstitutionArgumentMappings
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h 
b/gcc/rust/typecheck/rust-tyty-subst.h
index 4d09a3013e7..039eb36589e 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -199,7 +199,8 @@ public:
 
   bool was_substituted () const;
 
-  SubstitutionArgumentMappings get_substitution_arguments () const;
+  SubstitutionArgumentMappings _substitution_arguments ();
+  const SubstitutionArgumentMappings _substitution_arguments () const;
 
   // this is the count of type params that are not substituted fuly
   size_t num_required_substitutions () const;
@@ -301,7 +302,7 @@ public:
   bool monomorphize ();
 
   // TODO comment
-  virtual BaseType *handle_substitions (SubstitutionArgumentMappings mappings)
+  virtual BaseType *handle_substitions (SubstitutionArgumentMappings )
 = 0;
 
   SubstitutionArgumentMappings get_used_arguments () const;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 4c324c66c16..a3271eb0d1a 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -1148,7 +1148,7 @@ handle_substitions (SubstitutionArgumentMappings 
_mappings,
 }
 
 ADTType *
-ADTType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+ADTType::handle_substitions (SubstitutionArgumentMappings _mappings)
 {
   ADTType *adt = static_cast (clone ());
   adt->set_ty_ref (mappings->get_next_hir_id ());
@@ -1333,7 +1333,7 @@ TupleType::monomorphized_clone () const
 }
 
 TupleType *
-TupleType::handle_substitions (SubstitutionArgumentMappings mappings)
+TupleType::handle_substitions (SubstitutionArgumentMappings )
 {
   auto mappings_table = Analysis::Mappings::get ();
 
@@ -1474,7 +1474,7 @@ FnType::monomorphized_clone () const
 }
 
 FnType *
-FnType::handle_substitions (SubstitutionArgumentMappings subst_mappings)
+FnType::handle_substitions (SubstitutionArgumentMappings _mappings)
 {
   FnType *fn = static_cast (clone ());
   

[committed 61/88] gccrs: expander: Add documentation for `expand_eager_invocations`

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* expand/rust-macro-expand.cc (MacroExpander::expand_eager_invocations):
Add documentation explaining the algorithm.
---
 gcc/rust/expand/rust-macro-expand.cc | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/expand/rust-macro-expand.cc 
b/gcc/rust/expand/rust-macro-expand.cc
index 0ff849dc85d..4b494490424 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -197,17 +197,25 @@ MacroExpander::expand_eager_invocations 
(AST::MacroInvocation )
   auto start = kv.first.first;
   auto end = kv.first.second;
 
-  // TODO: Add doc
+  // We're now going to re-add the tokens to the invocation's token tree.
+  // 1. Basically, what we want to do is insert all tokens up until the
+  //beginning of the macro invocation (start).
+  // 2. Then, we'll insert all of the tokens resulting from the macro
+  //expansion: These are in `new_tokens`.
+  // 3. Finally, we'll do that again from
+  //the end of macro and go back to 1.
+
   for (size_t i = current_idx; i < start; i++)
new_stream.emplace_back (stream[i]->clone_token ());
 
-  // TODO: Add doc
   for (auto  : new_tokens)
new_stream.emplace_back (tok->clone_token ());
 
   current_idx = end;
 }
-  // TODO: Add doc
+
+  // Once all of that is done, we copy the last remaining tokens from the
+  // original stream
   for (size_t i = current_idx; i < stream.size (); i++)
 new_stream.emplace_back (stream[i]->clone_token ());
 
-- 
2.40.0



[committed 41/88] gccrs: Refactor PathProbe into cc file

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-hir-path-probe.cc (PathProbeType::PathProbeType): 
refactor
(PathProbeType::Probe): likewise
(PathProbeType::visit): likewise
(PathProbeType::process_enum_item_for_candiates): likewise
(PathProbeType::process_impl_items_for_candidates): likewise
(PathProbeType::is_reciever_generic): likewise
(PathProbeImplTrait::PathProbeImplTrait): likewise
(PathProbeImplTrait::Probe): likewise
(PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise
* typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise
* typecheck/rust-hir-trait-resolve.cc
(PathProbeImplTrait::process_trait_impl_items_for_candidates): likewise
---
 gcc/rust/typecheck/rust-hir-path-probe.cc| 344 +++
 gcc/rust/typecheck/rust-hir-path-probe.h | 302 +---
 gcc/rust/typecheck/rust-hir-trait-resolve.cc |  22 --
 3 files changed, 360 insertions(+), 308 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc 
b/gcc/rust/typecheck/rust-hir-path-probe.cc
index cb3270d3623..06d8920d2eb 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -18,10 +18,168 @@
 
 #include "rust-hir-path-probe.h"
 #include "rust-hir-type-check-item.h"
+#include "rust-hir-trait-resolve.h"
 
 namespace Rust {
 namespace Resolver {
 
+// PathProbeType
+
+PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment ,
+ DefId specific_trait_id)
+  : TypeCheckBase (), receiver (receiver), search (query),
+current_impl (nullptr), specific_trait_id (specific_trait_id)
+{}
+
+std::set
+PathProbeType::Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment _name,
+ bool probe_impls, bool probe_bounds,
+ bool ignore_mandatory_trait_items,
+ DefId specific_trait_id)
+{
+  PathProbeType probe (receiver, segment_name, specific_trait_id);
+  if (probe_impls)
+{
+  if (receiver->get_kind () == TyTy::TypeKind::ADT)
+   {
+ const TyTy::ADTType *adt
+   = static_cast (receiver);
+ if (adt->is_enum ())
+   probe.process_enum_item_for_candiates (adt);
+   }
+
+  probe.process_impl_items_for_candidates ();
+}
+
+  if (!probe_bounds)
+return probe.candidates;
+
+  if (!probe.is_reciever_generic ())
+{
+  std::vector> probed_bounds
+   = TypeBoundsProbe::Probe (receiver);
+  for (auto  : probed_bounds)
+   {
+ const TraitReference *trait_ref = candidate.first;
+ if (specific_trait_id != UNKNOWN_DEFID)
+   {
+ if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+   continue;
+   }
+
+ HIR::ImplBlock *impl = candidate.second;
+ probe.process_associated_trait_for_candidates (
+   trait_ref, impl, ignore_mandatory_trait_items);
+   }
+}
+
+  for (const TyTy::TypeBoundPredicate  :
+   receiver->get_specified_bounds ())
+{
+  const TraitReference *trait_ref = predicate.get ();
+  if (specific_trait_id != UNKNOWN_DEFID)
+   {
+ if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
+   continue;
+   }
+
+  probe.process_predicate_for_candidates (predicate,
+ ignore_mandatory_trait_items);
+}
+
+  return probe.candidates;
+}
+
+void
+PathProbeType::visit (HIR::TypeAlias )
+{
+  Identifier name = alias.get_new_type_name ();
+  if (search.as_string ().compare (name) == 0)
+{
+  HirId tyid = alias.get_mappings ().get_hirid ();
+  TyTy::BaseType *ty = nullptr;
+  bool ok = query_type (tyid, );
+  rust_assert (ok);
+
+  PathProbeCandidate::ImplItemCandidate impl_item_candidate{,
+   current_impl};
+  PathProbeCandidate candidate{
+   PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
+   alias.get_locus (), impl_item_candidate};
+  candidates.insert (std::move (candidate));
+}
+}
+
+void
+PathProbeType::visit (HIR::ConstantItem )
+{
+  Identifier name = constant.get_identifier ();
+  if (search.as_string ().compare (name) == 0)
+{
+  HirId tyid = constant.get_mappings ().get_hirid ();
+  TyTy::BaseType *ty = nullptr;
+  bool ok = query_type (tyid, );
+  rust_assert (ok);
+
+  PathProbeCandidate::ImplItemCandidate impl_item_candidate{,
+   current_impl};
+  PathProbeCandidate candidate{
+   PathProbeCandidate::CandidateType::IMPL_CONST, ty,
+   constant.get_locus (), impl_item_candidate};
+  candidates.insert (std::move (candidate));
+}
+}

[committed 44/88] gccrs: Rename rust-tyctx.cc to rust-typecheck-context.cc

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* Make-lang.in: update name
* typecheck/rust-tyctx.cc: Moved to...
* typecheck/rust-typecheck-context.cc: ...here.
---
 gcc/rust/Make-lang.in   | 2 +-
 gcc/rust/typecheck/{rust-tyctx.cc => rust-typecheck-context.cc} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename gcc/rust/typecheck/{rust-tyctx.cc => rust-typecheck-context.cc} (100%)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 5e173f1d2dc..4752bb83562 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -118,7 +118,7 @@ GRS_OBJS = \
 rust/rust-tyty-util.o \
 rust/rust-tyty-call.o \
 rust/rust-tyty-subst.o \
-rust/rust-tyctx.o \
+rust/rust-typecheck-context.o \
 rust/rust-tyty-bounds.o \
 rust/rust-hir-type-check-util.o \
 rust/rust-hir-trait-resolve.o \
diff --git a/gcc/rust/typecheck/rust-tyctx.cc 
b/gcc/rust/typecheck/rust-typecheck-context.cc
similarity index 100%
rename from gcc/rust/typecheck/rust-tyctx.cc
rename to gcc/rust/typecheck/rust-typecheck-context.cc
-- 
2.40.0



[committed 42/88] gccrs: Refactor PathProbeType code into CC file

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-hir-path-probe.cc 
(PathProbeCandidate::Candidate::Candidate): refactor
(PathProbeCandidate::PathProbeCandidate): likewise
(PathProbeCandidate::as_string): likewise
(PathProbeCandidate::is_enum_candidate): likewise
(PathProbeCandidate::is_impl_candidate): likewise
(PathProbeCandidate::is_trait_candidate): likewise
(PathProbeCandidate::is_full_trait_item_candidate): likewise
(PathProbeCandidate::get_error): likewise
(PathProbeCandidate::is_error): likewise
(PathProbeCandidate::get_defid): likewise
(PathProbeCandidate::operator<): likewise
* typecheck/rust-hir-path-probe.h (struct PathProbeCandidate): likewise
---
 gcc/rust/typecheck/rust-hir-path-probe.cc | 109 ++
 gcc/rust/typecheck/rust-hir-path-probe.h  |  82 +++-
 2 files changed, 124 insertions(+), 67 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc 
b/gcc/rust/typecheck/rust-hir-path-probe.cc
index 06d8920d2eb..be89ceb8645 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -23,6 +23,115 @@
 namespace Rust {
 namespace Resolver {
 
+// PathProbeCandidate
+
+PathProbeCandidate::Candidate::Candidate (EnumItemCandidate enum_field)
+  : enum_field (enum_field)
+{}
+
+PathProbeCandidate::Candidate::Candidate (ImplItemCandidate impl) : impl (impl)
+{}
+
+PathProbeCandidate::Candidate::Candidate (TraitItemCandidate trait)
+  : trait (trait)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+   Location locus,
+   EnumItemCandidate enum_field)
+  : type (type), ty (ty), locus (locus), item (enum_field)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+   Location locus, ImplItemCandidate impl)
+  : type (type), ty (ty), locus (locus), item (impl)
+{}
+
+PathProbeCandidate::PathProbeCandidate (CandidateType type, TyTy::BaseType *ty,
+   Location locus,
+   TraitItemCandidate trait)
+  : type (type), ty (ty), locus (locus), item (trait)
+{}
+
+std::string
+PathProbeCandidate::as_string () const
+{
+  return "PathProbe candidate TODO - as_string";
+}
+
+bool
+PathProbeCandidate::is_enum_candidate () const
+{
+  return type == ENUM_VARIANT;
+}
+
+bool
+PathProbeCandidate::is_impl_candidate () const
+{
+  return type == IMPL_CONST || type == IMPL_TYPE_ALIAS || type == IMPL_FUNC;
+}
+
+bool
+PathProbeCandidate::is_trait_candidate () const
+{
+  return type == TRAIT_ITEM_CONST || type == TRAIT_TYPE_ALIAS
+|| type == TRAIT_FUNC;
+}
+
+bool
+PathProbeCandidate::is_full_trait_item_candidate () const
+{
+  return is_trait_candidate () && item.trait.impl == nullptr;
+}
+
+PathProbeCandidate
+PathProbeCandidate::get_error ()
+{
+  return PathProbeCandidate (ERROR, nullptr, Location (),
+ImplItemCandidate{nullptr, nullptr});
+}
+
+bool
+PathProbeCandidate::is_error () const
+{
+  return type == ERROR;
+}
+
+DefId
+PathProbeCandidate::get_defid () const
+{
+  switch (type)
+{
+case ENUM_VARIANT:
+  return item.enum_field.variant->get_defid ();
+  break;
+
+case IMPL_CONST:
+case IMPL_TYPE_ALIAS:
+case IMPL_FUNC:
+  return item.impl.impl_item->get_impl_mappings ().get_defid ();
+  break;
+
+case TRAIT_ITEM_CONST:
+case TRAIT_TYPE_ALIAS:
+case TRAIT_FUNC:
+  return item.trait.item_ref->get_mappings ().get_defid ();
+  break;
+
+case ERROR:
+default:
+  return UNKNOWN_DEFID;
+}
+
+  return UNKNOWN_DEFID;
+}
+
+bool
+PathProbeCandidate::operator< (const PathProbeCandidate ) const
+{
+  return get_defid () < c.get_defid ();
+}
+
 // PathProbeType
 
 PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h 
b/gcc/rust/typecheck/rust-hir-path-probe.h
index 783282a0dc9..dd511ac4184 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -73,89 +73,37 @@ struct PathProbeCandidate
 ImplItemCandidate impl;
 TraitItemCandidate trait;
 
-Candidate (EnumItemCandidate enum_field) : enum_field (enum_field) {}
-Candidate (ImplItemCandidate impl) : impl (impl) {}
-Candidate (TraitItemCandidate trait) : trait (trait) {}
+Candidate (EnumItemCandidate enum_field);
+Candidate (ImplItemCandidate impl);
+Candidate (TraitItemCandidate trait);
   } item;
 
   PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
- EnumItemCandidate enum_field)
-: type (type), ty (ty), locus (locus), item (enum_field)
-  {}
+ EnumItemCandidate enum_field);
 
   

[committed 35/88] gccrs: Add another test case for passing associated type-bounds

2023-04-05 Thread arthur . cohen
From: Philip Herron 

This demonstrates that this also works for custom algebraic data types too.

gcc/testsuite/ChangeLog:

* rust/execute/torture/issue-1720-2.rs: New test.

Signed-off-by: Philip Herron 
---
 .../rust/execute/torture/issue-1720-2.rs  | 30 +++
 1 file changed, 30 insertions(+)
 create mode 100644 gcc/testsuite/rust/execute/torture/issue-1720-2.rs

diff --git a/gcc/testsuite/rust/execute/torture/issue-1720-2.rs 
b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs
new file mode 100644
index 000..35833dbb813
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1720-2.rs
@@ -0,0 +1,30 @@
+mod core {
+mod ops {
+#[lang = "add"]
+pub trait Add {
+type Output;
+
+fn add(self, rhs: Rhs) -> Self::Output;
+}
+}
+}
+
+struct Foo(i32);
+
+impl core::ops::Add for Foo {
+type Output = i32;
+
+fn add(self, rhs: Foo) -> Self::Output {
+self.0 + rhs.0
+}
+}
+
+pub fn bar>(a: T) -> i32 {
+a + a
+}
+
+pub fn main() -> i32 {
+let a = Foo(1);
+
+bar(a) - 2
+}
-- 
2.40.0



[committed 52/88] gccrs: Add missing Sized, Copy and Clone lang item mappings

2023-04-05 Thread arthur . cohen
From: Philip Herron 

We need these lang items to be defined and later down the line the mappings
will be used to implement proper copy and clone logic.

Fixes #1786

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* util/rust-lang-item.h:

gcc/testsuite/ChangeLog:

* rust/compile/issue-1786.rs: New test.
---
 gcc/rust/util/rust-lang-item.h   | 24 
 gcc/testsuite/rust/compile/issue-1786.rs | 23 +++
 2 files changed, 47 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-1786.rs

diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 29c364bad61..c5ef6200fb4 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -80,6 +80,12 @@ public:
 FN_ONCE,
 FN_ONCE_OUTPUT,
 
+// markers
+COPY,
+CLONE,
+SIZED,
+
+// delimiter
 UNKNOWN,
   };
 
@@ -237,6 +243,18 @@ public:
   {
return ItemType::FN_ONCE_OUTPUT;
   }
+else if (item.compare ("copy") == 0)
+  {
+   return ItemType::COPY;
+  }
+else if (item.compare ("clone") == 0)
+  {
+   return ItemType::CLONE;
+  }
+else if (item.compare ("sized") == 0)
+  {
+   return ItemType::SIZED;
+  }
 
 return ItemType::UNKNOWN;
   }
@@ -321,6 +339,12 @@ public:
return "fn_once";
   case FN_ONCE_OUTPUT:
return "fn_once_output";
+  case COPY:
+   return "copy";
+  case CLONE:
+   return "clone";
+  case SIZED:
+   return "sized";
 
   case UNKNOWN:
return "";
diff --git a/gcc/testsuite/rust/compile/issue-1786.rs 
b/gcc/testsuite/rust/compile/issue-1786.rs
new file mode 100644
index 000..f73b63d0cb6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1786.rs
@@ -0,0 +1,23 @@
+#[lang = "clone"]
+trait Clone {
+fn clone() -> Self;
+
+fn clone_from( self, source: ) {
+*self = source.clone()
+}
+}
+
+#[lang = "copy"]
+pub trait Copy: Clone {
+// Empty.
+}
+
+mod impls {
+use super::Clone;
+
+impl Clone for char {
+fn clone() -> Self {
+*self
+}
+}
+}
-- 
2.40.0



[committed 40/88] gccrs: Refactor BaseType, InferType and ErrorType impl into cc file

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-tyty.cc (BaseType::BaseType): refactor
(BaseType::~BaseType): likewise
(BaseType::get_ref): likewise
(BaseType::set_ref): likewise
(BaseType::get_ty_ref): likewise
(BaseType::set_ty_ref): likewise
(BaseType::is_equal): likewise
(BaseType::is_unit): likewise
(BaseType::get_kind): likewise
(BaseType::get_combined_refs): likewise
(BaseType::append_reference): likewise
(BaseType::supports_substitutions): likewise
(BaseType::has_subsititions_defined): likewise
(BaseType::can_substitute): likewise
(BaseType::needs_generic_substitutions): likewise
(BaseType::contains_type_parameters): likewise
(BaseType::get_ident): likewise
(BaseType::get_locus): likewise
(InferType::InferType): likewise
(InferType::get_infer_kind): likewise
(InferType::get_name): likewise
(InferType::is_concrete): likewise
(ErrorType::ErrorType): likewise
(ErrorType::is_unit): likewise
(ErrorType::is_concrete): likewise
(ErrorType::get_name): likewise
(ErrorType::monomorphized_clone): likewise
* typecheck/rust-tyty.h (class SubstitutionArgumentMappings): likewise
---
 gcc/rust/typecheck/rust-tyty.cc | 181 
 gcc/rust/typecheck/rust-tyty.h  |  92 ++--
 2 files changed, 211 insertions(+), 62 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index b45bd99b1bd..079055e870d 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -146,6 +146,122 @@ is_primitive_type_kind (TypeKind kind)
 }
 }
 
+// BASE TYPE
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+   std::set refs)
+  : TypeBoundsMappings ({}), kind (kind), ref (ref), ty_ref (ty_ref),
+combined (refs), ident (ident), mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+   std::vector specified_bounds,
+   std::set refs)
+  : TypeBoundsMappings (specified_bounds), kind (kind), ref (ref),
+ty_ref (ty_ref), combined (refs), ident (ident),
+mappings (Analysis::Mappings::get ())
+{}
+
+BaseType::~BaseType () {}
+
+HirId
+BaseType::get_ref () const
+{
+  return ref;
+}
+
+void
+BaseType::set_ref (HirId id)
+{
+  if (id != ref)
+append_reference (ref);
+  ref = id;
+}
+
+HirId
+BaseType::get_ty_ref () const
+{
+  return ty_ref;
+}
+
+void
+BaseType::set_ty_ref (HirId id)
+{
+  ty_ref = id;
+}
+
+bool
+BaseType::is_equal (const BaseType ) const
+{
+  return get_kind () == other.get_kind ();
+}
+
+bool
+BaseType::is_unit () const
+{
+  return false;
+}
+
+TypeKind
+BaseType::get_kind () const
+{
+  return kind;
+}
+
+std::set
+BaseType::get_combined_refs () const
+{
+  return combined;
+}
+
+void
+BaseType::append_reference (HirId id)
+{
+  combined.insert (id);
+}
+
+bool
+BaseType::supports_substitutions () const
+{
+  return false;
+}
+
+bool
+BaseType::has_subsititions_defined () const
+{
+  return false;
+}
+
+bool
+BaseType::can_substitute () const
+{
+  return supports_substitutions () && has_subsititions_defined ();
+}
+
+bool
+BaseType::needs_generic_substitutions () const
+{
+  return false;
+}
+
+bool
+BaseType::contains_type_parameters () const
+{
+  return !is_concrete ();
+}
+
+const RustIdent &
+BaseType::get_ident () const
+{
+  return ident;
+}
+
+Location
+BaseType::get_locus () const
+{
+  return ident.locus;
+}
+
 bool
 BaseType::satisfies_bound (const TypeBoundPredicate ) const
 {
@@ -330,6 +446,40 @@ BaseType::debug () const
  debug_str ().c_str ());
 }
 
+// InferType
+
+InferType::InferType (HirId ref, InferTypeKind infer_kind, Location locus,
+ std::set refs)
+  : BaseType (ref, ref, TypeKind::INFER,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+infer_kind (infer_kind)
+{}
+
+InferType::InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind,
+ Location locus, std::set refs)
+  : BaseType (ref, ty_ref, TypeKind::INFER,
+ {Resolver::CanonicalPath::create_empty (), locus}, refs),
+infer_kind (infer_kind)
+{}
+
+InferType::InferTypeKind
+InferType::get_infer_kind () const
+{
+  return infer_kind;
+}
+
+std::string
+InferType::get_name () const
+{
+  return as_string ();
+}
+
+bool
+InferType::is_concrete () const
+{
+  return true;
+}
+
 void
 InferType::accept_vis (TyVisitor )
 {
@@ -435,6 +585,35 @@ InferType::default_type (BaseType **type) const
   return false;
 }
 
+// ErrorType
+
+ErrorType::ErrorType (HirId ref, std::set refs)
+  : BaseType (ref, ref, TypeKind::ERROR,
+ {Resolver::CanonicalPath::create_empty (), Location ()}, refs)
+{}
+
+ErrorType::ErrorType (HirId 

[committed 31/88] gccrs: parser: Improve parsing of complex generic arguments

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

The parser was missing code for handling complex type arguments such
as type paths or nested generics.

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_generic_arg): Handle type
paths and nested generics properly.

gcc/testsuite/ChangeLog:

* rust/compile/parse_complex_generic_application.rs: New test.
* rust/compile/parse_complex_generic_application2.rs: New test.
---
 gcc/rust/parse/rust-parse-impl.h|  4 +++-
 .../parse_complex_generic_application.rs| 17 +
 .../parse_complex_generic_application2.rs   | 10 ++
 3 files changed, 30 insertions(+), 1 deletion(-)
 create mode 100644 
gcc/testsuite/rust/compile/parse_complex_generic_application.rs
 create mode 100644 
gcc/testsuite/rust/compile/parse_complex_generic_application2.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 23b033fb26e..3610790815c 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6309,7 +6309,9 @@ Parser::parse_generic_arg ()
// could either have a valid type or a macro (FIXME: anything else?). So
// we need one bit of lookahead to differentiate if this is really
auto next_tok = lexer.peek_token (1);
-   if (next_tok->get_id () == EXCLAM)
+   if (next_tok->get_id () == LEFT_ANGLE
+   || next_tok->get_id () == SCOPE_RESOLUTION
+   || next_tok->get_id () == EXCLAM)
  {
auto type = parse_type ();
if (type)
diff --git a/gcc/testsuite/rust/compile/parse_complex_generic_application.rs 
b/gcc/testsuite/rust/compile/parse_complex_generic_application.rs
new file mode 100644
index 000..d5c7bf488b7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_complex_generic_application.rs
@@ -0,0 +1,17 @@
+pub enum Either {
+Left(T),
+Right(E),
+}
+
+pub mod err {
+pub struct Error;
+pub struct ErrorWrap(T);
+}
+
+pub fn foo_err() -> Either<(), err::Error> {
+Either::Left(())
+}
+
+pub fn foo_err_wrap() -> Either<(), err::ErrorWrap> {
+Either::Left(())
+}
diff --git a/gcc/testsuite/rust/compile/parse_complex_generic_application2.rs 
b/gcc/testsuite/rust/compile/parse_complex_generic_application2.rs
new file mode 100644
index 000..0361931c50c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_complex_generic_application2.rs
@@ -0,0 +1,10 @@
+pub enum Either {
+Left(L),
+Right(R),
+}
+
+pub struct Wrap(T);
+
+pub fn foo_wrap() -> Either<(), Wrap> {
+Either::Left(())
+}
-- 
2.40.0



[committed 51/88] gccrs: Fix nullptr dereference

2023-04-05 Thread arthur . cohen
From: Philip Herron 

When we check if this is concrete the guard checks to ensure the argument
is non null but the check here is wrongly returning early when the check
is non null meaning when it is null and therefore not concrete it will
end up doing a null dereference.

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-tyty-subst.cc (SubstitutionArg::is_conrete): fix check
---
 gcc/rust/typecheck/rust-tyty-subst.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc 
b/gcc/rust/typecheck/rust-tyty-subst.cc
index 7f5bb22687d..996bbf2d885 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -213,8 +213,8 @@ SubstitutionArg::is_error () const
 bool
 SubstitutionArg::is_conrete () const
 {
-  if (argument != nullptr)
-return true;
+  if (argument == nullptr)
+return false;
 
   if (argument->get_kind () == TyTy::TypeKind::PARAM)
 return false;
-- 
2.40.0



[committed 37/88] gccrs: Refactor TyVar and TypeBoundPredicates

2023-04-05 Thread arthur . cohen
From: Philip Herron 

This extract these helpers into seperate files

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* Make-lang.in: update makefile
* typecheck/rust-tyty.cc (TyVar::TyVar): move to new file
(TyVar::get_tyty): likewise
(TyVar::get_implicit_infer_var): likewise
(TyVar::subst_covariant_var): likewise
(TyVar::clone): likewise
(TyVar::monomorphized_clone): likewise
(TyWithLocation::TyWithLocation): likewise
* typecheck/rust-tyty.h (class BaseType): cleanup
(class TypeBoundPredicate): move to its own file
(class TypeBoundPredicateItem): likewise
(class TypeBoundsMappings): likewise
(class TyVar): likewise
(class TyWithLocation): likewise
* typecheck/rust-tyty-bounds.h: New file.
* typecheck/rust-tyty-util.cc: New file.
* typecheck/rust-tyty-util.h: New file.
---
 gcc/rust/Make-lang.in |   1 +
 gcc/rust/typecheck/rust-tyty-bounds.h |  88 +++
 gcc/rust/typecheck/rust-tyty-util.cc  | 116 ++
 gcc/rust/typecheck/rust-tyty-util.h   |  69 +++
 gcc/rust/typecheck/rust-tyty.cc   |  90 
 gcc/rust/typecheck/rust-tyty.h|  90 +---
 6 files changed, 276 insertions(+), 178 deletions(-)
 create mode 100644 gcc/rust/typecheck/rust-tyty-bounds.h
 create mode 100644 gcc/rust/typecheck/rust-tyty-util.cc
 create mode 100644 gcc/rust/typecheck/rust-tyty-util.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index a0c5757592e..2aa61bcfb19 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -115,6 +115,7 @@ GRS_OBJS = \
 rust/rust-pub-restricted-visitor.o \
 rust/rust-privacy-reporter.o \
 rust/rust-tyty.o \
+rust/rust-tyty-util.o \
 rust/rust-tyty-call.o \
 rust/rust-tyctx.o \
 rust/rust-tyty-bounds.o \
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.h 
b/gcc/rust/typecheck/rust-tyty-bounds.h
new file mode 100644
index 000..44839bd0b40
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-bounds.h
@@ -0,0 +1,88 @@
+// 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_TYTY_BOUNDS_H
+#define RUST_TYTY_BOUNDS_H
+
+#include "rust-location.h"
+
+namespace Rust {
+
+namespace Resolver {
+class TraitReference;
+class TraitItemReference;
+class AssociatedImplTrait;
+} // namespace Resolver
+
+namespace TyTy {
+
+class BaseType;
+class TypeBoundPredicate;
+class TypeBoundPredicateItem
+{
+public:
+  TypeBoundPredicateItem (const TypeBoundPredicate *parent,
+ const Resolver::TraitItemReference *trait_item_ref);
+
+  static TypeBoundPredicateItem error ();
+
+  bool is_error () const;
+
+  BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
+
+  const Resolver::TraitItemReference *get_raw_item () const;
+
+  bool needs_implementation () const;
+
+  const TypeBoundPredicate *get_parent () const;
+
+  Location get_locus () const;
+
+private:
+  const TypeBoundPredicate *parent;
+  const Resolver::TraitItemReference *trait_item_ref;
+};
+
+class TypeBoundsMappings
+{
+protected:
+  TypeBoundsMappings (std::vector specified_bounds);
+
+public:
+  std::vector _specified_bounds ();
+
+  const std::vector _specified_bounds () const;
+
+  size_t num_specified_bounds () const;
+
+  std::string raw_bounds_as_string () const;
+
+  std::string bounds_as_string () const;
+
+  std::string raw_bounds_as_name () const;
+
+protected:
+  void add_bound (TypeBoundPredicate predicate);
+
+  std::vector specified_bounds;
+};
+
+} // namespace TyTy
+} // namespace Rust
+
+#endif // RUST_TYTY_BOUNDS_H
diff --git a/gcc/rust/typecheck/rust-tyty-util.cc 
b/gcc/rust/typecheck/rust-tyty-util.cc
new file mode 100644
index 000..5037f68cb3f
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-util.cc
@@ -0,0 +1,116 @@
+// 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; 

[committed 33/88] gccrs: Add support for feature check.

2023-04-05 Thread arthur . cohen
From: mxlol233 

This commit implements a very basic feature checking module.

gcc/rust/ChangeLog:

* Make-lang.in: Add object files: `rust-feature.o` and 
`rust-feature-gate.o`
* checks/errors/rust-feature-gate.cc: New file.
* checks/errors/rust-feature-gate.h: New file.
* checks/errors/rust-feature.cc: New file.
* checks/errors/rust-feature.h: New file.
* rust-session-manager.cc: Add FeatureGate check.

gcc/testsuite/ChangeLog:

* rust/compile/feature.rs: New test.

Signed-off-by: Xiao Ma 
---
 gcc/rust/Make-lang.in   |   2 +
 gcc/rust/checks/errors/rust-feature-gate.cc |  63 +++
 gcc/rust/checks/errors/rust-feature-gate.h  | 191 
 gcc/rust/checks/errors/rust-feature.cc  |  66 +++
 gcc/rust/checks/errors/rust-feature.h   |  76 
 gcc/rust/rust-session-manager.cc|   4 +
 gcc/testsuite/rust/compile/feature.rs   |   4 +
 7 files changed, 406 insertions(+)
 create mode 100644 gcc/rust/checks/errors/rust-feature-gate.cc
 create mode 100644 gcc/rust/checks/errors/rust-feature-gate.h
 create mode 100644 gcc/rust/checks/errors/rust-feature.cc
 create mode 100644 gcc/rust/checks/errors/rust-feature.h
 create mode 100644 gcc/testsuite/rust/compile/feature.rs

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 87f3ba66eba..a0c5757592e 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -161,6 +161,8 @@ GRS_OBJS = \
 rust/rust-import-archive.o \
 rust/rust-extern-crate.o \
 rust/rust-builtins.o \
+rust/rust-feature.o \
+rust/rust-feature-gate.o \
 $(END)
 # removed object files from here
 
diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc 
b/gcc/rust/checks/errors/rust-feature-gate.cc
new file mode 100644
index 000..cd26f8a17f5
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature-gate.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-feature-gate.h"
+#include "rust-feature.h"
+
+namespace Rust {
+
+void
+FeatureGate::check (AST::Crate )
+{
+  std::vector valid_features;
+  for (const auto  : crate.inner_attrs)
+{
+  if (attr.get_path ().as_string () == "feature")
+   {
+ const auto _input = attr.get_attr_input ();
+ auto type = attr_input.get_attr_input_type ();
+ if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
+   {
+ const auto  = static_cast (
+   attr.get_attr_input ());
+ std::unique_ptr meta_item (
+   option.parse_to_meta_item ());
+ for (const auto  : meta_item->get_items ())
+   {
+ const auto  = item->as_string ();
+ auto tname = Feature::as_name (name);
+ if (!tname.is_none ())
+   valid_features.push_back (Feature::create (tname.get ()));
+ else
+   rust_error_at (item->get_locus (), "unknown feature '%s'",
+  name.c_str ());
+   }
+   }
+   }
+}
+  valid_features.shrink_to_fit ();
+
+  // TODO (mxlol233): add the real feature gate stuff.
+  auto  = crate.items;
+  for (auto it = items.begin (); it != items.end (); it++)
+{
+  auto  = *it;
+  item->accept_vis (*this);
+}
+}
+} // namespace Rust
\ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-feature-gate.h 
b/gcc/rust/checks/errors/rust-feature-gate.h
new file mode 100644
index 000..080c15ccd23
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-feature-gate.h
@@ -0,0 +1,191 @@
+// 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 

[committed 32/88] gccrs: parser: Fix parsing of closure param list

2023-04-05 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_closure_expr): Advance tokens
properly when parsing closure param list.

gcc/testsuite/ChangeLog:

* rust/compile/closure_move_expr.rs: New test.
---
 gcc/rust/parse/rust-parse-impl.h| 2 ++
 gcc/testsuite/rust/compile/closure_move_expr.rs | 9 +
 2 files changed, 11 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/closure_move_expr.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 3610790815c..4ceb978f7f4 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7592,6 +7592,7 @@ Parser::parse_closure_expr 
(AST::AttrVec outer_attrs)
 case PIPE:
   // actually may have parameters
   lexer.skip_token ();
+  t = lexer.peek_token ();
 
   while (t->get_id () != PIPE)
{
@@ -7608,6 +7609,7 @@ Parser::parse_closure_expr 
(AST::AttrVec outer_attrs)
 
  if (lexer.peek_token ()->get_id () != COMMA)
{
+ lexer.skip_token ();
  // not an error but means param list is done
  break;
}
diff --git a/gcc/testsuite/rust/compile/closure_move_expr.rs 
b/gcc/testsuite/rust/compile/closure_move_expr.rs
new file mode 100644
index 000..780c316e0af
--- /dev/null
+++ b/gcc/testsuite/rust/compile/closure_move_expr.rs
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fsyntax-only" }
+
+fn foo() {
+move |l: u32, r: u32| l + r
+}
+
+fn foo2() {
+|l: u32, r: u32| l + r
+}
-- 
2.40.0



[committed 38/88] gccrs: Refactor SubstitutionRef base class into its own CC file

2023-04-05 Thread arthur . cohen
From: Philip Herron 

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* Make-lang.in: update the makefile
* typecheck/rust-tyty.cc (SubstitutionParamMapping::need_substitution): 
likewise
(SubstitutionParamMapping::override_context): likewise
(SubstitutionRef::get_mappings_from_generic_args): likewise
(SubstitutionRef::infer_substitions): likewise
(SubstitutionRef::are_mappings_bound): likewise
(SubstitutionRef::solve_missing_mappings_from_this): likewise
(SubstitutionRef::monomorphize): likewise
* typecheck/rust-tyty.h (class SubstitutionParamMapping): likewise
(class SubstitutionArg): likewise
(std::functionhttp://www.gnu.org/licenses/>.
+
+#include "rust-tyty-subst.h"
+#include "rust-hir-full.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
+#include "rust-substitution-mapper.h"
+#include "rust-hir-type-check-type.h"
+
+namespace Rust {
+namespace TyTy {
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+  const HIR::TypeParam , ParamType *param)
+  : generic (generic), param (param)
+{}
+
+SubstitutionParamMapping::SubstitutionParamMapping (
+  const SubstitutionParamMapping )
+  : generic (other.generic), param (other.param)
+{}
+
+std::string
+SubstitutionParamMapping::as_string () const
+{
+  if (param == nullptr)
+return "nullptr";
+
+  return param->get_name ();
+}
+
+SubstitutionParamMapping
+SubstitutionParamMapping::clone () const
+{
+  return SubstitutionParamMapping (generic,
+  static_cast (param->clone ()));
+}
+
+ParamType *
+SubstitutionParamMapping::get_param_ty ()
+{
+  return param;
+}
+
+const ParamType *
+SubstitutionParamMapping::get_param_ty () const
+{
+  return param;
+}
+
+const HIR::TypeParam &
+SubstitutionParamMapping::get_generic_param ()
+{
+  return generic;
+};
+
+bool
+SubstitutionParamMapping::needs_substitution () const
+{
+  return !(get_param_ty ()->is_concrete ());
+}
+
+Location
+SubstitutionParamMapping::get_param_locus () const
+{
+  return generic.get_locus ();
+}
+
+bool
+SubstitutionParamMapping::param_has_default_ty () const
+{
+  return generic.has_type ();
+}
+
+BaseType *
+SubstitutionParamMapping::get_default_ty () const
+{
+  TyVar var (generic.get_type_mappings ().get_hirid ());
+  return var.get_tyty ();
+}
+
+bool
+SubstitutionParamMapping::need_substitution () const
+{
+  if (!param->can_resolve ())
+return true;
+
+  auto resolved = param->resolve ();
+  return !resolved->is_concrete ();
+}
+
+bool
+SubstitutionParamMapping::fill_param_ty (
+  SubstitutionArgumentMappings _mappings, Location locus)
+{
+  SubstitutionArg arg = SubstitutionArg::error ();
+  bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), );
+  if (!ok)
+return true;
+
+  TyTy::BaseType  = *arg.get_tyty ();
+  if (type.get_kind () == TyTy::TypeKind::INFER)
+{
+  type.inherit_bounds (*param);
+}
+  else
+{
+  if (!param->bounds_compatible (type, locus, true))
+   return false;
+}
+
+  if (type.get_kind () == TypeKind::PARAM)
+{
+  // delete param;
+  param = static_cast (type.clone ());
+}
+  else
+{
+  // check the substitution is compatible with bounds
+  if (!param->bounds_compatible (type, locus, true))
+   return false;
+
+  // recursively pass this down to all HRTB's
+  for (auto  : param->get_specified_bounds ())
+   bound.handle_substitions (subst_mappings);
+
+  param->set_ty_ref (type.get_ref ());
+}
+
+  return true;
+}
+
+void
+SubstitutionParamMapping::override_context ()
+{
+  if (!param->can_resolve ())
+return;
+
+  auto mappings = Analysis::Mappings::get ();
+  auto context = Resolver::TypeCheckContext::get ();
+
+  context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
+  UNKNOWN_NODEID,
+  param->get_ref (),
+  UNKNOWN_LOCAL_DEFID),
+   param->resolve ());
+}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionParamMapping *param,
+ BaseType *argument)
+  : param (param), argument (argument)
+{}
+
+SubstitutionArg::SubstitutionArg (const SubstitutionArg )
+  : param (other.param), argument (other.argument)
+{}
+
+SubstitutionArg &
+SubstitutionArg::operator= (const SubstitutionArg )
+{
+  param = other.param;
+  argument = other.argument;
+  return *this;
+}
+
+BaseType *
+SubstitutionArg::get_tyty ()
+{
+  return argument;
+}
+
+const BaseType *
+SubstitutionArg::get_tyty () const
+{
+  return argument;
+}
+
+const SubstitutionParamMapping *
+SubstitutionArg::get_param_mapping () const
+{
+  return param;
+}
+
+SubstitutionArg
+SubstitutionArg::error ()
+{
+  return SubstitutionArg (nullptr, nullptr);
+}
+
+bool
+SubstitutionArg::is_error () const
+{
+  return param == nullptr || argument == nullptr;
+}
+

[committed 36/88] gccrs: Move TypePredicateItem impl out of the header

2023-04-05 Thread arthur . cohen
From: Philip Herron 

This moves the implementation code out of the header and into its
respective cc file.

Signed-off-by: Philip Herron 

gcc/rust/ChangeLog:

* typecheck/rust-tyty-bounds.cc (TypeBoundPredicateItem::error): 
refactor
(TypeBoundPredicateItem::is_error): likewise
(TypeBoundPredicateItem::get_parent): likewise
* typecheck/rust-tyty.h: Move the implementation for the above
---
 gcc/rust/typecheck/rust-tyty-bounds.cc | 24 
 gcc/rust/typecheck/rust-tyty.h | 16 
 2 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc 
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 30f7b0d02e3..e7eb9a760f5 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -364,6 +364,30 @@ TypeBoundPredicate::lookup_associated_item (const 
std::string ) const
   return TypeBoundPredicateItem (this, trait_item_ref);
 }
 
+TypeBoundPredicateItem::TypeBoundPredicateItem (
+  const TypeBoundPredicate *parent,
+  const Resolver::TraitItemReference *trait_item_ref)
+  : parent (parent), trait_item_ref (trait_item_ref)
+{}
+
+TypeBoundPredicateItem
+TypeBoundPredicateItem::error ()
+{
+  return TypeBoundPredicateItem (nullptr, nullptr);
+}
+
+bool
+TypeBoundPredicateItem::is_error () const
+{
+  return parent == nullptr || trait_item_ref == nullptr;
+}
+
+const TypeBoundPredicate *
+TypeBoundPredicateItem::get_parent () const
+{
+  return parent;
+}
+
 TypeBoundPredicateItem
 TypeBoundPredicate::lookup_associated_item (
   const Resolver::TraitItemReference *ref) const
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 20a243fe980..7d32ed59494 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -82,19 +82,11 @@ class TypeBoundPredicateItem
 {
 public:
   TypeBoundPredicateItem (const TypeBoundPredicate *parent,
- const Resolver::TraitItemReference *trait_item_ref)
-: parent (parent), trait_item_ref (trait_item_ref)
-  {}
+ const Resolver::TraitItemReference *trait_item_ref);
 
-  static TypeBoundPredicateItem error ()
-  {
-return TypeBoundPredicateItem (nullptr, nullptr);
-  }
+  static TypeBoundPredicateItem error ();
 
-  bool is_error () const
-  {
-return parent == nullptr || trait_item_ref == nullptr;
-  }
+  bool is_error () const;
 
   BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
 
@@ -102,7 +94,7 @@ public:
 
   bool needs_implementation () const;
 
-  const TypeBoundPredicate *get_parent () const { return parent; }
+  const TypeBoundPredicate *get_parent () const;
 
   Location get_locus () const;
 
-- 
2.40.0



[committed 34/88] gccrs: Removed comment copy-pasted from gcc/tree.def

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* backend/rust-compile-expr.cc (CompileExpr::visit): Removed 
copy-pasted comment.

Signed-off-by: Owen Avery 
---
 gcc/rust/backend/rust-compile-expr.cc | 24 
 1 file changed, 24 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index 436fc924a13..c26f6f440ec 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1341,30 +1341,6 @@ CompileExpr::visit (HIR::MatchExpr )
   // SWITCH_ALL_CASES_P is true if the switch includes a default label or the
   // case label ranges cover all possible values of the condition expression
 
-  /* Switch expression.
-
- TREE_TYPE is the original type of the condition, before any
- language required type conversions.  It may be NULL, in which case
- the original type and final types are assumed to be the same.
-
- Operand 0 is the expression used to perform the branch,
- Operand 1 is the body of the switch, which probably contains
-   CASE_LABEL_EXPRs.  It may also be NULL, in which case operand 2
-   must not be NULL.  */
-  // DEFTREECODE (SWITCH_EXPR, "switch_expr", tcc_statement, 2)
-
-  /* Used to represent a case label.
-
- Operand 0 is CASE_LOW.  It may be NULL_TREE, in which case the label
-   is a 'default' label.
- Operand 1 is CASE_HIGH.  If it is NULL_TREE, the label is a simple
-   (one-value) case label.  If it is non-NULL_TREE, the case is a range.
- Operand 2 is CASE_LABEL, which has the corresponding LABEL_DECL.
- Operand 3 is CASE_CHAIN.  This operand is only used in tree-cfg.cc to
-   speed up the lookup of case labels which use a particular edge in
-   the control flow graph.  */
-  // DEFTREECODE (CASE_LABEL_EXPR, "case_label_expr", tcc_statement, 4)
-
   TyTy::TypeKind scrutinee_kind = check_match_scrutinee (expr, ctx);
   if (scrutinee_kind == TyTy::TypeKind::ERROR)
 {
-- 
2.40.0



[committed 30/88] gccrs: Implement lowering ReferencePattern from AST to HIR

2023-04-05 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* ast/rust-pattern.h:
(ReferencePattern::is_double_reference): Add method.
(ReferencePattern::get_is_mut): Add method.
* hir/rust-ast-lower-pattern.cc
(ASTLoweringPattern::visit): Add ReferencePattern visitor.
* hir/rust-ast-lower-pattern.h:
(ASTLoweringPattern::visit): Add ReferencePattern visitor.

Signed-off-by: Owen Avery 
---
 gcc/rust/ast/rust-pattern.h|  4 
 gcc/rust/hir/rust-ast-lower-pattern.cc | 29 ++
 gcc/rust/hir/rust-ast-lower-pattern.h  |  1 +
 3 files changed, 34 insertions(+)

diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index c86bdf6f820..cf5d2ead10d 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -469,6 +469,10 @@ public:
 return pattern;
   }
 
+  bool is_double_reference () const { return has_two_amps; }
+
+  bool get_is_mut () const { return is_mut; }
+
   NodeId get_node_id () const { return node_id; }
 
   NodeId get_pattern_node_id () const override final { return node_id; }
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc 
b/gcc/rust/hir/rust-ast-lower-pattern.cc
index a0fd8dded38..1961c740624 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -249,5 +249,34 @@ ASTLoweringPattern::visit (AST::GroupedPattern )
   pattern.get_pattern_in_parens ()->accept_vis (*this);
 }
 
+void
+ASTLoweringPattern::visit (AST::ReferencePattern )
+{
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
+mappings->get_next_hir_id (crate_num),
+UNKNOWN_LOCAL_DEFID);
+
+  HIR::Pattern *inner
+= ASTLoweringPattern::translate (pattern.get_referenced_pattern ().get ());
+
+  translated
+= new HIR::ReferencePattern (mapping, std::unique_ptr 
(inner),
+pattern.get_is_mut () ? Mutability::Mut
+  : Mutability::Imm,
+pattern.get_locus ());
+
+  if (pattern.is_double_reference ())
+{
+  Analysis::NodeMapping mapping2 (crate_num, pattern.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+  translated
+   = new HIR::ReferencePattern (mapping2,
+std::unique_ptr (translated),
+Mutability::Imm, pattern.get_locus ());
+}
+}
+
 } // namespace HIR
 } // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h 
b/gcc/rust/hir/rust-ast-lower-pattern.h
index 0075e27e9c0..2d175a25cb4 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.h
+++ b/gcc/rust/hir/rust-ast-lower-pattern.h
@@ -40,6 +40,7 @@ public:
   void visit (AST::LiteralPattern ) override;
   void visit (AST::RangePattern ) override;
   void visit (AST::GroupedPattern ) override;
+  void visit (AST::ReferencePattern ) override;
 
 private:
   ASTLoweringPattern ();
-- 
2.40.0



  1   2   >