[gcc r15-225] pru: Implement TARGET_ADDRESS_COST

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:3888f62ffb7b919ada4959207448af15b2cfd5a5

commit r15-225-g3888f62ffb7b919ada4959207448af15b2cfd5a5
Author: Dimitar Dimitrov 
Date:   Sun Oct 22 14:44:29 2023 +0300

pru: Implement TARGET_ADDRESS_COST

Stop relying on the default fallback to TARGET_RTX_COST for PRU's
addressing costs.  Implement TARGET_ADDRESS_COST, in order to allow RTX
cost refactoring in the future without affecting the addressing costs.

No code generation changes are expected by this patch.  No changes were
detected when running embench-iot and building a few real-world firmware
examples.

gcc/ChangeLog:

* config/pru/pru.cc (pru_address_cost): Implement address cost
calculation.
(TARGET_ADDRESS_COST): Define for PRU.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru.cc | 25 +
 1 file changed, 25 insertions(+)

diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index 270c536d4c7..a76451f4223 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -784,6 +784,28 @@ pru_rtx_costs (rtx x, machine_mode mode,
 }
 }
 
+/* Calculate the cost of an addressing mode that contains ADDR.
+   ADDR must be a valid address.  */
+
+static int
+pru_address_cost (rtx addr, machine_mode, addr_space_t as, bool)
+{
+  if (as != ADDR_SPACE_GENERIC)
+/* All currently implemented special address spaces for PRU
+   are much more efficient than generic memory I/O.  */
+return 0;
+  else if (ctable_addr_operand (addr, VOIDmode)
+  || (GET_CODE (addr) == PLUS
+  && ctable_base_operand (XEXP (addr, 1), VOIDmode)))
+/* Using CTABLE instructions reduces register pressure,
+   so give it precedence.  */
+return 1;
+  else
+/* Same two instructions (LBBO/SBBO) are used for any valid
+   addressing mode.  */
+return 2;
+}
+
 /* Insn costs on PRU are straightforward because:
  - Insns emit 0, 1 or more instructions.
  - All instructions are 32-bit length.
@@ -3208,6 +3230,9 @@ pru_unwind_word_mode (void)
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS pru_rtx_costs
 
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST pru_address_cost
+
 #undef TARGET_INSN_COST
 #define TARGET_INSN_COST pru_insn_cost


[gcc r15-226] pru: Implement zero fill for 64-bit registers

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:ca7d6d729183685279a0d9dcd39aed11021f1dfa

commit r15-226-gca7d6d729183685279a0d9dcd39aed11021f1dfa
Author: Dimitar Dimitrov 
Date:   Sat Nov 18 23:05:09 2023 +0200

pru: Implement zero fill for 64-bit registers

Loading a constant zero in a 64-bit register now takes one instead of
two instructions.

gcc/ChangeLog:

* config/pru/pru.md: New pattern alternative for zero-filling
64-bit registers.

gcc/testsuite/ChangeLog:

* gcc.target/pru/mov-0.c: New test.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru.md| 18 ++
 gcc/testsuite/gcc.target/pru/mov-0.c | 19 +++
 2 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 8393d8f9607..0123952aa9e 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -248,8 +248,8 @@
 ; Forcing DI reg alignment (akin to microblaze's HARD_REGNO_MODE_OK)
 ; does not seem efficient, and will violate TI ABI.
 (define_insn "mov"
-  [(set (match_operand:MOV64 0 "nonimmediate_operand" "=m,r,r,r,r,r,r")
-   (match_operand:MOV64 1 "general_operand"  "r,m,Um,r,T,J,nF"))]
+  [(set (match_operand:MOV64 0 "nonimmediate_operand" "=m,r,r,r,r,r,r,r")
+   (match_operand:MOV64 1 "general_operand"  "r,m,Z,Um,r,T,J,nF"))]
   ""
 {
   switch (which_alternative)
@@ -259,8 +259,10 @@
 case 1:
   return "lb%B1o\\t%b0, %1, %S1";
 case 2:
-  return "fill\\t%F0, 8";
+  return "zero\\t%F0, 8";
 case 3:
+  return "fill\\t%F0, 8";
+case 4:
   /* careful with overlapping source and destination regs.  */
   gcc_assert (GP_REG_P (REGNO (operands[0])));
   gcc_assert (GP_REG_P (REGNO (operands[1])));
@@ -268,18 +270,18 @@
return "mov\\t%N0, %N1\;mov\\t%F0, %F1";
   else
return "mov\\t%F0, %F1\;mov\\t%N0, %N1";
-case 4:
-  return "ldi\\t%F0, %%pmem(%1)\;ldi\\t%N0, 0";
 case 5:
-  return "ldi\\t%F0, %1\;ldi\\t%N0, 0";
+  return "ldi\\t%F0, %%pmem(%1)\;ldi\\t%N0, 0";
 case 6:
+  return "ldi\\t%F0, %1\;ldi\\t%N0, 0";
+case 7:
   return "ldi32\\t%F0, %w1\;ldi32\\t%N0, %W1";
 default:
   gcc_unreachable ();
   }
 }
-  [(set_attr "type" "st,ld,alu,alu,alu,alu,alu")
-   (set_attr "length" "4,4,4,8,8,8,16")])
+  [(set_attr "type" "st,ld,alu,alu,alu,alu,alu,alu")
+   (set_attr "length" "4,4,4,4,8,8,8,16")])
 
 ;
 ; load_multiple pattern(s).
diff --git a/gcc/testsuite/gcc.target/pru/mov-0.c 
b/gcc/testsuite/gcc.target/pru/mov-0.c
new file mode 100644
index 000..0190be36fa4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mov-0.c
@@ -0,0 +1,19 @@
+/* Loading a register with constant 0 integer value.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+int
+test_set_0_si (void)
+{
+  /* Since zero-extension is free, "zero" fill is not implemented for SI.  */
+  /* { dg-final { scan-assembler "ldi\\tr14(.b0)?, 0" } } */
+  return 0;
+}
+
+long long
+test_set_0_di (void)
+{
+  /* { dg-final { scan-assembler "zero\\tr14(.b0)?, 8" } } */
+  return 0;
+}


[gcc r15-227] pru: Optimize the extzv and insv patterns

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:47b757cf31fffb2ae5fdb93f9f031890080504a8

commit r15-227-g47b757cf31fffb2ae5fdb93f9f031890080504a8
Author: Dimitar Dimitrov 
Date:   Sun Nov 19 12:20:08 2023 +0200

pru: Optimize the extzv and insv patterns

Optimize the generated code for the bit-field extract and insert
patterns:
  - Use bit-set and bit-clear instructions for 1-bit fields.
  - Expand to SImode operations instead of relying on the default
expansion to word (QI) mode.

gcc/ChangeLog:

* config/pru/pru.md (extzv): Make it an expand pattern,
handle efficiently zero-positioned bit-fields.
(insv): New expand pattern.

gcc/testsuite/ChangeLog:

* gcc.target/pru/ashiftrt.c: Minor update due to new (but
equivalent) generated code sequence.
* gcc.target/pru/extzv-1.c: New test.
* gcc.target/pru/extzv-2.c: New test.
* gcc.target/pru/extzv-3.c: New test.
* gcc.target/pru/insv-1.c: New test.
* gcc.target/pru/insv-2.c: New test.
* gcc.target/pru/insv-3.c: New test.
* gcc.target/pru/insv-4.c: New test.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru.md   | 104 +---
 gcc/testsuite/gcc.target/pru/ashiftrt.c |   2 +-
 gcc/testsuite/gcc.target/pru/extzv-1.c  |  14 +
 gcc/testsuite/gcc.target/pru/extzv-2.c  |  15 +
 gcc/testsuite/gcc.target/pru/extzv-3.c  |  13 
 gcc/testsuite/gcc.target/pru/insv-1.c   |  14 +
 gcc/testsuite/gcc.target/pru/insv-2.c   |  14 +
 gcc/testsuite/gcc.target/pru/insv-3.c   |  14 +
 gcc/testsuite/gcc.target/pru/insv-4.c   |  14 +
 9 files changed, 194 insertions(+), 10 deletions(-)

diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 0123952aa9e..2ceea2e7b1c 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -486,22 +486,108 @@
 })
 
 ;; Bit extraction
-;; We define it solely to allow combine to choose SImode
+;; One reason to define it is to allow combine to choose SImode
 ;; for word mode when trying to match our cbranch_qbbx_* insn.
 ;;
 ;; Check how combine.cc:make_extraction() uses
 ;; get_best_reg_extraction_insn() to select the op size.
-(define_insn "extzv"
-  [(set (match_operand:QISI 0 "register_operand"   "=r")
+(define_expand "extzv"
+  [(set (match_operand:QISI 0 "register_operand")
  (zero_extract:QISI
-  (match_operand:QISI 1 "register_operand" "r")
-  (match_operand:QISI 2 "const_int_operand""i")
-  (match_operand:QISI 3 "const_int_operand""i")))]
+  (match_operand:QISI 1 "register_operand")
+  (match_operand:QISI 2 "const_int_operand")
+  (match_operand:QISI 3 "const_int_operand")))]
   ""
-  "lsl\\t%0, %1, (%S0 * 8 - %2 - %3)\;lsr\\t%0, %0, (%S0 * 8 - %2)"
-  [(set_attr "type" "complex")
-   (set_attr "length" "8")])
+{
+  const int nbits = INTVAL (operands[2]);
+  const int bitpos = INTVAL (operands[3]);
+  const int trailing_bits = GET_MODE_BITSIZE (mode) - nbits - bitpos;
+
+  if (bitpos == 0 && nbits <= 7)
+{
+  emit_insn (gen_and3 (operands[0],
+operands[1],
+gen_int_mode ((HOST_WIDE_INT_1U << nbits) - 1,
+  mode)));
+  DONE;
+}
+
+  rtx src = operands[1];
+  if (trailing_bits != 0)
+{
+  emit_insn (gen_ashl3 (operands[0],
+ operands[1],
+ GEN_INT (trailing_bits)));
+  src = operands[0];
+}
+  emit_insn (gen_lshr3 (operands[0],
+ src,
+ GEN_INT (trailing_bits + bitpos)));
+  DONE;
+})
+
+;; Bit-field insert.
+(define_expand "insv"
+  [(set (zero_extract:QISI
+ (match_operand:QISI 0 "register_operand")
+ (match_operand:QISI 1 "const_int_operand")
+ (match_operand:QISI 2 "const_int_operand"))
+   (match_operand:QISI 3 "reg_or_ubyte_operand"))]
+  ""
+{
+  const int nbits = INTVAL (operands[1]);
+  const int bitpos = INTVAL (operands[2]);
 
+  if (nbits == 1)
+{
+  rtx j;
+  rtx src = gen_reg_rtx (mode);
+  rtx dst = operands[0];
+
+  emit_move_insn (src, operands[3]);
+
+  emit_insn (gen_and3 (dst,
+dst,
+gen_int_mode (~(HOST_WIDE_INT_1U << bitpos),
+  mode)));
+
+  rtx_code_label *skip_set_label = gen_label_rtx ();
+  j = emit_jump_insn (gen_cbranch_qbbx_eq4 (
+ src,
+ GEN_INT (0),
+ skip_set_label));
+  JUMP_LABEL (j) = skip_set_label;
+  LABEL_NUSES (skip_set_label)++;
+
+  emit_insn (gen_ior3 (dst,
+

[gcc r15-228] pru: Add pattern variants for zero extending destination

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:b3ad0d413c009e839ff180f19f6b0a18822f521d

commit r15-228-gb3ad0d413c009e839ff180f19f6b0a18822f521d
Author: Dimitar Dimitrov 
Date:   Fri Dec 29 21:22:58 2023 +0200

pru: Add pattern variants for zero extending destination

The higher bits in the result of some ALU operations are inherently
always zero when all input operands are smaller than 32-bits.

Add pattern variants to match when the resulting value is zero
extended, so that all operations can be effectively executed in a
single instruction.  For PRU it simply means to use a wider register for
destination.

ALU operations which cannot be presented as zero-extending their
destination are addition, subtraction and logical shift left.  The PRU
ALU performs all operations in 32-bit mode, so the carry-out and
shifted-out bits would violate the assumption that ALU operation was
performed in 16-bit or 8-bit mode, and result was zero-extended.

gcc/ChangeLog:

* config/pru/alu-zext.md (_noz0): New subst attribute.
(_impl): Allow zero-extending the destination.
(): Remove unified pattern
(ashl_impl): New distinct pattern.
(lshr_impl): Ditto.
(alu3_zext_op0_subst): New subst iterator to zero-extend the
destination register.

gcc/testsuite/ChangeLog:

* gcc.target/pru/extzv-1.c: Update to mark the new more
efficient generated code sequence.
* gcc.target/pru/extzv-2.c: Ditto.
* gcc.target/pru/extzv-3.c: Ditto.
* gcc.target/pru/zero_extend-op0.c: New test.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/alu-zext.md | 38 ++
 gcc/testsuite/gcc.target/pru/extzv-1.c |  2 +-
 gcc/testsuite/gcc.target/pru/extzv-2.c |  2 +-
 gcc/testsuite/gcc.target/pru/extzv-3.c |  2 +-
 gcc/testsuite/gcc.target/pru/zero_extend-op0.c | 28 +++
 5 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/gcc/config/pru/alu-zext.md b/gcc/config/pru/alu-zext.md
index 04378db4774..c88eaf0ab44 100644
--- a/gcc/config/pru/alu-zext.md
+++ b/gcc/config/pru/alu-zext.md
@@ -33,6 +33,7 @@
 
 (define_subst_attr "alu2_zext" "alu2_zext_subst" "_z" "_noz")
 
+(define_subst_attr "alu3_zext_op0" "alu3_zext_op0_subst" "_z0" "_noz0")
 (define_subst_attr "alu3_zext_op1" "alu3_zext_op1_subst" "_z1" "_noz1")
 (define_subst_attr "alu3_zext_op2" "alu3_zext_op2_subst" "_z2" "_noz2")
 (define_subst_attr "alu3_zext" "alu3_zext_subst" "_z" "_noz")
@@ -44,6 +45,7 @@
 (define_subst_attr "bitalu_zext"   "bitalu_zext_subst"   "_z" "_noz")
 
 (define_code_iterator ALUOP3 [plus minus and ior xor umin umax ashift 
lshiftrt])
+(define_code_iterator ALUOP3_ZEXT0 [and ior xor umin umax lshiftrt])
 (define_code_iterator ALUOP2 [neg not])
 
 ;; Arithmetic Operations
@@ -130,8 +132,9 @@
   "set\\t%0, %1, %T2"
   [(set_attr "type" "alu")])
 
-; Regular ALU ops
-(define_insn 
"_impl_"
+; Regular ALU ops.  For all of them it is safe to present the result as
+; zero-extended, because there is no carry or shifted-out bits.
+(define_insn 
"_impl_"
   [(set (match_operand:EQD 0 "register_operand" "=r")
(LOGICAL:EQD
  (zero_extend:EQD
@@ -142,14 +145,25 @@
   "\\t%0, %1, %u2"
   [(set_attr "type" "alu")])
 
-; Shift ALU ops
-(define_insn 
"_impl_"
+; Shift left ALU op.  Cannot present the result as zero-extended because
+; of the shifted-out bits.
+(define_insn 
"ashl_impl_"
   [(set (match_operand:EQD 0 "register_operand" "=r")
-   (SHIFT:EQD
+   (ashift:EQD
 (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))
 (zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"]
   ""
-  "\\t%0, %1, %2"
+  "lsl\\t%0, %1, %2"
+  [(set_attr "type" "alu")])
+
+; Shift right ALU op.  The result can be presented as zero-extended.
+(define_insn 
"lshr_impl_"
+  [(set (match_operand:EQD 0 "register_operand" "=r")
+   (lshiftrt:EQD
+(zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))
+(zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"]
+  ""
+  "lsr\\t%0, %1, %2"
   [(set_attr "type" "alu")])
 
 ;; Substitutions
@@ -197,6 +211,18 @@
(ALUOP3:EQD (zero_extend:EQD (match_dup 1))
(match_dup 2)))])
 
+;; Some ALU operations with zero-extended inputs are
+;; equivalent to doing the same ALU operation in the
+;; smaller mode, and then zero-extending the output.
+(define_subst "alu3_zext_op0_subst"
+  [(set (match_operand:EQD 0)
+   (ALUOP3_ZEXT0:EQD (zero_extend:EQD (match_operand:EQS0 1))
+ (zero_extend:EQD (match_operand:EQS0 2]
+  "GET_MODE_SIZE (mode) < GET_MODE_SIZE (mode)"
+  [(set (match_dup 0)
+   (zero_extend:EQD
+ (ALUOP3_ZEXT0:EQS0 (match_dup 1)
+(match_dup 2])
 
 (define_subs

[gcc r15-229] pru: Skip register save if function will not return

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:b3bcc3f6a775ec1fee2ebc881e9c8706cf60351e

commit r15-229-gb3bcc3f6a775ec1fee2ebc881e9c8706cf60351e
Author: Dimitar Dimitrov 
Date:   Sat Jan 13 22:29:57 2024 +0200

pru: Skip register save if function will not return

There is no need to store callee-saved registers in prologue if the
function would never return.  Size optimization is paramount for the
microcontroller-class PRU.

Some backends save some registers for noreturn functions.  But for PRU
debuggability is a less concern because GDB has not been ported yet
for PRU.

gcc/ChangeLog:

* config/pru/pru.cc (prologue_saved_reg_p): Skip saving
if function will not return.

gcc/testsuite/ChangeLog:

* gcc.target/pru/noreturn-prologue-1.c: New test.
* gcc.target/pru/noreturn-prologue-2.c: New test.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru.cc  |  4 
 gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c | 10 ++
 gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c | 11 +++
 3 files changed, 25 insertions(+)

diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index a76451f4223..e5ec398d2db 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -443,6 +443,10 @@ prologue_saved_reg_p (int regno)
 {
   gcc_assert (GP_REG_P (regno));
 
+  /* Do not save the register if function will not return.  */
+  if (TREE_THIS_VOLATILE (current_function_decl))
+return false;
+
   if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
 return true;
 
diff --git a/gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c 
b/gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c
new file mode 100644
index 000..af69e52d925
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/noreturn-prologue-1.c
@@ -0,0 +1,10 @@
+/* Ensure prologues are not generated for noreturn functions.  */
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text == 0 } } */
+
+void test(void)
+{
+  asm volatile ("# \n\t" : : : "r5", "r10");
+  __builtin_unreachable ();
+}
diff --git a/gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c 
b/gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c
new file mode 100644
index 000..8d12a9c462b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/noreturn-prologue-2.c
@@ -0,0 +1,11 @@
+/* Ensure prologues are not generated for noreturn functions.  */
+/* { dg-do assemble } */
+/* { dg-options "-Os" } */
+/* { dg-final { object-size text == 4 } } */
+
+void test(void)
+{
+  asm volatile ("# \n\t" : : : "r0", "r9");
+  for (;;)
+;
+}


[gcc r15-230] pru: Drop usage of ATTRIBUTE_UNUSED

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:00090d5ea82f1acad8fd4feead4652a9fc5572f6

commit r15-230-g00090d5ea82f1acad8fd4feead4652a9fc5572f6
Author: Dimitar Dimitrov 
Date:   Tue Jan 23 22:03:33 2024 +0200

pru: Drop usage of ATTRIBUTE_UNUSED

Remove usage of ATTRIBUTE_UNUSED.  Instead remove the argument's name,
which in C++ means that the argument would not be used.

gcc/ChangeLog:

* config/pru/pru-passes.cc: Drop ATTRIBUTE_UNUSED and remove
argument's name.
* config/pru/pru-pragma.cc (pru_pragma_ctable_entry): Ditto.
* config/pru/pru.cc (pru_function_profiler): Ditto.
(pru_can_eliminate): Ditto.
(pru_rtx_costs): Ditto.
(pru_insert_attributes): Ditto.
(pru_function_value): Ditto.
(pru_libcall_value): Ditto.
(pru_return_in_memory): Ditto.
(pru_builtin_decl): Ditto.
(pru_expand_builtin): Ditto.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru-passes.cc |  2 +-
 gcc/config/pru/pru-pragma.cc |  2 +-
 gcc/config/pru/pru.cc| 24 +---
 3 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/gcc/config/pru/pru-passes.cc b/gcc/config/pru/pru-passes.cc
index fdef068f6a3..a76be8fd528 100644
--- a/gcc/config/pru/pru-passes.cc
+++ b/gcc/config/pru/pru-passes.cc
@@ -68,7 +68,7 @@ public:
   /* opt_pass methods: */
   virtual unsigned int execute (function *);
 
-  virtual bool gate (function *fun ATTRIBUTE_UNUSED)
+  virtual bool gate (function *)
   {
 return pru_current_abi == PRU_ABI_TI;
   }
diff --git a/gcc/config/pru/pru-pragma.cc b/gcc/config/pru/pru-pragma.cc
index f948411aef7..73bb4b60e51 100644
--- a/gcc/config/pru/pru-pragma.cc
+++ b/gcc/config/pru/pru-pragma.cc
@@ -40,7 +40,7 @@
 
WARNING: Only immediate constant addresses are currently supported.  */
 static void
-pru_pragma_ctable_entry (cpp_reader * reader ATTRIBUTE_UNUSED)
+pru_pragma_ctable_entry (cpp_reader *)
 {
   tree ctable_index, base_addr;
   enum cpp_ttype type;
diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index e5ec398d2db..49d35c60d12 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -405,7 +405,7 @@ pru_get_return_address (int count)
 
 /* Implement FUNCTION_PROFILER macro.  */
 void
-pru_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
+pru_function_profiler (FILE *file, int)
 {
   fprintf (file, "\tmov\tr1, ra\n");
   fprintf (file, "\tcall\t_mcount\n");
@@ -467,7 +467,7 @@ prologue_saved_reg_p (int regno)
 
 /* Implement TARGET_CAN_ELIMINATE.  */
 static bool
-pru_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+pru_can_eliminate (const int, const int to)
 {
   if (to == STACK_POINTER_REGNUM)
 return !frame_pointer_needed;
@@ -637,9 +637,7 @@ pru_option_override (void)
cost has been computed, and false if subexpressions should be
scanned.  In either case, *TOTAL contains the cost result.  */
 static bool
-pru_rtx_costs (rtx x, machine_mode mode,
-  int outer_code, int opno ATTRIBUTE_UNUSED,
-  int *total, bool speed ATTRIBUTE_UNUSED)
+pru_rtx_costs (rtx x, machine_mode mode, int outer_code, int, int *total, bool)
 {
   const int code = GET_CODE (x);
 
@@ -2174,7 +2172,7 @@ pru_nongeneric_pointer_addrspace (tree typ)
during the "mov" pattern expansion.  */
 
 static void
-pru_insert_attributes (tree node, tree *attributes ATTRIBUTE_UNUSED)
+pru_insert_attributes (tree node, tree *)
 {
 
   /* Validate __regio_symbol variable declarations.  */
@@ -2399,15 +2397,14 @@ pru_function_arg_advance (cumulative_args_t cum_v,
 
 /* Implement TARGET_FUNCTION_VALUE.  */
 static rtx
-pru_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
- bool outgoing ATTRIBUTE_UNUSED)
+pru_function_value (const_tree ret_type, const_tree, bool)
 {
   return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNUM);
 }
 
 /* Implement TARGET_LIBCALL_VALUE.  */
 static rtx
-pru_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+pru_libcall_value (machine_mode mode, const_rtx)
 {
   return gen_rtx_REG (mode, FIRST_RETVAL_REGNUM);
 }
@@ -2421,7 +2418,7 @@ pru_function_value_regno_p (const unsigned int regno)
 
 /* Implement TARGET_RETURN_IN_MEMORY.  */
 bool
-pru_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+pru_return_in_memory (const_tree type, const_tree)
 {
   bool in_memory = (!pru_arg_in_reg_bysize (int_size_in_bytes (type))
|| int_size_in_bytes (type) == -1);
@@ -2989,7 +2986,7 @@ pru_init_builtins (void)
 /* Implement TARGET_BUILTIN_DECL.  */
 
 static tree
-pru_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
+pru_builtin_decl (unsigned code, bool)
 {
   switch (code)
 {
@@ -3068,10 +3065,7 @@ pru_expand_delay_cycles (rtx arg)
IGNORE is nonzero if the value is to be ignored.  */
 
 static rtx
-pru_expand_builtin (tree exp, rtx tar

[gcc r15-231] pru: Use HOST_WIDE_INT_1U macro

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:3d342993a4d5000bcd3fd407e42e348c6d4a80b3

commit r15-231-g3d342993a4d5000bcd3fd407e42e348c6d4a80b3
Author: Dimitar Dimitrov 
Date:   Sat Mar 2 15:05:12 2024 +0200

pru: Use HOST_WIDE_INT_1U macro

Use the HOST_WIDE_INT_1U macro instead of literal 1 when constructing
constants for RTL.

gcc/ChangeLog:

* config/pru/pru.md (lshrdi3): Use HOST_WIDE_INT_1U macro.
(ashldi3): Ditto.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru.md | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 2ceea2e7b1c..db7a5af6875 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -870,7 +870,8 @@
   JUMP_LABEL (j) = skip_hiset_label;
   LABEL_NUSES (skip_hiset_label)++;
 
-  emit_insn (gen_iorsi3 (dst_lo, dst_lo, GEN_INT (1 << 31)));
+  const HOST_WIDE_INT bit31_mask = HOST_WIDE_INT_1U << 31;
+  emit_insn (gen_iorsi3 (dst_lo, dst_lo, GEN_INT (bit31_mask)));
   emit_label (skip_hiset_label);
   emit_insn (gen_rtx_SET (dst_hi,
  gen_rtx_LSHIFTRT (SImode, src_hi, const1_rtx)));
@@ -959,7 +960,8 @@
   JUMP_LABEL (j) = skip_hiset_label;
   LABEL_NUSES (skip_hiset_label)++;
 
-  emit_insn (gen_iorsi3 (dst_hi, dst_hi, GEN_INT (1 << 0)));
+  const HOST_WIDE_INT bit0_mask = HOST_WIDE_INT_1U << 0;
+  emit_insn (gen_iorsi3 (dst_hi, dst_hi, GEN_INT (bit0_mask)));
   emit_label (skip_hiset_label);
   emit_insn (gen_rtx_SET (dst_lo,
  gen_rtx_ASHIFT (SImode, src_lo, const1_rtx)));


[gcc r15-232] pru: Refactor to use passes definition file

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:4cf8daaf8a5db7ac1123fd2cbc3d9fc466bda69d

commit r15-232-g4cf8daaf8a5db7ac1123fd2cbc3d9fc466bda69d
Author: Dimitar Dimitrov 
Date:   Sat Mar 9 22:16:09 2024 +0200

pru: Refactor to use passes definition file

Switch to using a passes definition file instead of explicitly
registering the PRU-specific passes in pru.cc.  This would make it
cleaner to add new PRU-specific passes.

There are no functional changes.

gcc/ChangeLog:

* config/pru/pru-passes.cc (class pass_tiabi_check): Rename to
add "pru_" prefix.
(class pass_pru_tiabi_check): Ditto.
(pass_tiabi_check::execute): Ditto.
(pass_pru_tiabi_check::execute): Ditto.
(make_pru_tiabi_check): Ditto.
(pru_register_abicheck_pass): Remove.
* config/pru/pru-protos.h (pru_register_abicheck_pass): Remove.
(make_pru_tiabi_check): Add declaration.
* config/pru/pru.cc (pru_option_override): Remove explicit pass
registration.
* config/pru/t-pru: Register PRU passes definition file.
* config/pru/pru-passes.def: New file.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru-passes.cc  | 30 +-
 gcc/config/pru/pru-passes.def | 24 
 gcc/config/pru/pru-protos.h   |  2 +-
 gcc/config/pru/pru.cc |  5 -
 gcc/config/pru/t-pru  |  2 ++
 5 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/gcc/config/pru/pru-passes.cc b/gcc/config/pru/pru-passes.cc
index a76be8fd528..d2c6ae8737d 100644
--- a/gcc/config/pru/pru-passes.cc
+++ b/gcc/config/pru/pru-passes.cc
@@ -44,10 +44,10 @@ namespace {
 /* Scan the tree to ensure that the compiled code by GCC
conforms to the TI ABI specification.  If GCC cannot
output a conforming code, raise an error.  */
-const pass_data pass_data_tiabi_check =
+const pass_data pass_data_pru_tiabi_check =
 {
   GIMPLE_PASS, /* type */
-  "*tiabi_check", /* name */
+  "*pru_tiabi_check", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
   TV_NONE, /* tv_id */
   PROP_gimple_any, /* properties_required */
@@ -58,11 +58,11 @@ const pass_data pass_data_tiabi_check =
 };
 
 /* Implementation class for the TI ABI compliance-check pass.  */
-class pass_tiabi_check : public gimple_opt_pass
+class pass_pru_tiabi_check : public gimple_opt_pass
 {
 public:
-  pass_tiabi_check (gcc::context *ctxt)
-: gimple_opt_pass (pass_data_tiabi_check, ctxt)
+  pass_pru_tiabi_check (gcc::context *ctxt)
+: gimple_opt_pass (pass_data_pru_tiabi_check, ctxt)
   {}
 
   /* opt_pass methods: */
@@ -73,7 +73,7 @@ public:
 return pru_current_abi == PRU_ABI_TI;
   }
 
-}; // class pass_tiabi_check
+}; // class pass_pru_tiabi_check
 
 /* Return 1 if type TYPE is a pointer to function type or a
structure having a pointer to function type as one of its fields.
@@ -187,7 +187,7 @@ check_op_callback (tree *tp, int *walk_subtrees, void *data)
 
 /* Pass implementation.  */
 unsigned
-pass_tiabi_check::execute (function *fun)
+pass_pru_tiabi_check::execute (function *fun)
 {
   struct walk_stmt_info wi;
   const_tree fntype = TREE_TYPE (fun->decl);
@@ -210,19 +210,7 @@ pass_tiabi_check::execute (function *fun)
 } // anon namespace
 
 gimple_opt_pass *
-make_pass_tiabi_check (gcc::context *ctxt)
+make_pru_tiabi_check (gcc::context *ctxt)
 {
-  return new pass_tiabi_check (ctxt);
-}
-
-/* Register as early as possible.  */
-void
-pru_register_abicheck_pass (void)
-{
-  opt_pass *tiabi_check = make_pass_tiabi_check (g);
-  struct register_pass_info tiabi_check_info
-= { tiabi_check, "*warn_unused_result",
-   1, PASS_POS_INSERT_AFTER
-  };
-  register_pass (&tiabi_check_info);
+  return new pass_pru_tiabi_check (ctxt);
 }
diff --git a/gcc/config/pru/pru-passes.def b/gcc/config/pru/pru-passes.def
new file mode 100644
index 000..cdef089bd82
--- /dev/null
+++ b/gcc/config/pru/pru-passes.def
@@ -0,0 +1,24 @@
+/* Description of target passes for PRU.
+   Copyright (C) 2024 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
+   .  */
+
+/* If strict TI ABI conformance is requested, then this pass would validate
+   that the compiled code by GCC conforms to the TI ABI specification.
+   If GCC cannot output a conf

[gcc r15-233] pru: New validation pass for minrt

2024-05-07 Thread Dimitar Dimitrov via Gcc-cvs
https://gcc.gnu.org/g:0822400aae8f79de8f10ddde268f592ba6c2d2fb

commit r15-233-g0822400aae8f79de8f10ddde268f592ba6c2d2fb
Author: Dimitar Dimitrov 
Date:   Fri Feb 9 22:30:28 2024 +0200

pru: New validation pass for minrt

Add a new pru-specific pass to validate that the assumptions for the
minimal C runtime are not violated by the user program.

gcc/ChangeLog:

* config/pru/pru-passes.cc (class pass_pru_minrt_check): New
pass.
(pass_pru_minrt_check::execute): New method.
(make_pru_minrt_check): New function.
* config/pru/pru-passes.def (INSERT_PASS_AFTER): Register the
minrt check pass.
* config/pru/pru-protos.h (make_pru_minrt_check): Add
declaration.

gcc/testsuite/ChangeLog:

* g++.target/pru/minrt-1.cc: New test.
* g++.target/pru/minrt-2.cc: New test.
* g++.target/pru/minrt-3.cc: New test.
* g++.target/pru/pru.exp: New test.
* gcc.target/pru/minrt-1.c: New test.
* gcc.target/pru/minrt-2.c: New test.
* gcc.target/pru/minrt-3.c: New test.

Signed-off-by: Dimitar Dimitrov 

Diff:
---
 gcc/config/pru/pru-passes.cc| 70 +
 gcc/config/pru/pru-passes.def   |  5 +++
 gcc/config/pru/pru-protos.h |  1 +
 gcc/testsuite/g++.target/pru/minrt-1.cc | 10 +
 gcc/testsuite/g++.target/pru/minrt-2.cc | 10 +
 gcc/testsuite/g++.target/pru/minrt-3.cc |  9 +
 gcc/testsuite/g++.target/pru/pru.exp| 34 
 gcc/testsuite/gcc.target/pru/minrt-1.c  | 10 +
 gcc/testsuite/gcc.target/pru/minrt-2.c  | 10 +
 gcc/testsuite/gcc.target/pru/minrt-3.c  |  9 +
 10 files changed, 168 insertions(+)

diff --git a/gcc/config/pru/pru-passes.cc b/gcc/config/pru/pru-passes.cc
index d2c6ae8737d..5e7e22df65d 100644
--- a/gcc/config/pru/pru-passes.cc
+++ b/gcc/config/pru/pru-passes.cc
@@ -214,3 +214,73 @@ make_pru_tiabi_check (gcc::context *ctxt)
 {
   return new pass_pru_tiabi_check (ctxt);
 }
+
+namespace {
+
+/* Scan the tree to ensure that the compiled code by GCC
+   conforms to the non-standard minimal runtime.  */
+const pass_data pass_data_pru_minrt_check =
+{
+  GIMPLE_PASS, /* type */
+  "*pru_minrt_check", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_NONE, /* tv_id */
+  PROP_gimple_any, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+/* Implementation class for the minrt compliance-check pass.  */
+class pass_pru_minrt_check : public gimple_opt_pass
+{
+public:
+  pass_pru_minrt_check (gcc::context *ctxt)
+: gimple_opt_pass (pass_data_pru_minrt_check, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual unsigned int execute (function *);
+
+  virtual bool gate (function *)
+  {
+return TARGET_MINRT;
+  }
+
+}; // class pass_pru_minrt_check
+
+/* Pass implementation.  */
+unsigned
+pass_pru_minrt_check::execute (function *fun)
+{
+  const_tree fntype = TREE_TYPE (fun->decl);
+
+  if (id_equal (DECL_NAME (fun->decl), "main"))
+{
+  /* Argument list always ends with VOID_TYPE, so subtract one
+to get the number of function arguments.  */
+  const unsigned num_args = list_length (TYPE_ARG_TYPES (fntype)) - 1;
+
+  if (num_args != 0)
+   error_at (DECL_SOURCE_LOCATION (fun->decl), "function % "
+ "must have no arguments when using the "
+ "%<-minrt%> option");
+
+  /* The required CFG analysis to detect when a functions would never
+return is available only with -O1 and higher.  */
+  if (optimize >= 1 && !TREE_THIS_VOLATILE (fun->decl))
+   error_at (DECL_SOURCE_LOCATION (fun->decl), "function % "
+ "must never return when using the "
+ "%<-minrt%> option");
+}
+  return 0;
+}
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pru_minrt_check (gcc::context *ctxt)
+{
+  return new pass_pru_minrt_check (ctxt);
+}
diff --git a/gcc/config/pru/pru-passes.def b/gcc/config/pru/pru-passes.def
index cdef089bd82..3eee313ac67 100644
--- a/gcc/config/pru/pru-passes.def
+++ b/gcc/config/pru/pru-passes.def
@@ -22,3 +22,8 @@
If GCC cannot output a conforming code, then an error is raised.  */
 
 INSERT_PASS_AFTER (pass_warn_unused_result, 1, pru_tiabi_check);
+
+/* If -minrt option is used, then this pass would validate
+   that the compiled code by GCC is compatible with the minimal
+   C runtime.  */
+INSERT_PASS_AFTER (pass_warn_function_noreturn, 1, pru_minrt_check);
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index 74426bb86ea..3baf605d915 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -73,6 +73,7 @@ extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT 
caddr);
 extern int pru_symref2ioregno (rtx op);
 
 extern rtl_opt_

[gcc r14-10174] Bump BASE-VER

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:43b730b9134af60a8f1c5b107d625f7127ff23c5

commit r14-10174-g43b730b9134af60a8f1c5b107d625f7127ff23c5
Author: Richard Biener 
Date:   Tue May 7 09:23:01 2024 +0200

Bump BASE-VER

* BASE-VER: Set to 14.1.1.

Diff:
---
 gcc/BASE-VER | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/BASE-VER b/gcc/BASE-VER
index 7b3b6e02bb3..26f2bbc1975 100644
--- a/gcc/BASE-VER
+++ b/gcc/BASE-VER
@@ -1 +1 @@
-14.1.0
+14.1.1


[gcc r15-235] Support dot_prod optabs for 64-bit vector.

2024-05-07 Thread hongtao Liu via Gcc-cvs
https://gcc.gnu.org/g:fa911365490a7ca308878517a4af6189ffba7ed6

commit r15-235-gfa911365490a7ca308878517a4af6189ffba7ed6
Author: liuhongt 
Date:   Wed Dec 20 11:43:25 2023 +0800

Support dot_prod optabs for 64-bit vector.

gcc/ChangeLog:

PR target/113079
* config/i386/mmx.md (usdot_prodv8qi): New expander.
(sdot_prodv8qi): Ditto.
(udot_prodv8qi): Ditto.
(usdot_prodv4hi): Ditto.
(udot_prodv4hi): Ditto.
(sdot_prodv4hi): Ditto.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr113079.c: New test.
* gcc.target/i386/pr113079-2.c: New test.
* gcc.target/i386/sse4-pr113079-2.c: New test.

Diff:
---
 gcc/config/i386/mmx.md  | 195 
 gcc/testsuite/gcc.target/i386/pr113079-2.c  | 161 +++
 gcc/testsuite/gcc.target/i386/pr113079.c|  57 +++
 gcc/testsuite/gcc.target/i386/sse4-pr113079-2.c | 158 +++
 4 files changed, 571 insertions(+)

diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 9a8d6030d8b..5f342497885 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -6342,6 +6342,201 @@
   DONE;
 })
 
+(define_expand "usdot_prodv8qi"
+  [(match_operand:V2SI 0 "register_operand")
+   (match_operand:V8QI 1 "register_operand")
+   (match_operand:V8QI 2 "register_operand")
+   (match_operand:V2SI 3 "register_operand")]
+  "TARGET_MMX_WITH_SSE && TARGET_SSE4_1"
+{
+  operands[1] = force_reg (V8QImode, operands[1]);
+  operands[2] = force_reg (V8QImode, operands[2]);
+  operands[3] = force_reg (V2SImode, operands[3]);
+
+  if ((TARGET_AVX512VNNI && TARGET_AVX512VL)
+ || TARGET_AVXVNNI)
+{
+  rtx op1 = lowpart_subreg (V16QImode, operands[1], V8QImode);
+  rtx op2 = lowpart_subreg (V16QImode, operands[2], V8QImode);
+  rtx op3 = lowpart_subreg (V4SImode, operands[3], V2SImode);
+  rtx op0 = gen_reg_rtx (V4SImode);
+
+  emit_insn (gen_usdot_prodv16qi (op0, op1, op2, op3));
+  emit_move_insn (operands[0], lowpart_subreg (V2SImode, op0, V4SImode));
+ }
+   else
+ {
+  rtx op1 = gen_reg_rtx (V8HImode);
+  rtx op2 = gen_reg_rtx (V8HImode);
+  rtx op3 = gen_reg_rtx (V4SImode);
+  rtx op0 = gen_reg_rtx (V4SImode);
+  rtx op0_1 = gen_reg_rtx (V4SImode);
+
+  emit_move_insn (op3, CONST0_RTX (V4SImode));
+  emit_insn (gen_zero_extendv8qiv8hi2 (op1, operands[1]));
+  emit_insn (gen_extendv8qiv8hi2 (op2, operands[2]));
+  emit_insn (gen_sdot_prodv8hi (op0, op1, op2, op3));
+
+  /* vec_perm (op0, 2, 3, 0, 1);  */
+  emit_insn (gen_sse2_pshufd (op0_1, op0, GEN_INT (78)));
+  emit_insn (gen_addv4si3 (op0, op0, op0_1));
+  emit_insn (gen_addv2si3 (operands[0], operands[3],
+  lowpart_subreg (V2SImode, op0, V4SImode)));
+ }
+DONE;
+})
+
+(define_expand "sdot_prodv8qi"
+  [(match_operand:V2SI 0 "register_operand")
+   (match_operand:V8QI 1 "register_operand")
+   (match_operand:V8QI 2 "register_operand")
+   (match_operand:V2SI 3 "register_operand")]
+  "TARGET_MMX_WITH_SSE && TARGET_SSE4_1"
+{
+  operands[1] = force_reg (V8QImode, operands[1]);
+  operands[2] = force_reg (V8QImode, operands[2]);
+  operands[3] = force_reg (V2SImode, operands[3]);
+
+  if (TARGET_AVXVNNIINT8)
+{
+  rtx op1 = lowpart_subreg (V16QImode, operands[1], V8QImode);
+  rtx op2 = lowpart_subreg (V16QImode, operands[2], V8QImode);
+  rtx op3 = lowpart_subreg (V4SImode, operands[3], V2SImode);
+  rtx op0 = gen_reg_rtx (V4SImode);
+
+  emit_insn (gen_sdot_prodv16qi (op0, op1, op2, op3));
+  emit_move_insn (operands[0], lowpart_subreg (V2SImode, op0, V4SImode));
+}
+  else
+{
+  rtx op1 = gen_reg_rtx (V8HImode);
+  rtx op2 = gen_reg_rtx (V8HImode);
+  rtx op3 = gen_reg_rtx (V4SImode);
+  rtx op0 = gen_reg_rtx (V4SImode);
+  rtx op0_1 = gen_reg_rtx (V4SImode);
+
+  emit_move_insn (op3, CONST0_RTX (V4SImode));
+  emit_insn (gen_extendv8qiv8hi2 (op1, operands[1]));
+  emit_insn (gen_extendv8qiv8hi2 (op2, operands[2]));
+  emit_insn (gen_sdot_prodv8hi (op0, op1, op2, op3));
+
+  /* vec_perm (op0, 2, 3, 0, 1);  */
+  emit_insn (gen_sse2_pshufd (op0_1, op0, GEN_INT (78)));
+  emit_insn (gen_addv4si3 (op0, op0, op0_1));
+  emit_insn (gen_addv2si3 (operands[0], operands[3],
+  lowpart_subreg (V2SImode, op0, V4SImode)));
+}
+  DONE;
+
+})
+
+(define_expand "udot_prodv8qi"
+  [(match_operand:V2SI 0 "register_operand")
+   (match_operand:V8QI 1 "register_operand")
+   (match_operand:V8QI 2 "register_operand")
+   (match_operand:V2SI 3 "register_operand")]
+  "TARGET_MMX_WITH_SSE && TARGET_SSE4_1"
+{
+  operands[1] = force_reg (V8QImode, operands[1]);
+  operands[2] = force_reg (V8QImode, operands[2]);
+  operands[3] = force_reg (V2SImode, operands[3]);
+
+  if (TARGET_AVXVNNIINT8

[gcc r15-236] Extend usdot_prodv*qi with vpmaddwd when AVXVNNI/AVX512VNNI is not available.

2024-05-07 Thread hongtao Liu via Gcc-cvs
https://gcc.gnu.org/g:8b974f54393ab2d2d16a0051a68c155455a92aad

commit r15-236-g8b974f54393ab2d2d16a0051a68c155455a92aad
Author: liuhongt 
Date:   Mon Jan 8 15:13:41 2024 +0800

Extend usdot_prodv*qi with vpmaddwd when AVXVNNI/AVX512VNNI is not 
available.

gcc/ChangeLog:

* config/i386/sse.md (usdot_prodv*qi): Extend to VI1_AVX512
with vpmaddwd when avxvnni/avx512vnni is not available.

Diff:
---
 gcc/config/i386/sse.md | 55 +-
 1 file changed, 41 insertions(+), 14 deletions(-)

diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 1bf50726e83..f57f36ae380 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -29955,21 +29955,48 @@
 
 (define_expand "usdot_prod"
   [(match_operand: 0 "register_operand")
-   (match_operand:VI1_AVX512VNNI 1 "register_operand")
-   (match_operand:VI1_AVX512VNNI 2 "register_operand")
+   (match_operand:VI1_AVX512 1 "register_operand")
+   (match_operand:VI1_AVX512 2 "register_operand")
(match_operand: 3 "register_operand")]
-  "(( == 64 && TARGET_EVEX512)
-|| ((TARGET_AVX512VNNI && TARGET_AVX512VL)
-   || TARGET_AVXVNNI))"
-{
-  operands[1] = lowpart_subreg (mode,
-   force_reg (mode, operands[1]),
-   mode);
-  operands[2] = lowpart_subreg (mode,
-   force_reg (mode, operands[2]),
-   mode);
-  emit_insn (gen_vpdpbusd_ (operands[0], operands[3],
- operands[1], operands[2]));
+  "TARGET_SSE2"
+{
+  if ( == 64
+ ? TARGET_AVX512VNNI
+ : ((TARGET_AVX512VNNI && TARGET_AVX512VL) || TARGET_AVXVNNI))
+{
+  operands[1] = lowpart_subreg (mode,
+   force_reg (mode, operands[1]),
+   mode);
+  operands[2] = lowpart_subreg (mode,
+   force_reg (mode, operands[2]),
+   mode);
+  emit_insn (gen_vpdpbusd_ (operands[0], operands[3],
+ operands[1], operands[2]));
+}
+  else
+{
+  /* Emulate with vpdpwssd.  */
+  rtx op1_lo = gen_reg_rtx (mode);
+  rtx op1_hi = gen_reg_rtx (mode);
+  rtx op2_lo = gen_reg_rtx (mode);
+  rtx op2_hi = gen_reg_rtx (mode);
+
+  emit_insn (gen_vec_unpacku_lo_ (op1_lo, operands[1]));
+  emit_insn (gen_vec_unpacks_lo_ (op2_lo, operands[2]));
+  emit_insn (gen_vec_unpacku_hi_ (op1_hi, operands[1]));
+  emit_insn (gen_vec_unpacks_hi_ (op2_hi, operands[2]));
+
+  rtx res1 = gen_reg_rtx (mode);
+  rtx res2 = gen_reg_rtx (mode);
+  rtx sum = gen_reg_rtx (mode);
+
+  emit_move_insn (sum, CONST0_RTX (mode));
+  emit_insn (gen_sdot_prod (res1, op1_lo,
+   op2_lo, sum));
+  emit_insn (gen_sdot_prod (res2, op1_hi,
+   op2_hi, operands[3]));
+  emit_insn (gen_add3 (operands[0], res1, res2));
+}
   DONE;
 })


[gcc r15-234] Optimize 64-bit vector permutation with punpcklqdq + 128-bit vector pshuf.

2024-05-07 Thread hongtao Liu via Gcc-cvs
https://gcc.gnu.org/g:a9f642783853b60bb0a59562b8ab3ed10ec01641

commit r15-234-ga9f642783853b60bb0a59562b8ab3ed10ec01641
Author: liuhongt 
Date:   Wed Dec 20 11:54:43 2023 +0800

Optimize 64-bit vector permutation with punpcklqdq + 128-bit vector pshuf.

gcc/ChangeLog:

PR target/113090
* config/i386/i386-expand.cc
(expand_vec_perm_punpckldq_pshuf): New function.
(ix86_expand_vec_perm_const_1): Try
expand_vec_perm_punpckldq_pshuf for sequence of 2
instructions.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr113090.c: New test.

Diff:
---
 gcc/config/i386/i386-expand.cc   | 71 
 gcc/testsuite/gcc.target/i386/pr113090.c | 25 +++
 2 files changed, 96 insertions(+)

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index a6132911e6a..2f27bfb484c 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -21173,6 +21173,74 @@ expand_vec_perm_pshuflw_pshufhw (struct 
expand_vec_perm_d *d)
   return true;
 }
 
+/* Try to permute 2 64-bit vectors by punpckldq + 128-bit vector shuffle.  */
+static bool
+expand_vec_perm_punpckldq_pshuf (struct expand_vec_perm_d *d)
+{
+  if (GET_MODE_BITSIZE (d->vmode) != 64
+  || !TARGET_MMX_WITH_SSE
+  || d->one_operand_p)
+return false;
+
+  machine_mode widen_vmode;
+  switch (d->vmode)
+{
+/* pshufd.  */
+case E_V2SImode:
+  widen_vmode = V4SImode;
+  break;
+
+/* pshufd.  */
+case E_V2SFmode:
+  widen_vmode = V4SFmode;
+  break;
+
+case E_V4HImode:
+  widen_vmode = V8HImode;
+  /* pshufb.  */
+  if (!TARGET_SSSE3)
+   return false;
+  break;
+
+case E_V8QImode:
+  /* pshufb.  */
+  widen_vmode = V16QImode;
+  if (!TARGET_SSSE3)
+   return false;
+  break;
+
+default:
+  return false;
+}
+
+  if (d->testing_p)
+return true;
+
+  struct expand_vec_perm_d dperm;
+  dperm.target = gen_reg_rtx (widen_vmode);
+  rtx op0 = gen_reg_rtx (widen_vmode);
+  emit_move_insn (op0, gen_rtx_VEC_CONCAT (widen_vmode, d->op0, d->op1));
+  dperm.op0 = op0;
+  dperm.op1 = op0;
+  dperm.vmode = widen_vmode;
+  unsigned nelt = GET_MODE_NUNITS (widen_vmode);
+  dperm.nelt = nelt;
+  dperm.one_operand_p = true;
+  dperm.testing_p = false;
+
+  for (unsigned i = 0; i != nelt / 2; i++)
+{
+  dperm.perm[i] = d->perm[i];
+  dperm.perm[i + nelt / 2] = d->perm[i];
+}
+
+  gcc_assert (expand_vec_perm_1 (&dperm));
+  emit_move_insn (d->target, lowpart_subreg (d->vmode,
+dperm.target,
+dperm.vmode));
+  return true;
+}
+
 /* A subroutine of ix86_expand_vec_perm_const_1.  Try to simplify
the permutation using the SSSE3 palignr instruction.  This succeeds
when all of the elements in PERM fit within one vector and we merely
@@ -23685,6 +23753,9 @@ ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d 
*d)
   if (expand_vec_perm_shufps_shufps (d))
 return true;
 
+  if (expand_vec_perm_punpckldq_pshuf (d))
+return true;
+
   /* Try sequences of three instructions.  */
 
   if (expand_vec_perm_even_odd_pack (d))
diff --git a/gcc/testsuite/gcc.target/i386/pr113090.c 
b/gcc/testsuite/gcc.target/i386/pr113090.c
new file mode 100644
index 000..0f0b7cc0084
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr113090.c
@@ -0,0 +1,25 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse4.1" } */
+/* { dg-final { scan-assembler-times "pshufd" 3 } } */
+
+typedef int v2si __attribute__((vector_size(8)));
+typedef short v4hi __attribute__((vector_size(8)));
+typedef char v8qi __attribute__((vector_size(8)));
+
+v2si
+foo (v2si a, v2si b)
+{
+return __builtin_shufflevector (a, b, 1, 2);
+}
+
+v4hi
+foo1 (v4hi a, v4hi b)
+{
+  return __builtin_shufflevector (a, b, 2, 3, 4, 5);
+}
+
+v8qi
+foo2 (v8qi a, v8qi b)
+{
+  return __builtin_shufflevector (a, b, 4, 5, 6, 7, 8, 9, 10, 11);
+}


[gcc r15-238] ada: Update comment about implicit inputs of Depends contract

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:f18a632749b8b2ccfcf83454f60cfeb9958c36d2

commit r15-238-gf18a632749b8b2ccfcf83454f60cfeb9958c36d2
Author: Piotr Trojanek 
Date:   Thu Jan 4 19:26:12 2024 +0100

ada: Update comment about implicit inputs of Depends contract

Sync comment with the updated SPARK RM rules.

gcc/ada/

* sem_prag.adb (Collect_Global_Item): Update comment.

Diff:
---
 gcc/ada/sem_prag.adb | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 5764992237b..0eb4450dba3 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -31669,8 +31669,7 @@ package body Sem_Prag is
Append_New_Elmt (Formal, Subp_Outputs);
 
--  OUT parameters can act as inputs when the related type is
-   --  tagged, unconstrained array, unconstrained record, or record
-   --  with unconstrained components.
+   --  tagged, unconstrained array or unconstrained record.
 
if Ekind (Formal) = E_Out_Parameter
  and then Is_Unconstrained_Or_Tagged_Item (Formal)


[gcc r15-239] ada: Accept constants of access types as globals of side-effect function

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:262d6de0a97d88ea1edbab51d4cd2b3aa36f91a5

commit r15-239-g262d6de0a97d88ea1edbab51d4cd2b3aa36f91a5
Author: Piotr Trojanek 
Date:   Thu Jan 4 19:58:07 2024 +0100

ada: Accept constants of access types as globals of side-effect function

Complete support for functions with side-effects.

gcc/ada/

* sem_prag.adb (Analyze_Global_Item): Handle side-effect
functions like procedures.

Diff:
---
 gcc/ada/sem_prag.adb | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 0eb4450dba3..fa2a4cbed39 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -2860,7 +2860,9 @@ package body Sem_Prag is
   | E_Procedure
   | E_Generic_Procedure
   | E_Task_Type
- or else Is_Single_Task_Object (Spec_Id))
+ or else Is_Single_Task_Object (Spec_Id)
+ or else
+   Is_Function_With_Side_Effects (Spec_Id))
  then
 null;
  else


[gcc r15-242] ada: Fix bug in overloaded selected_components in aspect_specifications

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:d4b41cc4b02e365fc749dc90975af4d2360a8fb3

commit r15-242-gd4b41cc4b02e365fc749dc90975af4d2360a8fb3
Author: Bob Duff 
Date:   Fri Jan 5 10:40:00 2024 -0500

ada: Fix bug in overloaded selected_components in aspect_specifications

This patch fixes a bug where if a selected_component X.Y appears in an
aspect_specification, and there are two or more overloaded Y's in X,
then it can choose the wrong one, leading to subsequent type errors.
It was always picking the last declaration of Y, and leaving Entity
set to that. We now reset Entity (as for the already-existing code
for N_Identifier just below).

Note that Resolve_Aspect_Expressions is called only for
aspect_specifications, and not even all aspect_specifications,
so the bug didn't occur for other names. For example,
Resolve_Aspect_Expressions is not called for aspect_specifications
in the visible part of a library package if there is no private part.

gcc/ada/

* sem_ch13.adb (Resolve_Name): This is called only for names in
aspect_specifications. If the name is an overloaded
selected_component, reset the Entity. Note that this was already
done for N_Identifier in the code just below.

Diff:
---
 gcc/ada/sem_ch13.adb | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index ed0e61bd7b2..c16a7710594 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -15925,12 +15925,20 @@ package body Sem_Ch13 is
   and then Chars (Prefix (N)) /= Chars (E)
 then
Find_Selected_Component (N);
+
+   --  Reset the Entity if N is overloaded since the entity might
+   --  not be the correct one; allow later resolution to set it
+   --  properly.
+
+   if Is_Overloaded (N) then
+  Set_Entity (N, Empty);
+   end if;
 end if;
 
 return Skip;
 
- --  Resolve identifiers that are not selectors in parameter
- --  associations (these are never resolved by visibility).
+ --  Resolve identifiers, but not selectors in parameter associations;
+ --  the selectors are never resolved by visibility.
 
  elsif Nkind (N) = N_Identifier
and then Chars (N) /= Chars (E)
@@ -15939,8 +15947,7 @@ package body Sem_Ch13 is
  then
 Find_Direct_Name (N);
 
---  Reset the Entity if N is overloaded since the entity may not
---  be the correct one.
+--  Reset the Entity as above for selected_components
 
 if Is_Overloaded (N) then
Set_Entity (N, Empty);


[gcc r15-243] ada: Minor comment improvement

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:26b2fa8d30b5fd84a371469721af7b8f5a41f06a

commit r15-243-g26b2fa8d30b5fd84a371469721af7b8f5a41f06a
Author: Bob Duff 
Date:   Fri Jan 5 17:18:43 2024 -0500

ada: Minor comment improvement

Clarify comment about selectors.

gcc/ada/

* sem_ch13.adb (Resolve_Name): Clarify comment.

Diff:
---
 gcc/ada/sem_ch13.adb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index c16a7710594..1f3f8277294 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -15938,7 +15938,7 @@ package body Sem_Ch13 is
 return Skip;
 
  --  Resolve identifiers, but not selectors in parameter associations;
- --  the selectors are never resolved by visibility.
+ --  such selectors are never resolved by visibility.
 
  elsif Nkind (N) = N_Identifier
and then Chars (N) /= Chars (E)


[gcc r15-244] ada: Reject non-statically compatible extended return statement

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:15a8d0dd59dd8c92600a89b6f5fe339e5ce74a11

commit r15-244-g15a8d0dd59dd8c92600a89b6f5fe339e5ce74a11
Author: Javier Miranda 
Date:   Sun Jan 7 13:37:15 2024 +

ada: Reject non-statically compatible extended return statement

Add missing check of RM 6.5(5.3/5): when the result subtype of the
function is defined by a subtype mark, the subtype defined by the
subtype indication of the extended return statement shall be
statically compatible with the result subtype of the function.

gcc/ada/

* sem_ch3.adb (Check_Return_Subtype_Indication): Add missing check
on statically compatible subtypes.
* sem_eval.adb (Subtypes_Statically_Compatible): Ensure that both
types are either scalar types or access types to evaluate this
predicate.

Diff:
---
 gcc/ada/sem_ch3.adb  | 25 +
 gcc/ada/sem_eval.adb |  4 ++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 578c57c10fa..c15f0bfc283 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -4129,6 +4129,31 @@ package body Sem_Ch3 is
if not Subtypes_Statically_Match (Obj_Typ, R_Typ) then
   Error_No_Match (Indic);
end if;
+
+--  If the result subtype of the function is defined by a
+--  subtype_mark, the return_subtype_indication shall be a
+--  subtype_indication. The subtype defined by the subtype_
+--  indication shall be statically compatible with the result
+--  subtype of the function (RM 6.5(5.3/5)).
+
+--  We exclude the extended return statement of the predefined
+--  stream input to avoid reporting spurious errors, because its
+--  code is expanded on the basis of the base type (see subprogram
+--  Stream_Base_Type).
+
+elsif Nkind (Indic) = N_Subtype_Indication
+  and then not Subtypes_Statically_Compatible (Obj_Typ, R_Typ)
+  and then not Is_TSS (Func_Id, TSS_Stream_Input)
+then
+   Error_Msg_N
+ ("result subtype must be statically compatible with the " &
+  "function result type", Indic);
+
+   if not Predicates_Compatible (Obj_Typ, R_Typ) then
+  Error_Msg_NE
+("\predicate on result subtype is not compatible with &",
+ Indic, R_Typ);
+   end if;
 end if;
 
  --  All remaining cases are illegal
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 42f2668bb93..03006b63070 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -6507,7 +6507,7 @@ package body Sem_Eval is
 
   --  Scalar types
 
-  elsif Is_Scalar_Type (T1) then
+  elsif Is_Scalar_Type (T1) and then Is_Scalar_Type (T2) then
 
  --  Definitely compatible if we match
 
@@ -6560,7 +6560,7 @@ package body Sem_Eval is
 
   --  Access types
 
-  elsif Is_Access_Type (T1) then
+  elsif Is_Access_Type (T1) and then Is_Access_Type (T2) then
  return
(not Is_Constrained (T2)
  or else Subtypes_Statically_Match


[gcc r15-245] ada: Fix spurious error on generic state in SPARK

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:d82909fed0a90a2950e2413429efce655ecba8d2

commit r15-245-gd82909fed0a90a2950e2413429efce655ecba8d2
Author: Yannick Moy 
Date:   Mon Jan 8 09:53:58 2024 +0100

ada: Fix spurious error on generic state in SPARK

The public state of a generic package needs not be part of the state of
the enclosing unit, only the state of instantiations need to be accounted
for in the enclosing package. Now fixed.

gcc/ada/

* sem_util.adb (Find_Placement_In_State_Space): Stop search for
placement when reaching the public state of a generic package.

Diff:
---
 gcc/ada/sem_util.adb | 8 
 1 file changed, 8 insertions(+)

diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 3af029fd9a3..d629c76fd47 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -9103,6 +9103,14 @@ package body Sem_Util is
Placement := Private_State_Space;
return;
 
+--  The item or its enclosing package appear in the visible state
+--  space of a generic package.
+
+elsif Ekind (Pack_Id) = E_Generic_Package then
+   Placement := Not_In_Package;
+   Pack_Id := Empty;
+   return;
+
 --  When the item appears in the visible state space of a package,
 --  continue to climb the scope stack as this may not be the final
 --  state space.


[gcc r15-249] ada: Fix LTO type mismatches in GNAT.Sockets.Thin

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:d59f383a90487d081e1754e529a8ed41837767ec

commit r15-249-gd59f383a90487d081e1754e529a8ed41837767ec
Author: Eric Botcazou 
Date:   Tue Jan 9 16:25:09 2024 +0100

ada: Fix LTO type mismatches in GNAT.Sockets.Thin

The default implementation of GNAT.Sockets.Thin is mainly used on Linux and
the socklen_t type used in various routines of the BSD sockets C API is a
typedef for unsigned int there, so importing it as Interface.C.int will be
flagged as a type mismatch during LTO compilation.

gcc/ada/

* libgnat/g-socthi.ads (C_Bind): Turn into inline function.
(C_Getpeername): Likewise.
(C_Getsockname): Likewise.
(C_Getsockopt): Likewise.
(C_Setsockopt): Likewise.
(Nonreentrant_Gethostbyaddr): Likewise.
* libgnat/g-socthi.adb (Syscall_Accept): Adjust profile.
(Syscall_Connect): Likewise.
(Syscall_Recvfrom): Likewise.
(Syscall_Sendto): Likewise.
(C_Bind): New function.
(C_Accept): Adjust to above change for profiles.
(C_Connect): Likewise.
(C_Getpeername): New function.
(C_Getsockname): Likewise.
(C_Getsockopt): Likewise.
(C_Recvfrom):  Adjust to above change for profiles.
(C_Setsockopt): New function.
(Nonreentrant_Gethostbyaddr): Likewise.

Diff:
---
 gcc/ada/libgnat/g-socthi.adb | 176 ---
 gcc/ada/libgnat/g-socthi.ads |  12 +--
 2 files changed, 170 insertions(+), 18 deletions(-)

diff --git a/gcc/ada/libgnat/g-socthi.adb b/gcc/ada/libgnat/g-socthi.adb
index dce2717cda3..f8ddcc7fca6 100644
--- a/gcc/ada/libgnat/g-socthi.adb
+++ b/gcc/ada/libgnat/g-socthi.adb
@@ -62,13 +62,13 @@ package body GNAT.Sockets.Thin is
function Syscall_Accept
  (S   : C.int;
   Addr: System.Address;
-  Addrlen : not null access C.int) return C.int;
+  Addrlen : not null access C.unsigned) return C.int;
pragma Import (C, Syscall_Accept, "accept");
 
function Syscall_Connect
  (S   : C.int;
   Name: System.Address;
-  Namelen : C.int) return C.int;
+  Namelen : C.unsigned) return C.int;
pragma Import (C, Syscall_Connect, "connect");
 
function Syscall_Recv
@@ -84,7 +84,7 @@ package body GNAT.Sockets.Thin is
   Len : C.size_t;
   Flags   : C.int;
   From: System.Address;
-  Fromlen : not null access C.int) return System.CRTL.ssize_t;
+  Fromlen : not null access C.unsigned) return System.CRTL.ssize_t;
pragma Import (C, Syscall_Recvfrom, "recvfrom");
 
function Syscall_Recvmsg
@@ -105,7 +105,7 @@ package body GNAT.Sockets.Thin is
   Len   : C.size_t;
   Flags : C.int;
   To: System.Address;
-  Tolen : C.int) return System.CRTL.ssize_t;
+  Tolen : C.unsigned) return System.CRTL.ssize_t;
pragma Import (C, Syscall_Sendto, "sendto");
 
function Syscall_Socket
@@ -125,6 +125,25 @@ package body GNAT.Sockets.Thin is
function Non_Blocking_Socket (S : C.int) return Boolean;
procedure Set_Non_Blocking_Socket (S : C.int; V : Boolean);
 
+   
+   -- C_Bind --
+   
+
+   function C_Bind
+ (S   : C.int;
+  Name: System.Address;
+  Namelen : C.int) return C.int
+   is
+  function Bind
+(S   : C.int;
+ Name: System.Address;
+ Namelen : C.unsigned) return C.int
+  with Import, Convention => C, External_Name => "bind";
+
+   begin
+  return Bind (S, Name, C.unsigned (Namelen));
+   end C_Bind;
+
--
-- C_Accept --
--
@@ -134,15 +153,18 @@ package body GNAT.Sockets.Thin is
   Addr: System.Address;
   Addrlen : not null access C.int) return C.int
is
-  R   : C.int;
-  Val : aliased C.int := 1;
+  R : C.int;
+  U_Addrlen : aliased C.unsigned;
+  Val   : aliased C.int := 1;
 
   Discard : C.int;
   pragma Warnings (Off, Discard);
 
begin
+  U_Addrlen := C.unsigned (Addrlen.all);
+
   loop
- R := Syscall_Accept (S, Addr, Addrlen);
+ R := Syscall_Accept (S, Addr, U_Addrlen'Unchecked_Access);
  exit when SOSC.Thread_Blocking_IO
or else R /= Failure
or else Non_Blocking_Socket (S)
@@ -150,6 +172,8 @@ package body GNAT.Sockets.Thin is
  delay Quantum;
   end loop;
 
+  Addrlen.all := C.int (U_Addrlen);
+
   if not SOSC.Thread_Blocking_IO
 and then R /= Failure
   then
@@ -177,7 +201,7 @@ package body GNAT.Sockets.Thin is
   Res : C.int;
 
begin
-  Res := Syscall_Connect (S, Name, Namelen);
+  Res := Syscall_Connect (S, Name, C.unsigned (Namelen));
 
   if SOSC.Thread_Blocking_IO
 or else Res /= Failure
@@ -215,7 +239,7 @@ package body GNAT.Sockets.Thin is
  end loop;
   end;
 
-  Res := Syscall_Co

[gcc r15-253] ada: Fix crash on body postcondition

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:e29c2dabc362c47e02374e4f793ffd48a0cfb4cb

commit r15-253-ge29c2dabc362c47e02374e4f793ffd48a0cfb4cb
Author: Bob Duff 
Date:   Fri Jan 12 08:12:27 2024 -0500

ada: Fix crash on body postcondition

This patch fixes a bug where the compiler could crash on a postcondition
on a subprogram body (i.e. a body that "acts as spec"), if the
postcondition contains 'Old attributes that use the Ada 2022 feature
that allows certain conditionals (see RM-6.1.1).

The main bug fix here is in exp_attr.adb to set Ins_Node properly in the
Acts_As_Spec case. Otherwise, the initialization of the 'Old temp would
occur before the declaration, which gigi does not like.

gcc/ada/

* exp_attr.adb (Attribute_Old): The 'Old attribute we are
processing here is in a postcondition, which cannot be inside the
"Wrapped_Statements" of the subprogram with that postcondition. So
remove the loop labeled "Climb the parent chain looking for
subprogram _Wrapped_Statements". The only way this loop could find
a Subp is if we are nested inside a subprogram that also has a
postcondition, and in that case we would find the wrong (outer)
one. In any case, Subp is set to Empty after the loop, so all
subsequent tests for Present (Subp) are necessarily False; remove
them and the corresponding code. Set Ins_Node unconditionally (to
the right thing). Remove obsolete comments.
* sem_util.adb (Determining_Expressions): Fix assertion;
Pragma_Test_Case was missing.
(Eligible_For_Conditional_Evaluation): Fix assert that could fail
in case of errors.
* libgnat/s-valspe.ads: Remove pragma Unevaluated_Use_Of_Old;
there are no uses of 'Old in this package.

Diff:
---
 gcc/ada/exp_attr.adb | 72 ++--
 gcc/ada/libgnat/s-valspe.ads |  2 --
 gcc/ada/sem_util.adb |  6 ++--
 3 files changed, 13 insertions(+), 67 deletions(-)

diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index a8e06f0005e..63b311c1b89 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -4988,7 +4988,6 @@ package body Exp_Attr is
  CW_Typ  : Entity_Id;
  Decl: Node_Id;
  Ins_Nod : Node_Id;
- Subp: Node_Id;
  Temp: Entity_Id;
 
  use Old_Attr_Util.Conditional_Evaluation;
@@ -5007,27 +5006,6 @@ package body Exp_Attr is
 return;
  end if;
 
- --  Climb the parent chain looking for subprogram _Wrapped_Statements
-
- Subp := N;
- while Present (Subp) loop
-exit when Nkind (Subp) = N_Subprogram_Body
-  and then Chars (Defining_Entity (Subp))
- = Name_uWrapped_Statements;
-
---  If assertions are disabled, no need to create the declaration
---  that preserves the value. The postcondition pragma in which
---  'Old appears will be checked or disabled according to the
---  current policy in effect.
-
-if Nkind (Subp) = N_Pragma and then not Is_Checked (Subp) then
-   return;
-end if;
-
-Subp := Parent (Subp);
- end loop;
- Subp := Empty;
-
  --  'Old can only appear in the case where local contract-related
  --  wrapper has been generated with the purpose of wrapping the
  --  original declarations and statements.
@@ -5040,44 +5018,20 @@ package body Exp_Attr is
  Mutate_Ekind (Temp, E_Constant);
  Set_Stores_Attribute_Old_Prefix (Temp);
 
- --  Push the scope of the related subprogram where _Postcondition
- --  resides as this ensures that the object will be analyzed in the
- --  proper context.
-
- if Present (Subp) then
-Push_Scope (Scope (Defining_Entity (Subp)));
-
- --  No need to push the scope when generating C code since the
- --  _Postcondition procedure has been inlined.
-
- else
-null;
- end if;
-
  --  Locate the insertion place of the internal temporary that saves
  --  the 'Old value.
 
- if Present (Subp) then
-Ins_Nod := Subp;
+ Ins_Nod := N;
+ while Nkind (Ins_Nod) /= N_Subprogram_Body loop
+Ins_Nod := Parent (Ins_Nod);
+ end loop;
 
- --  General case where the postcondition checks occur after the call
- --  to _Wrapped_Statements.
+ pragma Assert (Present (Wrapped_Statements
+   (if Acts_As_Spec (Ins_Nod)
+  then Defining_Unit_Name (Specification (Ins_Nod))
+  else Corresponding_Spec (Ins_Nod;
 
- else
-Ins_Nod := N;
-while Nkind (Ins_Nod) /= N_Subprogram_Body loop
-   Ins_Nod := Parent (Ins_

[gcc r15-254] ada: Fix typo in documentation comment

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:07f61618c7b7094ecb7d39b8bb4122efb02a3ef1

commit r15-254-g07f61618c7b7094ecb7d39b8bb4122efb02a3ef1
Author: Ronan Desplanques 
Date:   Mon Jan 15 17:38:44 2024 +0100

ada: Fix typo in documentation comment

gcc/ada/

* sinfo.ads: Fix typo.

Diff:
---
 gcc/ada/sinfo.ads | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 4e977152cd0..06b9ad0884e 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -4272,7 +4272,7 @@ package Sinfo is
   --  Etype
 
   -
-  --  3.4.5 Container_Aggregates --
+  --  4.3.5 Container_Aggregates --
   -
 
   --  ITERATED_ELEMENT_ASSOCIATION ::=


[gcc r15-256] ada: Add Global contracts to Ada.Numerics.Generic_Elementary_Functions

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:6e0494ecf00540b996014e3bc6db6a2d6529c6d7

commit r15-256-g6e0494ecf00540b996014e3bc6db6a2d6529c6d7
Author: Joffrey Huguet 
Date:   Mon Jan 15 17:20:47 2024 +0100

ada: Add Global contracts to Ada.Numerics.Generic_Elementary_Functions

GNATprove raised warnings about unspecified Global contracts when
using functions from an instance of
Ada.Numerics.Generic_Elementary_Functions. This patch adds null Global
contracts to all subprograms.

gcc/ada/

* libgnat/a-ngelfu.ads (Sqrt): Add Global contracts.
(Log): Likewise.
(Exp): Likewise.
("**"): Likewise.
(Sin): Likewise.
(Cos): Likewise.
(Tan): Likewise.
(Cot): Likewise.
(Arcsin): Likewise.
(Arccos): Likewise.
(Arctan): Likewise.
(Arccot): Likewise.
(Sinh): Likewise.
(Cosh): Likewise.
(Tanh): Likewise.
(Coth): Likewise.
(Arcsinh): Likewise.
(Arccosh): Likewise.
(Arctanh): Likewise.
(Arccoth): Likewise.

Diff:
---
 gcc/ada/libgnat/a-ngelfu.ads | 120 ++-
 1 file changed, 74 insertions(+), 46 deletions(-)

diff --git a/gcc/ada/libgnat/a-ngelfu.ads b/gcc/ada/libgnat/a-ngelfu.ads
index 0dfea78aa90..774c2c6152c 100644
--- a/gcc/ada/libgnat/a-ngelfu.ads
+++ b/gcc/ada/libgnat/a-ngelfu.ads
@@ -51,8 +51,9 @@ is
pragma Assertion_Policy (Pre => Ignore);
 
function Sqrt (X : Float_Type'Base) return Float_Type'Base with
- Pre  => X >= 0.0,
- Post => Sqrt'Result >= 0.0
+ Global => null,
+ Pre=> X >= 0.0,
+ Post   => Sqrt'Result >= 0.0
and then (if X = 0.0 then Sqrt'Result = 0.0)
and then (if X = 1.0 then Sqrt'Result = 1.0)
 
@@ -74,19 +75,23 @@ is
and then (if X >= Float_Type'Succ (0.0) then Sqrt'Result > 0.0);
 
function Log (X : Float_Type'Base) return Float_Type'Base with
- Pre  => X > 0.0,
- Post => (if X = 1.0 then Log'Result = 0.0);
+ Global => null,
+ Pre=> X > 0.0,
+ Post   => (if X = 1.0 then Log'Result = 0.0);
 
function Log (X, Base : Float_Type'Base) return Float_Type'Base with
- Pre  => X > 0.0 and Base > 0.0 and Base /= 1.0,
- Post => (if X = 1.0 then Log'Result = 0.0);
+ Global => null,
+ Pre=> X > 0.0 and Base > 0.0 and Base /= 1.0,
+ Post   => (if X = 1.0 then Log'Result = 0.0);
 
function Exp (X : Float_Type'Base) return Float_Type'Base with
- Post => (if X = 0.0 then Exp'Result = 1.0);
+ Global => null,
+ Post   => (if X = 0.0 then Exp'Result = 1.0);
 
function "**" (Left, Right : Float_Type'Base) return Float_Type'Base with
- Pre  => (if Left = 0.0 then Right > 0.0) and Left >= 0.0,
- Post => "**"'Result >= 0.0
+ Global => null,
+ Pre=> (if Left = 0.0 then Right > 0.0) and Left >= 0.0,
+ Post   => "**"'Result >= 0.0
and then (if Right = 0.0 then "**"'Result = 1.0)
and then (if Right = 1.0 then "**"'Result = Left)
and then (if Left  = 1.0 then "**"'Result = 1.0)
@@ -94,115 +99,138 @@ is
 
function Sin (X : Float_Type'Base) return Float_Type'Base with
  Inline,
- Post => Sin'Result in -1.0 .. 1.0
+ Global => null,
+ Post   => Sin'Result in -1.0 .. 1.0
and then (if X = 0.0 then Sin'Result = 0.0);
 
function Sin (X, Cycle : Float_Type'Base) return Float_Type'Base with
- Pre  => Cycle > 0.0,
- Post => Sin'Result in -1.0 .. 1.0
+ Global => null,
+ Pre=> Cycle > 0.0,
+ Post   => Sin'Result in -1.0 .. 1.0
and then (if X = 0.0 then Sin'Result = 0.0);
 
function Cos (X : Float_Type'Base) return Float_Type'Base with
  Inline,
- Post => Cos'Result in -1.0 .. 1.0
+ Global => null,
+ Post   => Cos'Result in -1.0 .. 1.0
and then (if X = 0.0 then Cos'Result = 1.0);
 
function Cos (X, Cycle : Float_Type'Base) return Float_Type'Base with
- Pre  => Cycle > 0.0,
- Post => Cos'Result in -1.0 .. 1.0
+ Global => null,
+ Pre=> Cycle > 0.0,
+ Post   => Cos'Result in -1.0 .. 1.0
and then (if X = 0.0 then Cos'Result = 1.0);
 
function Tan (X : Float_Type'Base) return Float_Type'Base with
- Post => (if X = 0.0 then Tan'Result = 0.0);
+ Global => null,
+ Post   => (if X = 0.0 then Tan'Result = 0.0);
 
function Tan (X, Cycle : Float_Type'Base) return Float_Type'Base with
- Pre  => Cycle > 0.0
+ Global => null,
+ Pre=> Cycle > 0.0
and then abs Float_Type'Base'Remainder (X, Cycle) /= 0.25 * Cycle,
- Post => (if X = 0.0 then Tan'Result = 0.0);
+ Post   => (if X = 0.0 then Tan'Result = 0.0);
 
function Cot (X : Float_Type'Base) return Float_Type'Base with
- Pre => X /= 0.0;
+ Global => null,
+ Pre=> X /= 0.0;
 
function Cot (X, Cycle : Float_Type'Base) return Float_Type'Base with
-  

[gcc r15-261] ada: Cleanup detection of per-object constraints in inlining for SPARK

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:36ddd8c0988164e2299f1de57866931386e4ceea

commit r15-261-g36ddd8c0988164e2299f1de57866931386e4ceea
Author: Piotr Trojanek 
Date:   Tue Jan 16 13:08:18 2024 +0100

ada: Cleanup detection of per-object constraints in inlining for SPARK

In GNATprove mode we didn't inline subprograms whose formal parameters
was of a record type with constraints depending on discriminants. Now
this is extended to formal parameters with per-object constraints,
regardless if they come from references to discriminants or from
attributes prefixed by the current type instance.

gcc/ada/

* inline.adb (Has_Formal_With_Per_Object_Constrained_Component):
Use flag Has_Per_Object_Constraint which is set by analysis;
rename for consistency.

Diff:
---
 gcc/ada/inline.adb | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb
index b7a6cc90cd2..169a22c0ba5 100644
--- a/gcc/ada/inline.adb
+++ b/gcc/ada/inline.adb
@@ -1555,7 +1555,7 @@ package body Inline is
   --  a return type of a deep type: either an access type or a composite
   --  type containing an access type.
 
-  function Has_Formal_With_Discriminant_Dependent_Fields
+  function Has_Formal_With_Per_Object_Constrained_Component
 (Id : Entity_Id) return Boolean;
   --  Returns true if the subprogram has at least one formal parameter of
   --  an unconstrained record type with per-object constraints on component
@@ -1701,23 +1701,23 @@ package body Inline is
  return False;
   end Has_Formal_Or_Result_Of_Deep_Type;
 
-  ---
-  -- Has_Formal_With_Discriminant_Dependent_Fields --
-  ---
+  --
+  -- Has_Formal_With_Per_Object_Constrained_Component --
+  --
 
-  function Has_Formal_With_Discriminant_Dependent_Fields
+  function Has_Formal_With_Per_Object_Constrained_Component
 (Id : Entity_Id) return Boolean
   is
- function Has_Discriminant_Dependent_Component
+ function Has_Per_Object_Constrained_Component
(Typ : Entity_Id) return Boolean;
  --  Determine whether unconstrained record type Typ has at least one
  --  component that depends on a discriminant.
 
  --
- -- Has_Discriminant_Dependent_Component --
+ -- Has_Per_Object_Constrained_Component --
  --
 
- function Has_Discriminant_Dependent_Component
+ function Has_Per_Object_Constrained_Component
(Typ : Entity_Id) return Boolean
  is
 Comp : Entity_Id;
@@ -1728,7 +1728,7 @@ package body Inline is
 
 Comp := First_Component (Typ);
 while Present (Comp) loop
-   if Has_Discriminant_Dependent_Constraint (Comp) then
+   if Has_Per_Object_Constraint (Comp) then
   return True;
end if;
 
@@ -1736,7 +1736,7 @@ package body Inline is
 end loop;
 
 return False;
- end Has_Discriminant_Dependent_Component;
+ end Has_Per_Object_Constrained_Component;
 
  --  Local variables
 
@@ -1745,7 +1745,7 @@ package body Inline is
  Formal_Typ : Entity_Id;
 
   --  Start of processing for
-  --  Has_Formal_With_Discriminant_Dependent_Fields
+  --  Has_Formal_With_Per_Object_Constrained_Component
 
   begin
  --  Inspect all parameters of the subprogram looking for a formal
@@ -1758,7 +1758,7 @@ package body Inline is
 
 if Is_Record_Type (Formal_Typ)
   and then not Is_Constrained (Formal_Typ)
-  and then Has_Discriminant_Dependent_Component (Formal_Typ)
+  and then Has_Per_Object_Constrained_Component (Formal_Typ)
 then
return True;
 end if;
@@ -1767,7 +1767,7 @@ package body Inline is
  end loop;
 
  return False;
-  end Has_Formal_With_Discriminant_Dependent_Fields;
+  end Has_Formal_With_Per_Object_Constrained_Component;
 
   
   -- Has_Hide_Unhide_Annotation --
@@ -2063,7 +2063,7 @@ package body Inline is
   --  in record component accesses (in particular with records containing
   --  packed arrays).
 
-  elsif Has_Formal_With_Discriminant_Dependent_Fields (Id) then
+  elsif Has_Formal_With_Per_Object_Constrained_Component (Id) then
  return False;
 
   --  Do not inline subprograms with a formal parameter or return type of


[gcc r15-259] ada: Reduce scope in the analysis of access attributes

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:a1e6fdc0773bd9d7e7a2e2a9135c2c6c982b67af

commit r15-259-ga1e6fdc0773bd9d7e7a2e2a9135c2c6c982b67af
Author: Piotr Trojanek 
Date:   Tue Jan 16 13:05:22 2024 +0100

ada: Reduce scope in the analysis of access attributes

Code cleanup; semantics is unaffected.

gcc/ada/

* sem_attr.adb (Analyze_Access_Attribute): Move code to IF
branch where its result is used.

Diff:
---
 gcc/ada/sem_attr.adb | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index c17f67356ef..6140cc0c0d6 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -982,15 +982,16 @@ package body Sem_Attr is
  if Is_Entity_Name (P) then
 Typ := Entity (P);
 
---  The reference may appear in an aggregate that has been expanded
---  into a loop. Locate scope of type definition, if any.
+if Is_Type (Typ) then
 
-Scop := Current_Scope;
-while Ekind (Scop) = E_Loop loop
-   Scop := Scope (Scop);
-end loop;
+   --  The reference may appear in an aggregate that has been
+   --  expanded into a loop. Locate scope of type definition,
+   --  if any.
 
-if Is_Type (Typ) then
+   Scop := Current_Scope;
+   while Ekind (Scop) = E_Loop loop
+  Scop := Scope (Scop);
+   end loop;
 
--  OK if we are within the scope of a limited type
--  let's mark the component as having per object constraint


[gcc r15-263] ada: Remove redundant guard against empty list of declarations

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:33f560e2722912fd86cd2c9b8584bdb81726dae8

commit r15-263-g33f560e2722912fd86cd2c9b8584bdb81726dae8
Author: Piotr Trojanek 
Date:   Mon Aug 22 21:36:11 2022 +0200

ada: Remove redundant guard against empty list of declarations

Code cleanup.

gcc/ada/

* inline.adb (Has_Single_Return): Remove redundant check for
empty list, because First works also for empty list.

Diff:
---
 gcc/ada/inline.adb | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb
index 169a22c0ba5..a628a59e145 100644
--- a/gcc/ada/inline.adb
+++ b/gcc/ada/inline.adb
@@ -4809,8 +4809,7 @@ package body Inline is
 
   else
  return
-   Present (Declarations (N))
- and then Present (First (Declarations (N)))
+   Present (First (Declarations (N)))
  and then Nkind (First (Declarations (N))) = N_Object_Declaration
  and then Entity (Expression (Return_Statement)) =
 Defining_Identifier (First (Declarations (N)));


[gcc r15-237] Mention that some options are turned on by `-Ofast` in their descriptions [PR97263]

2024-05-07 Thread Andrew Pinski via Gcc-cvs
https://gcc.gnu.org/g:0920e64ffa55adb063174559b274b0a521f34934

commit r15-237-g0920e64ffa55adb063174559b274b0a521f34934
Author: Andrew Pinski 
Date:   Mon May 6 14:14:41 2024 -0700

Mention that some options are turned on by `-Ofast` in their descriptions 
[PR97263]

Like was done for -ffast-math in r0-105946-ga570fc16fa8056, we should
document that -Ofast enables -fmath-errno, -funsafe-math-optimizations,
-finite-math-only, -fno-trapping-math in their documentation.

Note this changes the stronger "must not" to be "is not" for 
-fno-trapping-math
since we do enable it for -Ofast already.

gcc/ChangeLog:

PR middle-end/97263
* doc/invoke.texi(fmath-errno): Document it is turned on
with -Ofast.
(funsafe-math-optimizations): Likewise.
(ffinite-math-only): Likewise.
(fno-trapping-math): Likewise and use less strong language.

Signed-off-by: Andrew Pinski 

Diff:
---
 gcc/doc/invoke.texi | 41 ++---
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index dc4c5a3189d..ed03a613b4b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14996,11 +14996,12 @@ with a single instruction, e.g., @code{sqrt}.  A 
program that relies on
 IEEE exceptions for math error handling may want to use this flag
 for speed while maintaining IEEE arithmetic compatibility.
 
-This option is not turned on by any @option{-O} option since
-it can result in incorrect output for programs that depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions. It may, however, yield faster code for programs
-that do not require the guarantees of these specifications.
+This option is not turned on by any @option{-O} option  besides
+@option{-Ofast} since it can result in incorrect output for
+programs that depend on an exact implementation of IEEE or
+ISO rules/specifications for math functions. It may, however,
+yield faster code for programs that do not require the guarantees
+of these specifications.
 
 The default is @option{-fmath-errno}.
 
@@ -15017,11 +15018,12 @@ ANSI standards.  When used at link time, it may 
include libraries
 or startup files that change the default FPU control word or other
 similar optimizations.
 
-This option is not turned on by any @option{-O} option since
-it can result in incorrect output for programs that depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions. It may, however, yield faster code for programs
-that do not require the guarantees of these specifications.
+This option is not turned on by any @option{-O} option besides
+@option{-Ofast} since it can result in incorrect output
+for programs that depend on an exact implementation of IEEE
+or ISO rules/specifications for math functions. It may, however,
+yield faster code for programs that do not require the guarantees
+of these specifications.
 Enables @option{-fno-signed-zeros}, @option{-fno-trapping-math},
 @option{-fassociative-math} and @option{-freciprocal-math}.
 
@@ -15061,11 +15063,12 @@ The default is @option{-fno-reciprocal-math}.
 Allow optimizations for floating-point arithmetic that assume
 that arguments and results are not NaNs or +-Infs.
 
-This option is not turned on by any @option{-O} option since
-it can result in incorrect output for programs that depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions. It may, however, yield faster code for programs
-that do not require the guarantees of these specifications.
+This option is not turned on by any @option{-O} option besides
+@option{-Ofast} since it can result in incorrect output
+for programs that depend on an exact implementation of IEEE or
+ISO rules/specifications for math functions. It may, however,
+yield faster code for programs that do not require the guarantees
+of these specifications.
 
 The default is @option{-fno-finite-math-only}.
 
@@ -15089,10 +15092,10 @@ underflow, inexact result and invalid operation.  
This option requires
 that @option{-fno-signaling-nans} be in effect.  Setting this option may
 allow faster code if one relies on ``non-stop'' IEEE arithmetic, for example.
 
-This option should never be turned on by any @option{-O} option since
-it can result in incorrect output for programs that depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions.
+This option is not turned on by any @option{-O} option besides
+@option{-Ofast} since it can result in incorrect output for programs
+that depend on an exact implementation of IEEE or ISO rules/specifications
+for math functions.
 
 The default is @option{-ftrapping-math}.


[gcc r15-258] ada: Fix detection of components with per-object constraints

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:e8bcc47f25e59683194446c45a68442e1702259b

commit r15-258-ge8bcc47f25e59683194446c45a68442e1702259b
Author: Piotr Trojanek 
Date:   Tue Jan 16 12:55:24 2024 +0100

ada: Fix detection of components with per-object constraints

Routine Contains_POC (where POC means "per-object constraint") was
failing to detect expressions of the form "Current_Type'Access", because
it was comparing prefix (typically an N_Identifier) with a scope
(typically an N_Definining_Entity). This was harmless, because these
expressions are detected anyway in Analyze_Access_Attribute, together
with uses of 'Unconstrained_Access and 'Unchecked_Access.

Also, this routine was failing to detect the use of discriminants in
array types with constrained subtype indication, e.g.:

  type T (D : Integer) is record
 C : array (Integer range 1 .. D);
  end record;

It is simpler to just reuse Has_Discriminant_Dependent_Constraint and
leave detection of access attributes to Analyze_Access_Attribute.

gcc/ada/

* sem_attr.adb (Analyze_Access_Attribute): Prevent search from
going too far.
* sem_ch3.adb (Analyze_Component_Declaration): Remove
Contains_POC; reuse Has_Discriminant_Dependent_Constraint.

Diff:
---
 gcc/ada/sem_attr.adb | 20 --
 gcc/ada/sem_ch3.adb  | 74 ++--
 2 files changed, 14 insertions(+), 80 deletions(-)

diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index c067d882048..c17f67356ef 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -1014,16 +1014,20 @@ package body Sem_Attr is
  Q : Node_Id := Parent (N);
 
   begin
- while Present (Q)
-   and then Nkind (Q) /= N_Component_Declaration
- loop
+ while Present (Q) loop
+if Nkind (Q) = N_Component_Declaration then
+   Set_Has_Per_Object_Constraint
+ (Defining_Identifier (Q), True);
+   exit;
+
+--  Prevent the search from going too far
+
+elsif Is_Body_Or_Package_Declaration (Q) then
+   exit;
+end if;
+
 Q := Parent (Q);
  end loop;
-
- if Present (Q) then
-Set_Has_Per_Object_Constraint
-  (Defining_Identifier (Q), True);
- end if;
   end;
 
   if Nkind (P) = N_Expanded_Name then
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 737ea809492..ad9e9317b15 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -1960,71 +1960,11 @@ package body Sem_Ch3 is
   T   : Entity_Id;
   P   : Entity_Id;
 
-  function Contains_POC (Constr : Node_Id) return Boolean;
-  --  Determines whether a constraint uses the discriminant of a record
-  --  type thus becoming a per-object constraint (POC).
-
   function Is_Known_Limited (Typ : Entity_Id) return Boolean;
   --  Typ is the type of the current component, check whether this type is
   --  a limited type. Used to validate declaration against that of
   --  enclosing record.
 
-  --
-  -- Contains_POC --
-  --
-
-  function Contains_POC (Constr : Node_Id) return Boolean is
-  begin
- --  Prevent cascaded errors
-
- if Error_Posted (Constr) then
-return False;
- end if;
-
- case Nkind (Constr) is
-when N_Attribute_Reference =>
-   return Attribute_Name (Constr) = Name_Access
- and then Prefix (Constr) = Scope (Entity (Prefix (Constr)));
-
-when N_Discriminant_Association =>
-   return Denotes_Discriminant (Expression (Constr));
-
-when N_Identifier =>
-   return Denotes_Discriminant (Constr);
-
-when N_Index_Or_Discriminant_Constraint =>
-   declare
-  IDC : Node_Id;
-
-   begin
-  IDC := First (Constraints (Constr));
-  while Present (IDC) loop
-
- --  One per-object constraint is sufficient
-
- if Contains_POC (IDC) then
-return True;
- end if;
-
- Next (IDC);
-  end loop;
-
-  return False;
-   end;
-
-when N_Range =>
-   return Denotes_Discriminant (Low_Bound (Constr))
-or else
-  Denotes_Discriminant (High_Bound (Constr));
-
-when N_Range_Constraint =>
-   return Denotes_Discriminant (Range_Exp

[gcc r15-260] ada: Simplify detection of the enclosing scope

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:3e01dfa72623ede64ff2e92f6852d1fd07e8898d

commit r15-260-g3e01dfa72623ede64ff2e92f6852d1fd07e8898d
Author: Piotr Trojanek 
Date:   Tue Jan 16 13:07:20 2024 +0100

ada: Simplify detection of the enclosing scope

Code cleanup; behaviour is unaffected.

gcc/ada/

* sem_attr.adb (Analyze_Access_Attribute): Replace loop with
Current_Scope_No_Loops.

Diff:
---
 gcc/ada/sem_attr.adb | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index 6140cc0c0d6..e80a144ebb2 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -988,10 +988,7 @@ package body Sem_Attr is
--  expanded into a loop. Locate scope of type definition,
--  if any.
 
-   Scop := Current_Scope;
-   while Ekind (Scop) = E_Loop loop
-  Scop := Scope (Scop);
-   end loop;
+   Scop := Current_Scope_No_Loops;
 
--  OK if we are within the scope of a limited type
--  let's mark the component as having per object constraint


[gcc r15-241] ada: Fix Program_Error raised during generation of data representation in JSON

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:6fa5f50897c4beba0b55f0c0b76529758a5d24bd

commit r15-241-g6fa5f50897c4beba0b55f0c0b76529758a5d24bd
Author: Eric Botcazou 
Date:   Fri Jan 5 12:04:17 2024 +0100

ada: Fix Program_Error raised during generation of data representation in 
JSON

This happens for the extension of a private discriminated tagged type.

gcc/ada/

* repinfo.adb (List_Record_Info.List_Structural_Record_Layout): Add
another guard for private types after retrieving the parent in the
extension case.

Diff:
---
 gcc/ada/repinfo.adb | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
index 28a587f039b..28e4a642765 100644
--- a/gcc/ada/repinfo.adb
+++ b/gcc/ada/repinfo.adb
@@ -1491,6 +1491,12 @@ package body Repinfo is
 
   else
  Parent_Type := Base_Type (Parent_Type);
+
+ if Is_Private_Type (Parent_Type) then
+Parent_Type := Full_View (Parent_Type);
+pragma Assert (Present (Parent_Type));
+ end if;
+
  if not In_Extended_Main_Source_Unit (Parent_Type) then
 raise Not_In_Extended_Main;
  end if;


[gcc r15-264] ada: Fix grammar in comment

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:326f6a4e7400771893a482009c121fc77bc471fe

commit r15-264-g326f6a4e7400771893a482009c121fc77bc471fe
Author: Piotr Trojanek 
Date:   Thu Mar 12 16:53:53 2020 +0100

ada: Fix grammar in comment

Code cleanup.

gcc/ada/

* exp_aggr.ads (Static_Array_Aggregate): Fix typo in comment.

Diff:
---
 gcc/ada/exp_aggr.ads | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/ada/exp_aggr.ads b/gcc/ada/exp_aggr.ads
index 8db0a020663..0b92e98370a 100644
--- a/gcc/ada/exp_aggr.ads
+++ b/gcc/ada/exp_aggr.ads
@@ -61,7 +61,7 @@ package Exp_Aggr is
--  N is an array aggregate that may have a component association with
--  an others clause and a range. If bounds are static and the expressions
--  are compile-time known constants, rewrite N as a purely positional
-   --  aggregate, to be use to initialize variables and components of the type
+   --  aggregate, to be used to initialize variables and components of the type
--  without generating elaboration code.
 
 end Exp_Aggr;


[gcc r15-246] ada: Fix missing flag for GNATprove

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:41ebf2e641f85560452cb4cea35a7f3f013982bc

commit r15-246-g41ebf2e641f85560452cb4cea35a7f3f013982bc
Author: Yannick Moy 
Date:   Thu Jan 4 14:18:04 2024 +0100

ada: Fix missing flag for GNATprove

GNATprove expects the frontend to position correctly range check
flags, on expressions which might lead to a range check failure.
This was missing on in-out parameters of calls. Now fixed.

There is no impact on compilation.

gcc/ada/

* sem_res.adb (Resolve_Actuals): Add range check flag.

Diff:
---
 gcc/ada/sem_res.adb | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 67062c6b32b..dc48b0b7638 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -4388,6 +4388,17 @@ package body Sem_Res is
   Resolve (Expression (A));
end if;
 
+   --  In GNATprove mode, add a range check flag on scalar
+   --  conversions for IN OUT parameters. The check may be
+   --  needed on entry from the call.
+
+   if GNATprove_Mode
+ and then Ekind (F) = E_In_Out_Parameter
+ and then Is_Scalar_Type (Etype (F))
+   then
+  Set_Do_Range_Check (Expression (A));
+   end if;
+
 --  If the actual is a function call that returns a limited
 --  unconstrained object that needs finalization, create a
 --  transient scope for it, so that it can receive the proper


[gcc r15-266] ada: Prevent calculation of negative stack counts

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:c6b06faa3ccb2b12b80ee682d3f22a7f5aa9ddd3

commit r15-266-gc6b06faa3ccb2b12b80ee682d3f22a7f5aa9ddd3
Author: Piotr Trojanek 
Date:   Wed Jan 10 13:32:04 2024 +0100

ada: Prevent calculation of negative stack counts

Negative numbers of stack counts have no meaning.

gcc/ada/

* lib.ads, lib.adb (Primary_Stack_Count, Sec_Stack_Count,
Increment_Primary_Stack_Count, Increment_Sec_Stack_Count,
Unit_Record): Stack counts are never negative.
* ali.ads (Unit_Record): Likewise.
* bindgen.adb (Num_Primary_Stacks, Num_Sec_Stacks): Likewise.
* exp_ch3.adb (Count_Default_Sized_Task_Stacks): Likewise.
* sem_util.ads, sem_util.adb (Number_Of_Elements_In_Array):
Likewise.

Diff:
---
 gcc/ada/ali.ads  |  4 ++--
 gcc/ada/bindgen.adb  |  4 ++--
 gcc/ada/exp_ch3.adb  |  2 +-
 gcc/ada/lib.adb  | 12 ++--
 gcc/ada/lib.ads  | 12 ++--
 gcc/ada/sem_util.adb |  4 ++--
 gcc/ada/sem_util.ads |  2 +-
 7 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads
index 23c744433a3..67b8fcd1b80 100644
--- a/gcc/ada/ali.ads
+++ b/gcc/ada/ali.ads
@@ -482,11 +482,11 @@ package ALI is
   --  Indicates whether a package body or a spec has a library-level
   --  finalization routine.
 
-  Primary_Stack_Count : Int;
+  Primary_Stack_Count : Nat;
   --  Indicates the number of task objects declared in this unit that have
   --  default sized primary stacks.
 
-  Sec_Stack_Count : Int;
+  Sec_Stack_Count : Nat;
   --  Indicates the number of task objects declared in this unit that have
   --  default sized secondary stacks.
end record;
diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb
index bffd1344212..fc834e3a9b6 100644
--- a/gcc/ada/bindgen.adb
+++ b/gcc/ada/bindgen.adb
@@ -57,11 +57,11 @@ package body Bindgen is
Num_Elab_Calls : Nat := 0;
--  Number of generated calls to elaboration routines
 
-   Num_Primary_Stacks : Int := 0;
+   Num_Primary_Stacks : Nat := 0;
--  Number of default-sized primary stacks the binder needs to allocate for
--  task objects declared in the program.
 
-   Num_Sec_Stacks : Int := 0;
+   Num_Sec_Stacks : Nat := 0;
--  Number of default-sized primary stacks the binder needs to allocate for
--  task objects declared in the program.
 
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index e9fab87365c..f934dbfddaa 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -6738,7 +6738,7 @@ package body Exp_Ch3 is
--  Then multiply the result by the size of the array
 
declare
-  Quantity : constant Int := Number_Of_Elements_In_Array (Typ);
+  Quantity : constant Nat := Number_Of_Elements_In_Array (Typ);
   --  Number_Of_Elements_In_Array is non-trival, consequently
   --  its result is captured as an optimization.
 
diff --git a/gcc/ada/lib.adb b/gcc/ada/lib.adb
index ebd6bc99040..c465828c562 100644
--- a/gcc/ada/lib.adb
+++ b/gcc/ada/lib.adb
@@ -173,12 +173,12 @@ package body Lib is
   return Units.Table (U).OA_Setting;
end OA_Setting;
 
-   function Primary_Stack_Count (U : Unit_Number_Type) return Int is
+   function Primary_Stack_Count (U : Unit_Number_Type) return Nat is
begin
   return Units.Table (U).Primary_Stack_Count;
end Primary_Stack_Count;
 
-   function Sec_Stack_Count  (U : Unit_Number_Type) return Int is
+   function Sec_Stack_Count  (U : Unit_Number_Type) return Nat is
begin
   return Units.Table (U).Sec_Stack_Count;
end Sec_Stack_Count;
@@ -1034,8 +1034,8 @@ package body Lib is
-- Increment_Primary_Stack_Count --
---
 
-   procedure Increment_Primary_Stack_Count (Increment : Int) is
-  PSC : Int renames Units.Table (Current_Sem_Unit).Primary_Stack_Count;
+   procedure Increment_Primary_Stack_Count (Increment : Nat) is
+  PSC : Nat renames Units.Table (Current_Sem_Unit).Primary_Stack_Count;
begin
   PSC := PSC + Increment;
end Increment_Primary_Stack_Count;
@@ -1044,8 +1044,8 @@ package body Lib is
-- Increment_Sec_Stack_Count --
---
 
-   procedure Increment_Sec_Stack_Count (Increment : Int) is
-  SSC : Int renames Units.Table (Current_Sem_Unit).Sec_Stack_Count;
+   procedure Increment_Sec_Stack_Count (Increment : Nat) is
+  SSC : Nat renames Units.Table (Current_Sem_Unit).Sec_Stack_Count;
begin
   SSC := SSC + Increment;
end Increment_Sec_Stack_Count;
diff --git a/gcc/ada/lib.ads b/gcc/ada/lib.ads
index ee06cde2727..93ff1b13531 100644
--- a/gcc/ada/lib.ads
+++ b/gcc/ada/lib.ads
@@ -463,8 +463,8 @@ package Lib is
function No_Elab_Code_All (U : Unit_Number_Type) return Boolean;
function OA_Setting   (U : Unit_Number_Type) return Character;
function Primary_Stack_Co

[gcc r15-247] ada: Bad internal naming when using pragma Compile_Time_Error

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:8a116c6539b044ec20bd9fd604887a0a2e21a10e

commit r15-247-g8a116c6539b044ec20bd9fd604887a0a2e21a10e
Author: Justin Squirek 
Date:   Tue Jan 9 15:08:08 2024 +

ada: Bad internal naming when using pragma Compile_Time_Error

This patch fixes an error in the compiler whereby the presence of a 
condition
which tests the size of a type not known at compile time within an instance
of pragma Compile_Time_Error causes incorrect internal names to be generated
for said type during expansion.

gcc/ada/

* sem_prag.adb (Defer_Compile_Time_Warning_Error_To_BE): Better
handle itypes such that the tree copy required for the expansion
of the pragma doesn't cause ordering problems with internal names.

Diff:
---
 gcc/ada/sem_prag.adb | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index fa2a4cbed39..a2996137648 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -33812,7 +33812,23 @@ package body Sem_Prag is
   --  as 0.
 
   if not In_Extended_Main_Code_Unit (N) then
- Insert_Library_Level_Action (New_Copy_Tree (N));
+ --  We've created an Itype for the string in this pragma and
+ --  may have made other Itypes. When we copy the entire tree
+ --  of this pragma, we'll make a second copy of them in its
+ --  unit, which will mess up the numbering of the remaining
+ --  internal names.
+
+ declare
+Saved_Current_Sem_Unit : constant Unit_Number_Type :=
+  Current_Sem_Unit;
+New_N  : Node_Id;
+
+ begin
+Current_Sem_Unit := Main_Unit;
+New_N := New_Copy_Tree (N);
+Current_Sem_Unit := Saved_Current_Sem_Unit;
+Insert_Library_Level_Action (New_N);
+ end;
   end if;
end Defer_Compile_Time_Warning_Error_To_BE;


[gcc r15-248] ada: Aspects on multiple component declarations

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:ceaae63a4b4bae36eb2b693ee862f91267dfb62a

commit r15-248-gceaae63a4b4bae36eb2b693ee862f91267dfb62a
Author: Bob Duff 
Date:   Tue Jan 9 07:59:22 2024 -0500

ada: Aspects on multiple component declarations

This patch fixes a bug where aspect specifications were ignored
on all but the last of multiple component declarations.
For example, in a record type with components "X, Y: T with Volatile;"
only Y was marked Volatile; X was not. Both should be marked Volatile.

The fix is in Par.Ch3.P_Component_Items, where P_Aspect_Specifications
needs to be called each time through the loop.

In addition, various minor cleanups.

gcc/ada/

* par-ch3.adb (P_Component_Items): Move P_Aspect_Specifications
into the loop, so aspects can be attached to multiple component
declarations.
(P_Type_Declaration, P_Subtype_Declaration)
(P_Known_Discriminant_Part_Opt): Remove default for Semicolon in
calls to P_Aspect_Specifications.
* gen_il-gen-gen_nodes.adb (N_Discriminant_Specification): Add
Aspect_Specifications field to N_Discriminant_Specification, which
was missing.
* aspects.adb (Has_Aspect_Specifications_Flag): Make it True for
N_Discriminant_Specification.
* par-ch13.adb: Remove default for Semicolon in calls to
P_Aspect_Specifications.
(Get_Aspect_Specifications): Misc cleanup.
(P_Aspect_Specifications): Remove comment. It's not clear what
"the flag" is referring to, but anyway the first part of the
comment is obvious, and the second part is apparently obsolete.
Misc cleanup.
* par.adb (P_Aspect_Specifications, Get_Aspect_Specifications):
Remove default for Semicolon; calls are more readable that way.
Improve comments.
* par-ch12.adb: Remove default for Semicolon in calls to
P_Aspect_Specifications.
* par-ch6.adb: Likewise.
* par-ch7.adb: Likewise.
* par-ch9.adb: Likewise.
* par-endh.adb: Likewise.

Diff:
---
 gcc/ada/aspects.adb  |  3 ++-
 gcc/ada/gen_il-gen-gen_nodes.adb |  1 +
 gcc/ada/par-ch12.adb | 12 ++--
 gcc/ada/par-ch13.adb | 30 +++---
 gcc/ada/par-ch3.adb  | 12 ++--
 gcc/ada/par-ch6.adb  | 12 ++--
 gcc/ada/par-ch7.adb  |  2 +-
 gcc/ada/par-ch9.adb  |  4 ++--
 gcc/ada/par-endh.adb |  6 +++---
 gcc/ada/par.adb  | 22 +++---
 10 files changed, 45 insertions(+), 59 deletions(-)

diff --git a/gcc/ada/aspects.adb b/gcc/ada/aspects.adb
index 0d4988ac540..696ee672acd 100644
--- a/gcc/ada/aspects.adb
+++ b/gcc/ada/aspects.adb
@@ -450,6 +450,7 @@ package body Aspects is
Has_Aspect_Specifications_Flag : constant array (Node_Kind) of Boolean :=
  (N_Abstract_Subprogram_Declaration=> True,
   N_Component_Declaration  => True,
+  N_Discriminant_Specification => True,
   N_Entry_Body => True,
   N_Entry_Declaration  => True,
   N_Exception_Declaration  => True,
@@ -471,8 +472,8 @@ package body Aspects is
   N_Package_Body_Stub  => True,
   N_Package_Declaration=> True,
   N_Package_Instantiation  => True,
-  N_Package_Specification  => True,
   N_Package_Renaming_Declaration   => True,
+  N_Package_Specification  => True,
   N_Parameter_Specification=> True,
   N_Private_Extension_Declaration  => True,
   N_Private_Type_Declaration   => True,
diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb
index d7cc39bc048..fb00993a95e 100644
--- a/gcc/ada/gen_il-gen-gen_nodes.adb
+++ b/gcc/ada/gen_il-gen-gen_nodes.adb
@@ -1375,6 +1375,7 @@ begin -- Gen_IL.Gen.Gen_Nodes
 Sy (Null_Exclusion_Present, Flag, Default_False),
 Sy (Discriminant_Type, Node_Id),
 Sy (Expression, Node_Id, Default_Empty),
+Sy (Aspect_Specifications, List_Id, Default_No_List),
 Sm (More_Ids, Flag),
 Sm (Prev_Ids, Flag)));
 
diff --git a/gcc/ada/par-ch12.adb b/gcc/ada/par-ch12.adb
index 8eb06b682bf..56ab07c0cb3 100644
--- a/gcc/ada/par-ch12.adb
+++ b/gcc/ada/par-ch12.adb
@@ -223,7 +223,7 @@ package body Ch12 is
 Error_Msg_SP ("child unit allowed only at library level");
  end if;
 
- P_Aspect_Specifications (Gen_Decl);
+ P_Aspect_Specifications (Gen_Decl, Semicolon => True);
   end if;
 
   Set_Generic_Formal_Declarations (Gen_Decl, Decls);
@@ -482,7 +482,7 @@ package body Ch12 is
 
  

[gcc r15-250] ada: Improve pragma No_Return's pre-Ada2022 handling of functions

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:ef99791719a5695edc492b30b3a543c3659bf700

commit r15-250-gef99791719a5695edc492b30b3a543c3659bf700
Author: Steve Baird 
Date:   Mon Dec 18 16:17:40 2023 -0800

ada: Improve pragma No_Return's pre-Ada2022 handling of functions

Ada 2022 allows pragma No_Return to apply to a function (or a generic 
function).
For earlier Ada versions, if a No_Return pragma argument's possible
resolutions include a function (or a generic function) then we want to 
ignore
that candidate if a non-function candidate is also available and otherwise
to generate an error message mentioning that this is an Ada 2022 feature.

gcc/ada/

* sem_prag.adb (Analyze_Pragma): Restructure the loop over
possible resolutions of a No_Return pragma's argument so that
functions (and generic functions) are not processed until after it
is known whether there is a non-function candidate resolution. For
a pre-2022 Ada version, terminate the iteration before processing
functions if a non-function resolution is found.

Diff:
---
 gcc/ada/sem_prag.adb | 166 ++-
 1 file changed, 97 insertions(+), 69 deletions(-)

diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index a2996137648..ff02ae9a7af 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -20771,96 +20771,124 @@ package body Sem_Prag is
   raise Pragma_Exit;
end if;
 
+   Found := False;
--  Loop to find matching procedures or functions (Ada 2022)
 
-   E := Entity (Id);
+   Outer_Loop :
+   for Process_Functions in Boolean loop
 
-   Found := False;
-   while Present (E)
- and then Scope (E) = Current_Scope
-   loop
-  --  Ada 2022 (AI12-0269): A function can be No_Return
+  --  We make two passes over the Homonym list, first looking
+  --  at procedures and then at functions. This is done
+  --  in order to get the desired behavior in the pre-Ada2022
+  --  case. There are two subcases of the pre-Ada2022 case -
+  --  either we found a non-function candidate in the first
+  --  pass or we didn't. If we found one, then exit early
+  --  (i.e., skip the second pass); we want to silently ignore
+  --  any functions. But if we didn't find one then we do not
+  --  want to exit early because looking at functions will
+  --  allow us (if we find one) to generate a more useful
+  --  error message ("this is an Ada 2022 construct" instead of
+  --  "name could not be resolved").
 
-  if Ekind (E) in E_Generic_Procedure | E_Procedure
-   | E_Generic_Function | E_Function
-  then
- --  Check that the pragma is not applied to a body.
- --  First check the specless body case, to give a
- --  different error message. These checks do not apply
- --  if Relaxed_RM_Semantics, to accommodate other Ada
- --  compilers. Disable these checks under -gnatd.J.
-
- if not Debug_Flag_Dot_JJ then
-if Nkind (Parent (Declaration_Node (E))) =
-N_Subprogram_Body
-  and then not Relaxed_RM_Semantics
-then
-   Error_Pragma
- ("pragma% requires separate spec and must come "
-  & "before body");
-end if;
+  exit Outer_Loop when Found and Ada_Version < Ada_2022;
 
---  Now the "specful" body case
+  E := Entity (Id);
 
-if Rep_Item_Too_Late (E, N) then
-   raise Pragma_Exit;
-end if;
- end if;
+  while Present (E)
+and then Scope (E) = Current_Scope
+  loop
+ --  Ada 2022 (AI12-0269): A function can be No_Return
 
- if Check_No_Return (E, N) then
-Set_No_Return (E);
- end if;
+ if (if Process_Functions
+   then Ekind (E) in E_Generic_Function | E_Function
+   else Ekind (E) in E_Generic_Procedure | E_Procedure)
 
- --  A pragma that applies to a Ghost entity becomes Ghost
- --  for the purposes of legality checks and removal of
- --  ignored Ghost code.
+--  if From_Aspect_Speci

[gcc r15-251] Update copyright years.

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:711326014d078f330085127a200edb810191856d

commit r15-251-g711326014d078f330085127a200edb810191856d
Author: Marc Poulhiès 
Date:   Fri Jan 12 09:46:00 2024 +0100

Update copyright years.

Diff:
---
 gcc/ada/libgnat/s-finpri.adb | 2 +-
 gcc/ada/libgnat/s-finpri.ads | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/ada/libgnat/s-finpri.adb b/gcc/ada/libgnat/s-finpri.adb
index 7dc08a97f4b..05bf2a69ddc 100644
--- a/gcc/ada/libgnat/s-finpri.adb
+++ b/gcc/ada/libgnat/s-finpri.adb
@@ -6,7 +6,7 @@
 --  --
 -- B o d y  --
 --  --
---Copyright (C) 2023, Free Software Foundation, Inc.--
+-- Copyright (C) 2023-2024, Free Software Foundation, Inc.  --
 --  --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
diff --git a/gcc/ada/libgnat/s-finpri.ads b/gcc/ada/libgnat/s-finpri.ads
index ab79ea2c664..7a474436920 100644
--- a/gcc/ada/libgnat/s-finpri.ads
+++ b/gcc/ada/libgnat/s-finpri.ads
@@ -6,7 +6,7 @@
 --  --
 -- S p e c  --
 --  --
---Copyright (C) 2023, Free Software Foundation, Inc.--
+-- Copyright (C) 2023-2024, Free Software Foundation, Inc.  --
 --  --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --


[gcc r15-252] ada: Adapt proof of runtime units

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:1955a35a46e4667cccf8d22116edc29b88e3e729

commit r15-252-g1955a35a46e4667cccf8d22116edc29b88e3e729
Author: Yannick Moy 
Date:   Fri Jan 12 11:30:38 2024 +

ada: Adapt proof of runtime units

Restore proof of runtime units after changes in SPARK.

gcc/ada/

* libgnat/a-strsea.adb (Index): Add assertions.
* libgnat/a-strsup.ads ("="): Remove useless precondition.
* libgnat/s-aridou.adb (Prove_Rounding_Case): Add assertions.
(Lemma_Shift_Right): Add call to lemma.
* libgnat/s-arit32.adb (Prove_Rounding_Case): Add assertion.
(Prove_ Signs): Add assertions.
(Scaled_Divide32): Add assertions.

Diff:
---
 gcc/ada/libgnat/a-strsea.adb |  2 ++
 gcc/ada/libgnat/a-strsup.ads |  1 -
 gcc/ada/libgnat/s-aridou.adb |  9 +++--
 gcc/ada/libgnat/s-arit32.adb | 17 +++--
 4 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/gcc/ada/libgnat/a-strsea.adb b/gcc/ada/libgnat/a-strsea.adb
index 1dad3be4f4a..54f12199fcc 100644
--- a/gcc/ada/libgnat/a-strsea.adb
+++ b/gcc/ada/libgnat/a-strsea.adb
@@ -623,6 +623,7 @@ package body Ada.Strings.Search with SPARK_Mode is
(if (for some J in From .. Source'Last - PL1 =>
  Match (Source, Pattern, Mapping, J))
 then Result in From .. Source'Last - PL1
+  and then Match (Source, Pattern, Mapping, Result)
 else Result = 0);
 
   else
@@ -636,6 +637,7 @@ package body Ada.Strings.Search with SPARK_Mode is
(if (for some J in Source'First .. From - PL1 =>
   Match (Source, Pattern, Mapping, J))
 then Result in Source'First .. From - PL1
+  and then Match (Source, Pattern, Mapping, Result)
 else Result = 0);
   end if;
 
diff --git a/gcc/ada/libgnat/a-strsup.ads b/gcc/ada/libgnat/a-strsup.ads
index cb1dcc9a076..6c360f1982b 100644
--- a/gcc/ada/libgnat/a-strsup.ads
+++ b/gcc/ada/libgnat/a-strsup.ads
@@ -689,7 +689,6 @@ is
  (Left  : Super_String;
   Right : Super_String) return Boolean
with
- Pre=> Left.Max_Length = Right.Max_Length,
  Post   => "="'Result = (Super_To_String (Left) = Super_To_String (Right)),
  Global => null;
 
diff --git a/gcc/ada/libgnat/s-aridou.adb b/gcc/ada/libgnat/s-aridou.adb
index ac25e6a9183..6f27487db37 100644
--- a/gcc/ada/libgnat/s-aridou.adb
+++ b/gcc/ada/libgnat/s-aridou.adb
@@ -971,7 +971,7 @@ is
   procedure Prove_Rounding_Case is
   begin
  if Same_Sign (Big (X), Big (Y) * Big (Z)) then
-null;
+pragma Assert (abs Big_Q = Big (Qu));
  end if;
   end Prove_Rounding_Case;
 
@@ -1603,6 +1603,7 @@ is
  pragma Loop_Invariant (XX = Shift_Right (X, J));
  pragma Loop_Invariant (XX = X / Double_Uns'(2) ** J);
   end loop;
+  Lemma_Div_Commutation (X, Double_Uns'(2) ** Shift);
end Lemma_Shift_Right;
 
--
@@ -2441,7 +2442,11 @@ is
   procedure Prove_Rounding_Case is
   begin
  if Same_Sign (Big (X) * Big (Y), Big (Z)) then
-null;
+pragma Assert
+  (abs Big_Q =
+ (if Ru > (Zu - Double_Uns'(1)) / Double_Uns'(2)
+  then abs Quot + 1
+  else abs Quot));
  end if;
   end Prove_Rounding_Case;
 
diff --git a/gcc/ada/libgnat/s-arit32.adb b/gcc/ada/libgnat/s-arit32.adb
index 59a6db08199..221ef1e635e 100644
--- a/gcc/ada/libgnat/s-arit32.adb
+++ b/gcc/ada/libgnat/s-arit32.adb
@@ -415,7 +415,11 @@ is
   procedure Prove_Rounding_Case is
   begin
  if Same_Sign (Big (X) * Big (Y), Big (Z)) then
-null;
+pragma Assert
+  (abs Big_Q =
+ (if Ru > (Zu - Uns32'(1)) / Uns32'(2)
+  then abs Quot + 1
+  else abs Quot));
  end if;
   end Prove_Rounding_Case;
 
@@ -432,7 +436,14 @@ is
   -- Prove_Signs --
   -
 
-  procedure Prove_Signs is null;
+  procedure Prove_Signs is
+  begin
+ if (X >= 0) = (Y >= 0) then
+pragma Assert (Big (R) = Big_R and then Big (Q) = Big_Q);
+ else
+pragma Assert (Big (R) = Big_R and then Big (Q) = Big_Q);
+ end if;
+  end Prove_Signs;
 
--  Start of processing for Scaled_Divide32
 
@@ -483,6 +494,8 @@ is
   Lemma_Div_Commutation (D, Uns64 (Zu));
   Lemma_Rem_Commutation (D, Uns64 (Zu));
 
+  pragma Assert (Uns64 (Qu) = D / Uns64 (Zu));
+  pragma Assert (Uns64 (Ru) = D rem Uns64 (Zu));
   pragma Assert (Big (Ru) = abs Big_R);
   pragma Assert (Big (Qu) = abs Quot);
   pragma Assert (Big (Zu) = Big (Uns32'(abs Z)));


[gcc r15-267] ada: Fix calculation of tasks in null arrays

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:cb478e0a6f3a296e1c234a85fc0d45d633a0ff93

commit r15-267-gcb478e0a6f3a296e1c234a85fc0d45d633a0ff93
Author: Piotr Trojanek 
Date:   Wed Jan 10 18:48:04 2024 +0100

ada: Fix calculation of tasks in null arrays

Fix handling of null arrays when calculating the secondary stack size
for the binder.

gcc/ada/

* sem_util.adb (Number_Of_Elements_In_Array): Fix counting of
elements in null arrays; remove redundant parenthesis; avoid
run-time conversion of 1 to universal integer.

Diff:
---
 gcc/ada/sem_util.adb | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index bee078e6df5..5f44b4c26fe 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -25404,7 +25404,8 @@ package body Sem_Util is
 return 0;
  else
 Num :=
-  Num * UI_To_Int ((Expr_Value (High) - Expr_Value (Low) + 1));
+  Num * Int'Max
+(0, UI_To_Int (Expr_Value (High) - Expr_Value (Low) + Uint_1));
  end if;
 
  Next_Index (Indx);


[gcc r15-240] ada: SPARK rule changed on functions with side effects

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:428f83d7b10d92e223dac171cdfba4e9d084823f

commit r15-240-g428f83d7b10d92e223dac171cdfba4e9d084823f
Author: Yannick Moy 
Date:   Thu Dec 21 17:38:21 2023 +0100

ada: SPARK rule changed on functions with side effects

SPARK RM definition of function with side effects now makes them
implicitly volatile functions.

gcc/ada/

* sem_util.adb (Is_Volatile_Function): Return True on functions
with side effects.

Diff:
---
 gcc/ada/sem_util.adb | 5 +
 1 file changed, 5 insertions(+)

diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 18c9de05cf9..3af029fd9a3 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -21226,6 +21226,11 @@ package body Sem_Util is
   then
  return True;
 
+  --  A function with side-effects is volatile
+
+  elsif Is_Function_With_Side_Effects (Func_Id) then
+ return True;
+
   --  Otherwise the function is treated as volatile if it is subject to
   --  enabled pragma Volatile_Function.


[gcc r15-255] ada: Remove obsolete field Postconditions_Proc

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:fabb69655b1eb4a58c2978a80d7a6fd5d67684fc

commit r15-255-gfabb69655b1eb4a58c2978a80d7a6fd5d67684fc
Author: Eric Botcazou 
Date:   Mon Jan 15 10:55:58 2024 +0100

ada: Remove obsolete field Postconditions_Proc

It is now totally unused by the front-end and dependent tools.

gcc/ada/

* einfo.ads (Postconditions_Proc): Delete.
* gen_il-fields.ads (Opt_Field_Enum): Remove Postconditions_Proc.
* gen_il-gen-gen_entities.adb (E_Function): Likewise.
(E_Procedure): Likewise.
(E_Entry): Likewise.
(E_Entry_Family): Likewise.

Diff:
---
 gcc/ada/einfo.ads   | 3 ---
 gcc/ada/gen_il-fields.ads   | 1 -
 gcc/ada/gen_il-gen-gen_entities.adb | 4 
 3 files changed, 8 deletions(-)

diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index e3bfdb3507d..3c290ef9a93 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -4016,9 +4016,6 @@ package Einfo is
 --   ensure that the finalization masters of all pending access types are
 --   fully initialized when the full view is frozen.
 
---Postconditions_Proc
---   Obsolete field which can be removed once CodePeer is fixed ???
-
 --Predicate_Function (synthesized)
 --   Defined in all types. Set for types for which (Has_Predicates is True)
 --   and for which a predicate procedure has been built that tests that the
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index ac1e0c953f0..0a5bddf5816 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -851,7 +851,6 @@ package Gen_IL.Fields is
   Part_Of_References,
   Partial_View_Has_Unknown_Discr,
   Pending_Access_Types,
-  Postconditions_Proc,
   Predicate_Expression,
   Prev_Entity,
   Prival,
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb 
b/gcc/ada/gen_il-gen-gen_entities.adb
index cde016c3d1e..dd5db9746fd 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -1019,7 +1019,6 @@ begin -- Gen_IL.Gen.Gen_Entities
 Sm (Mechanism, Mechanism_Type),
 Sm (Next_Inlined_Subprogram, Node_Id),
 Sm (Original_Protected_Subprogram, Node_Id),
-Sm (Postconditions_Proc, Node_Id),
 Sm (Predicate_Expression, Node_Id),
 Sm (Protected_Subprogram, Node_Id),
 Sm (Protection_Object, Node_Id),
@@ -1069,7 +1068,6 @@ begin -- Gen_IL.Gen.Gen_Entities
 Sm (LSP_Subprogram, Node_Id),
 Sm (Next_Inlined_Subprogram, Node_Id),
 Sm (Original_Protected_Subprogram, Node_Id),
-Sm (Postconditions_Proc, Node_Id),
 Sm (Protected_Subprogram, Node_Id),
 Sm (Protection_Object, Node_Id),
 Sm (Receiving_Entry, Node_Id),
@@ -1113,7 +,6 @@ begin -- Gen_IL.Gen.Gen_Entities
 Sm (Is_Elaboration_Checks_OK_Id, Flag),
 Sm (Is_Elaboration_Warnings_OK_Id, Flag),
 Sm (Last_Entity, Node_Id),
-Sm (Postconditions_Proc, Node_Id),
 Sm (Protected_Body_Subprogram, Node_Id),
 Sm (Protection_Object, Node_Id),
 Sm (Scope_Depth_Value, Unat),
@@ -1140,7 +1137,6 @@ begin -- Gen_IL.Gen.Gen_Entities
 Sm (Is_Elaboration_Warnings_OK_Id, Flag),
 Sm (Last_Entity, Node_Id),
 Sm (Needs_No_Actuals, Flag),
-Sm (Postconditions_Proc, Node_Id),
 Sm (Protected_Body_Subprogram, Node_Id),
 Sm (Protection_Object, Node_Id),
 Sm (Renamed_Or_Alias, Node_Id),


[gcc r15-257] ada: Fix bad interaction between homogeneous finalization master and BIP protocol

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:5c8f6ee3663fc77834d1eb5f2d16e7d3ceb5d8cd

commit r15-257-g5c8f6ee3663fc77834d1eb5f2d16e7d3ceb5d8cd
Author: Eric Botcazou 
Date:   Tue Jan 16 09:18:15 2024 +0100

ada: Fix bad interaction between homogeneous finalization master and BIP 
protocol

Dynamically-allocated objects that require finalization are attached to a
finalization master, which is of a (limited) controlled type declared in
the System.Finalization_Masters unit. Now there are two kinds of them:
homogeneous and heterogeneous; for the former, all the objects attached
to the master share the same Finalize_Address primitive whereas, for the
latter, they may have different Finalize_Address primitives.

There is a problem in this scheme with the BIP protocol, because this
protocol forwards the finalization master from callers to callees and it
does so even if the result types are distinct, so it is possible for a
homogeneous finalization master to end up containing objects with different
Finalize_Address primitives; in that case, the object attached last wins
and sets the common Finalize_Address, which is then used to finalize other
objects with unpredictable outcome (and very loud valgrind report).

Therefore, this change gets rid of homogeneous finalization masters and
also streamlines the implementation of heterogeneous ones by storing the
Finalize_Address primitive on a per object basis in the FM_Node record.

gcc/ada/

* einfo.ads (Pending_Access_Types): Delete.
* exp_ch3.adb (Freeze_Type.Process_Pending_Access_Types): Likewise.
(Freeze_Type): Do not call Process_Pending_Access_Types.
* exp_ch7.ads (Make_Set_Finalize_Address_Call): Delete.
* exp_ch7.adb (Build_Finalization_Master.Add_Pending_Access_Type):
Delete.
(Build_Finalization_Master): Do not set Finalize_Address on the
master or call Add_Pending_Access_Type.
(Make_Set_Finalize_Address_Call): Delete.
* gen_il-fields.ads (Opt_Field_Enum): Remove Pending_Access_Types.
* gen_il-gen-gen_entities.adb (Type_Kind): Likewise.
* rtsfind.ads (RE_Id): Remove RE_Set_Finalize_Address.
(RE_Unit_Table): Likewise.
* sem_ch3.adb (Analyze_Full_Type_Declaration): Do not deal with
pending access types.
* libgnat/s-finmas.ads (Attach_Unprotected): Add Finalize_Address
second parameter.
(Delete_Finalize_Address_Unprotected): Delete.
(Finalize_Address): Likewise.
(Finalize_Address_Unprotected): Likewise.
(Is_Homogeneous): Likewise.
(Set_Finalize_Address): Likewise.
(Set_Finalize_Address_Unprotected): Likewise.
(Set_Heterogeneous_Finalize_Address_Unprotected): Likewise.
(Set_Is_Heterogeneous): Likewise.
(FM_Node): Add Finalize_Address component.
(Finalization_Master): Remove Is_Homogeneous and Finalize_Address
components.
* libgnat/s-finmas.adb: Remove with & use clauses for System.HTable.
(Finalize_Address_Table): Delete.
(Attach_Unprotected): Add Finalize_Address second parameter and save
its value in the Finalize_Address field of the node.
(Delete_Finalize_Address_Unprotected): Delete.
(Finalize): Call Finalize_Address saved in the nodes.
(Finalize_Address): Delete.
(Finalize_Address_Unprotected): Likewise.
(Hash): Likewise.
(Is_Homogeneous): Likewise.
(Print_Master): Adjust.
(Set_Finalize_Address): Delete.
(Set_Finalize_Address_Unprotected): Likewise.
(Set_Heterogeneous_Finalize_Address_Unprotected): Likewise.
(Set_Is_Heterogeneous): Likewise.
* libgnat/s-stposu.adb (Finalize_Address_Table_In_Use): Likewise.
(Allocate_Any_Controlled): Pass Fin_Address to Attach_Unprotected
and remove obsolete processing.
(Deallocate_Any_Controlled): Remove obsolete processing.
(Set_Pool_Of_Subpool): Do not call Set_Is_Heterogeneous.

Diff:
---
 gcc/ada/einfo.ads   |   9 --
 gcc/ada/exp_ch3.adb |  64 ---
 gcc/ada/exp_ch7.adb | 129 -
 gcc/ada/exp_ch7.ads |   9 --
 gcc/ada/gen_il-fields.ads   |   1 -
 gcc/ada/gen_il-gen-gen_entities.adb |   1 -
 gcc/ada/libgnat/s-finmas.adb| 222 +---
 gcc/ada/libgnat/s-finmas.ads|  54 +
 gcc/ada/libgnat/s-stposu.adb|  56 +
 gcc/ada/rtsfind.ads |   2 -
 gcc/ada/sem_ch3.adb |   8 --
 11 files changed, 32 insertions(+), 523 deletions(-)

diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 3c290ef9a93..c45c124b7ed 

[gcc r15-262] ada: Remove redundant guard against empty list of actions

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:e7c7bf30cdc04e73ecc34cfb2d955d1316a0e3eb

commit r15-262-ge7c7bf30cdc04e73ecc34cfb2d955d1316a0e3eb
Author: Piotr Trojanek 
Date:   Sun Aug 21 20:56:26 2022 +0200

ada: Remove redundant guard against empty list of actions

Code cleanup.

gcc/ada/

* exp_ch4.adb (Useful): Remove redundant check for empty list,
because iteration with First works also for empty list; rename
local variable from L to Action.

Diff:
---
 gcc/ada/exp_ch4.adb | 25 +++--
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 5fa47c9b6e7..505c4b3151a 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -12930,8 +12930,7 @@ package body Exp_Ch4 is
   --  to Opnd /= Shortcut_Value.
 
   function Useful (Actions : List_Id) return Boolean;
-  --  Return True if Actions is not empty and contains useful nodes to
-  --  process.
+  --  Return True if Actions contains useful nodes to process
 
   
   -- Make_Test_Expr --
@@ -12951,22 +12950,20 @@ package body Exp_Ch4 is
   
 
   function Useful (Actions : List_Id) return Boolean is
- L : Node_Id;
+ Action : Node_Id;
   begin
- if Present (Actions) then
-L := First (Actions);
+ Action := First (Actions);
 
---  For now "useful" means not N_Variable_Reference_Marker.
---  Consider stripping other nodes in the future.
+ --  For now "useful" means not N_Variable_Reference_Marker. Consider
+ --  stripping other nodes in the future.
 
-while Present (L) loop
-   if Nkind (L) /= N_Variable_Reference_Marker then
-  return True;
-   end if;
+ while Present (Action) loop
+if Nkind (Action) /= N_Variable_Reference_Marker then
+   return True;
+end if;
 
-   Next (L);
-end loop;
- end if;
+Next (Action);
+ end loop;
 
  return False;
   end Useful;


[gcc r15-265] ada: Cleanup calculation of task stacks

2024-05-07 Thread Marc Poulhi?s via Gcc-cvs
https://gcc.gnu.org/g:cf14e7c1db2f20d9dbcc8c3efdebe549ec5eec80

commit r15-265-gcf14e7c1db2f20d9dbcc8c3efdebe549ec5eec80
Author: Piotr Trojanek 
Date:   Wed Jan 10 13:14:34 2024 +0100

ada: Cleanup calculation of task stacks

Code cleanup; semantics is unaffected.

gcc/ada/

* exp_ch3.adb (Count_Default_Sized_Task_Stacks): Do not look for
tasks inside record discriminants; remove avoid repeated call to
Has_Task that happened for record components.
(Expand_N_Object_Declaration): Use high-level routine to detect
array types and subtypes; remove unused initial values.

Diff:
---
 gcc/ada/exp_ch3.adb | 31 +--
 1 file changed, 13 insertions(+), 18 deletions(-)

diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 4c0679f531b..e9fab87365c 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -6752,27 +6752,23 @@ package body Exp_Ch3 is
| E_Record_Subtype
| E_Record_Type
 =>
-   Component := First_Component_Or_Discriminant (Typ);
+   Component := First_Component (Typ);
 
--  Recursively descend each component of the composite type
-   --  looking for tasks, but only if the component is marked as
-   --  having a task.
+   --  looking for tasks.
 
while Present (Component) loop
-  if Has_Task (Etype (Component)) then
- declare
-P : Int;
-S : Int;
+  declare
+ P : Int;
+ S : Int;
 
- begin
-Count_Default_Sized_Task_Stacks
-  (Etype (Component), P, S);
-Pri_Stacks := Pri_Stacks + P;
-Sec_Stacks := Sec_Stacks + S;
- end;
-  end if;
+  begin
+ Count_Default_Sized_Task_Stacks (Etype (Component), P, S);
+ Pri_Stacks := Pri_Stacks + P;
+ Sec_Stacks := Sec_Stacks + S;
+  end;
 
-  Next_Component_Or_Discriminant (Component);
+  Next_Component (Component);
end loop;
 
 when E_Limited_Private_Subtype
@@ -7457,11 +7453,10 @@ package body Exp_Ch3 is
 and then not Restriction_Active (No_Secondary_Stack)
 and then (Restriction_Active (No_Implicit_Heap_Allocations)
   or else Restriction_Active (No_Implicit_Task_Allocations))
-and then not (Ekind (Typ) in E_Array_Type | E_Array_Subtype
-  and then Has_Init_Expression (N))
+and then not (Is_Array_Type (Typ) and then Has_Init_Expression (N))
   then
  declare
-PS_Count, SS_Count : Int := 0;
+PS_Count, SS_Count : Int;
  begin
 Count_Default_Sized_Task_Stacks (Typ, PS_Count, SS_Count);
 Increment_Primary_Stack_Count (PS_Count);


[gcc r15-268] Revert "Revert "combine: Don't combine if I2 does not change""

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:9dbff9c05520a74e6cd337578f27b56c941f64f3

commit r15-268-g9dbff9c05520a74e6cd337578f27b56c941f64f3
Author: Richard Biener 
Date:   Tue May 7 10:14:19 2024 +0200

Revert "Revert "combine: Don't combine if I2 does not change""

This reverts commit 109f1b28fc94c93096506e3df0c25e331cef19d0.

Diff:
---
 gcc/combine.cc | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/gcc/combine.cc b/gcc/combine.cc
index 92b8d98e6c1..71c9abc145c 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -4196,6 +4196,17 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, 
rtx_insn *i0,
   adjust_for_new_dest (i3);
 }
 
+  /* If I2 didn't change, this is not a combination (but a simplification or
+ canonicalisation with context), which should not be done here.  Doing
+ it here explodes the algorithm.  Don't.  */
+  if (rtx_equal_p (newi2pat, PATTERN (i2)))
+{
+  if (dump_file)
+   fprintf (dump_file, "i2 didn't change, not doing this\n");
+  undo_all ();
+  return 0;
+}
+
   /* We now know that we can do this combination.  Merge the insns and
  update the status of registers and LOG_LINKS.  */


[gcc r15-269] Remove obsolete Solaris 11.3 support

2024-05-07 Thread Rainer Orth via Libstdc++-cvs
https://gcc.gnu.org/g:f68e90a0fe88c50ad6f4b15ba9e9503c710d3444

commit r15-269-gf68e90a0fe88c50ad6f4b15ba9e9503c710d3444
Author: Rainer Orth 
Date:   Tue May 7 10:45:55 2024 +0200

Remove obsolete Solaris 11.3 support

Support for Solaris 11.3 had already been obsoleted in GCC 13.  However,
since the only Solaris system in the cfarm was running 11.3, I've kept
it in tree until now when both Solaris 11.4/SPARC and x86 systems have
been added.

This patch actually removes the Solaris 11.3 support.  Apart from
several minor simplifications, there are two more widespread changes:

* In Solaris 11.4, libsocket and libnsl were folded into libc, so
  there's no longer a need to link them explictly.

* Since Solaris 11.4, Solaris includes all crts needed by gcc (like
  crt1.o and gcrt1.o) with the base system.  All workarounds to provide
  fallbacks can thus go.

Bootstrapped without regressions on i386-pc-solaris2.11 and
sparc-sun-solaris2.11 (as/ld, gas/ld, and gas/gld) as well as Solaris
11.3/x86 to ascertain that version is actually rejected.

2024-04-30  Rainer Orth  

c++tools:
* configure.ac (ax_lib_socket_nsl.m4): Don't sinclude.
(AX_LIB_SOCKET_NSL): Don't call.
(NETLIBS): Remove.
* configure: Regenerate.
* Makefile.in (NETLIBS): Remove.
(g++-mapper-server$(exeext)): Remove $(NETLIBS).

gcc:
* config.gcc: Move *-*-solaris2.11.[0-3]* to unsupported list.
<*-*-solaris2*> (default_use_cxa_atexit): Set unconditionally.
* configure.ac (AX_LIB_SOCKET_NSL): Don't call.
(NETLIBS): Remove.
(gcc_cv_ld_aligned_shf_merge): Remove.
(hidden_linkonce) : Remove.
(gcc_cv_target_dl_iterate_phdr) <*-*-solaris2*>: Always set to yes.
* Makefile.in (NETLIBS): Remove.
* configure, config.in, aclocal.m4: Regenerate.
* config/sol2.h: Don't check HAVE_SOLARIS_CRTS.
(STARTFILE_SPEC): Remove !HAVE_SOLARIS_CRTS case.
[USE_GLD] (LINK_EH_SPEC): Remove TARGET_DL_ITERATE_PHDR guard.
* config/i386/i386.cc (USE_HIDDEN_LINKONCE): Remove guard.
* varasm.cc (mergeable_string_section): Remove
HAVE_LD_ALIGNED_SHF_MERGE handling.
(mergeable_constant_section): Likewise.

* doc/install.texi (Specific,i?86-*-solaris2*): Reference Solaris
11.4 only.
(Specific, *-*-solaris2*): Document Solaris 11.3 removal.  Remove
11.3 references and caveats.  Update for 11.4.

gcc/cp:
* Make-lang.in (cc1plus$(exeext)): Remove $(NETLIBS).

gcc/objcp:
* Make-lang.in (cc1objplus$(exeext)): Remove $(NETLIBS).

gcc/testsuite:
* lib/target-supports.exp (check_effective_target_pie): Always
enable on *-*-solaris2*.

libgcc:
* configure.ac <*-*-solaris2*> (libgcc_cv_solaris_crts): Remove.
* config.host <*-*-solaris2*>: Remove !libgcc_cv_solaris_crts
support.
* configure, config.in: Regenerate.
* config/sol2/gmon.c (internal_mcount) [!HAVE_SOLARIS_CRTS]: Remove.
* config/i386/sol2-c1.S, config/sparc/sol2-c1.S: Remove.
* config/sol2/t-sol2 (crt1.o, gcrt1.o): Remove.

libstdc++-v3:
* testsuite/lib/dg-options.exp (add_options_for_net_ts)
<*-*-solaris2*>: Don't link with -lsocket -lnsl.

Diff:
---
 c++tools/Makefile.in  |   3 +-
 c++tools/configure| 211 
 c++tools/configure.ac |  10 --
 gcc/Makefile.in   |   1 -
 gcc/aclocal.m4|   1 -
 gcc/config.gcc|  16 +--
 gcc/config.in |  13 --
 gcc/config/i386/i386.cc   |  10 +-
 gcc/config/sol2.h |  22 +--
 gcc/configure | 224 +-
 gcc/configure.ac  |  58 +---
 gcc/cp/Make-lang.in   |   2 +-
 gcc/doc/install.texi  |  39 ++
 gcc/objcp/Make-lang.in|   2 +-
 gcc/testsuite/lib/target-supports.exp |   8 +-
 gcc/varasm.cc |   6 +-
 libgcc/config.host|  23 +--
 libgcc/config.in  |   3 -
 libgcc/config/i386/sol2-c1.S  | 173 ---
 libgcc/config/sol2/gmon.c |  23 ---
 libgcc/config/sol2/t-sol2 |   6 -
 libgcc/config/sparc/sol2-c1.S | 103 --
 libgcc/configure  |  32 -
 libgcc/configure.ac   |  25 

[gcc r14-10175] AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:c6141ad24f73cf1771e33c7d7edf1d80d8df70b8

commit r14-10175-gc6141ad24f73cf1771e33c7d7edf1d80d8df70b8
Author: Georg-Johann Lay 
Date:   Fri May 3 18:47:50 2024 +0200

AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

ipa/92606: Inter-procedural analysis optimizes data across
address-spaces and PROGMEM.  As of v14, the PROGMEM part is
still not fixed (and there is still no target hook as proposed
in PR92932).  Just disable respective bogus optimization.

PR ipa/92606
gcc/
* config/avr/avr.cc (avr_option_override): Set
flag_ipa_icf_variables = 0.
gcc/testsuite/
* gcc.target/avr/torture/pr92606.c: New test.

(cherry picked from commit 08e752e72363ae7fd5a5fcb70913a0f7b240387b)

Diff:
---
 gcc/config/avr/avr.cc  |  6 +++
 gcc/testsuite/gcc.target/avr/torture/pr92606.c | 57 ++
 2 files changed, 63 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 510e4cea19f..74924ab0565 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1140,6 +1140,12 @@ avr_option_override (void)
   if (targetm.addr_space.zero_address_valid (ADDR_SPACE_GENERIC))
 flag_delete_null_pointer_checks = 0;
 
+  /* PR ipa/92606: Inter-procedural analysis optimizes data across
+ address-spaces and PROGMEM.  As of v14, the PROGMEM part is
+ still not fixed (and there is still no target hook as proposed
+ in PR92932).  Just disable respective bogus optimization.  */
+  flag_ipa_icf_variables = 0;
+
   if (flag_pic == 1)
 warning (OPT_fpic, "%<-fpic%> is not supported");
   if (flag_pic == 2)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr92606.c 
b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
new file mode 100644
index 000..cc07128c73b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef uint32_t T;
+
+#define NI __attribute__((noinline,noclone))
+
+
+#ifndef __AVR_TINY__
+#define read_u32(X) \
+(__extension__( \
+{   \
+uint16_t __addr16 = (uint16_t)(X);  \
+uint32_t __result;  \
+__asm__ __volatile__ ("lpm %A0, Z+" "\n\t"  \
+  "lpm %B0, Z+" "\n\t"  \
+  "lpm %C0, Z+" "\n\t"  \
+  "lpm %D0, Z" "\n\t"   \
+  : "=r" (__result), "+z" (__addr16));  \
+__result;   \
+}))
+#else
+NI uint32_t read_u32 (const uint32_t *p)
+{
+   return *p;
+}
+#endif
+
+static const __attribute((progmem)) T xyz_prog[] = { 123, 123, 123 };
+T xyz[] = { 123, 123, 123 };
+volatile int x = 0;
+
+NI void prf (T f)
+{
+if (f != 123)
+__builtin_abort();
+}
+
+NI void func_progmem()
+{
+prf (read_u32 (&xyz_prog[0]));
+}
+
+NI void func_ram()
+{
+prf (xyz[x]);
+}
+
+int main (void)
+{
+func_progmem();
+func_ram();
+
+   return 0;
+}


[gcc r15-270] Minor range type fixes for IPA in preparation for prange.

2024-05-07 Thread Aldy Hernandez via Gcc-cvs
https://gcc.gnu.org/g:24853cd854eb9b8a5c7b9706ad0908221bf964ce

commit r15-270-g24853cd854eb9b8a5c7b9706ad0908221bf964ce
Author: Aldy Hernandez 
Date:   Tue Mar 19 17:55:58 2024 +0100

Minor range type fixes for IPA in preparation for prange.

The polymorphic Value_Range object takes a tree type at construction
so it can determine what type of range to use (currently irange or
frange).  It seems a few of the types are slightly off.  This isn't a
problem now, because IPA only cares about integers and pointers, which
can both live in an irange.  However, with prange coming about, we
need to get the type right, because you can't store an integer in a
pointer range or vice versa.

Also, in preparation for prange, the irange::supports_p() idiom will become:

  irange::supports_p () || prange::supports_p()

To avoid changing all these places, I've added an inline function we
can later change and change everything at once.

Finally, there's a Value_Range::supports_type_p() &&
irange::supports_p() in the code.  The latter is a subset of the
former, so there's no need to check both.

gcc/ChangeLog:

* ipa-cp.cc (ipa_vr_operation_and_type_effects): Use ipa_supports_p.
(ipa_value_range_from_jfunc): Change Value_Range type.
(propagate_vr_across_jump_function): Same.
* ipa-cp.h (ipa_supports_p): New.
* ipa-fnsummary.cc (evaluate_conditions_for_known_args): Change 
Value_Range type.
* ipa-prop.cc (ipa_compute_jump_functions_for_edge): Use 
ipa_supports_p.
(ipcp_get_parm_bits): Same.

Diff:
---
 gcc/ipa-cp.cc| 14 +++---
 gcc/ipa-cp.h |  8 
 gcc/ipa-fnsummary.cc |  2 +-
 gcc/ipa-prop.cc  |  8 +++-
 4 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index a688dced5c9..5781f50c854 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1649,7 +1649,7 @@ ipa_vr_operation_and_type_effects (vrange &dst_vr,
   enum tree_code operation,
   tree dst_type, tree src_type)
 {
-  if (!irange::supports_p (dst_type) || !irange::supports_p (src_type))
+  if (!ipa_supports_p (dst_type) || !ipa_supports_p (src_type))
 return false;
 
   range_op_handler handler (operation);
@@ -1720,7 +1720,7 @@ ipa_value_range_from_jfunc (vrange &vr,
 
   if (TREE_CODE_CLASS (operation) == tcc_unary)
{
- Value_Range res (vr_type);
+ Value_Range res (parm_type);
 
  if (ipa_vr_operation_and_type_effects (res,
 srcvr,
@@ -1733,7 +1733,7 @@ ipa_value_range_from_jfunc (vrange &vr,
  Value_Range op_res (vr_type);
  Value_Range res (vr_type);
  tree op = ipa_get_jf_pass_through_operand (jfunc);
- Value_Range op_vr (vr_type);
+ Value_Range op_vr (TREE_TYPE (op));
  range_op_handler handler (operation);
 
  ipa_range_set_and_normalize (op_vr, op);
@@ -2527,7 +2527,7 @@ propagate_vr_across_jump_function (cgraph_edge *cs, 
ipa_jump_func *jfunc,
   if (src_lats->m_value_range.bottom_p ())
return dest_lat->set_to_bottom ();
 
-  Value_Range vr (operand_type);
+  Value_Range vr (param_type);
   if (TREE_CODE_CLASS (operation) == tcc_unary)
ipa_vr_operation_and_type_effects (vr,
   src_lats->m_value_range.m_vr,
@@ -2540,16 +2540,16 @@ propagate_vr_across_jump_function (cgraph_edge *cs, 
ipa_jump_func *jfunc,
{
  tree op = ipa_get_jf_pass_through_operand (jfunc);
  Value_Range op_vr (TREE_TYPE (op));
- Value_Range op_res (operand_type);
+ Value_Range op_res (param_type);
  range_op_handler handler (operation);
 
  ipa_range_set_and_normalize (op_vr, op);
 
  if (!handler
- || !op_res.supports_type_p (operand_type)
+ || !ipa_supports_p (operand_type)
  || !handler.fold_range (op_res, operand_type,
  src_lats->m_value_range.m_vr, op_vr))
-   op_res.set_varying (operand_type);
+   op_res.set_varying (param_type);
 
  ipa_vr_operation_and_type_effects (vr,
 op_res,
diff --git a/gcc/ipa-cp.h b/gcc/ipa-cp.h
index 7ff74fb5c98..abeaaa4053e 100644
--- a/gcc/ipa-cp.h
+++ b/gcc/ipa-cp.h
@@ -291,4 +291,12 @@ public:
 
 bool values_equal_for_ipcp_p (tree x, tree y);
 
+/* Return TRUE if IPA supports ranges of TYPE.  */
+
+static inline bool
+ipa_supports_p (tree type)
+{
+  return irange::supports_p (type);
+}
+
 #endif /* IPA_CP_H */
diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index 668a01ef175..07a853f78e3 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -515,7 +515,7 @@ evaluate_conditions_for_known_args (struct cgraph_nod

[gcc r12-10418] AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:231728b6dd7684e031f2a05e7e43bab54b7f2c5e

commit r12-10418-g231728b6dd7684e031f2a05e7e43bab54b7f2c5e
Author: Georg-Johann Lay 
Date:   Fri May 3 18:47:50 2024 +0200

AVR: ipa/92606 - Don't optimize PROGMEM data against non-PROGMEM.

ipa/92606: Inter-procedural analysis optimizes data across
address-spaces and PROGMEM.  As of v14, the PROGMEM part is
still not fixed (and there is still no target hook as proposed
in PR92932).  Just disable respective bogus optimization.

PR ipa/92606
gcc/
* config/avr/avr.cc (avr_option_override): Set
flag_ipa_icf_variables = 0.
gcc/testsuite/
* gcc.target/avr/torture/pr92606.c: New test.

(cherry picked from commit 08e752e72363ae7fd5a5fcb70913a0f7b240387b)

Diff:
---
 gcc/config/avr/avr.cc  | 10 +
 gcc/testsuite/gcc.target/avr/torture/pr92606.c | 57 ++
 2 files changed, 67 insertions(+)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 1905ac5790c..bc15017c61c 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -1095,6 +1095,16 @@ avr_option_override (void)
   flag_omit_frame_pointer = 0;
 }
 
+  /* Disable flag_delete_null_pointer_checks if zero is a valid address. */
+  if (targetm.addr_space.zero_address_valid (ADDR_SPACE_GENERIC))
+flag_delete_null_pointer_checks = 0;
+
+  /* PR ipa/92606: Inter-procedural analysis optimizes data across
+ address-spaces and PROGMEM.  As of v14, the PROGMEM part is
+ still not fixed (and there is still no target hook as proposed
+ in PR92932).  Just disable respective bogus optimization.  */
+  flag_ipa_icf_variables = 0;
+
   if (flag_pic == 1)
 warning (OPT_fpic, "%<-fpic%> is not supported");
   if (flag_pic == 2)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr92606.c 
b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
new file mode 100644
index 000..cc07128c73b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr92606.c
@@ -0,0 +1,57 @@
+/* { dg-do run } */
+
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+
+typedef uint32_t T;
+
+#define NI __attribute__((noinline,noclone))
+
+
+#ifndef __AVR_TINY__
+#define read_u32(X) \
+(__extension__( \
+{   \
+uint16_t __addr16 = (uint16_t)(X);  \
+uint32_t __result;  \
+__asm__ __volatile__ ("lpm %A0, Z+" "\n\t"  \
+  "lpm %B0, Z+" "\n\t"  \
+  "lpm %C0, Z+" "\n\t"  \
+  "lpm %D0, Z" "\n\t"   \
+  : "=r" (__result), "+z" (__addr16));  \
+__result;   \
+}))
+#else
+NI uint32_t read_u32 (const uint32_t *p)
+{
+   return *p;
+}
+#endif
+
+static const __attribute((progmem)) T xyz_prog[] = { 123, 123, 123 };
+T xyz[] = { 123, 123, 123 };
+volatile int x = 0;
+
+NI void prf (T f)
+{
+if (f != 123)
+__builtin_abort();
+}
+
+NI void func_progmem()
+{
+prf (read_u32 (&xyz_prog[0]));
+}
+
+NI void func_ram()
+{
+prf (xyz[x]);
+}
+
+int main (void)
+{
+func_progmem();
+func_ram();
+
+   return 0;
+}


[gcc r15-271] middle-end/114931 - type_hash_canon and structual equality types

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:b09c2e9560648b0cf993c2ca9ad972c34e6bddfa

commit r15-271-gb09c2e9560648b0cf993c2ca9ad972c34e6bddfa
Author: Richard Biener 
Date:   Fri May 3 10:44:50 2024 +0200

middle-end/114931 - type_hash_canon and structual equality types

TYPE_STRUCTURAL_EQUALITY_P is part of our type system so we have
to make sure to include that into the type unification done via
type_hash_canon.  This requires the flag to be set before querying
the hash which is the biggest part of the patch.

PR middle-end/114931
gcc/
* tree.cc (type_hash_canon_hash): Hash TYPE_STRUCTURAL_EQUALITY_P.
(type_cache_hasher::equal): Compare TYPE_STRUCTURAL_EQUALITY_P.
(build_array_type_1): Set TYPE_STRUCTURAL_EQUALITY_P before
probing with type_hash_canon.
(build_function_type): Likewise.
(build_method_type_directly): Likewise.
(build_offset_type): Likewise.
(build_complex_type): Likewise.
* attribs.cc (build_type_attribute_qual_variant): Likewise.

gcc/c-family/
* c-common.cc (complete_array_type): Set TYPE_STRUCTURAL_EQUALITY_P
before probing with type_hash_canon.

gcc/testsuite/
* gcc.dg/pr114931.c: New testcase.

Diff:
---
 gcc/attribs.cc  | 20 ++---
 gcc/c-family/c-common.cc| 11 +--
 gcc/testsuite/gcc.dg/pr114931.c | 10 +++
 gcc/tree.cc | 65 +
 4 files changed, 74 insertions(+), 32 deletions(-)

diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index 12ffc5f170a..3ab0b0fd87a 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -1336,6 +1336,16 @@ build_type_attribute_qual_variant (tree otype, tree 
attribute, int quals)
   tree dtype = ntype = build_distinct_type_copy (ttype);
 
   TYPE_ATTRIBUTES (ntype) = attribute;
+  /* If the target-dependent attributes make NTYPE different from
+its canonical type, we will need to use structural equality
+checks for this type.
+
+We shouldn't get here for stripping attributes from a type;
+the no-attribute type might not need structural comparison.  But
+we can if was discarded from type_hash_table.  */
+  if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
+ || !comp_type_attributes (ntype, ttype))
+   SET_TYPE_STRUCTURAL_EQUALITY (ntype);
 
   hashval_t hash = type_hash_canon_hash (ntype);
   ntype = type_hash_canon (hash, ntype);
@@ -1343,16 +1353,6 @@ build_type_attribute_qual_variant (tree otype, tree 
attribute, int quals)
   if (ntype != dtype)
/* This variant was already in the hash table, don't mess with
   TYPE_CANONICAL.  */;
-  else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
-  || !comp_type_attributes (ntype, ttype))
-   /* If the target-dependent attributes make NTYPE different from
-  its canonical type, we will need to use structural equality
-  checks for this type.
-
-  We shouldn't get here for stripping attributes from a type;
-  the no-attribute type might not need structural comparison.  But
-  we can if was discarded from type_hash_table.  */
-   SET_TYPE_STRUCTURAL_EQUALITY (ntype);
   else if (TYPE_CANONICAL (ntype) == ntype)
TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
 
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 01e3d247fc2..032dcb4b41d 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -7115,6 +7115,13 @@ complete_array_type (tree *ptype, tree initial_value, 
bool do_default)
   TYPE_TYPELESS_STORAGE (main_type) = TYPE_TYPELESS_STORAGE (type);
   layout_type (main_type);
 
+  /* Set TYPE_STRUCTURAL_EQUALITY_P early.  */
+  if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
+  || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
+SET_TYPE_STRUCTURAL_EQUALITY (main_type);
+  else
+TYPE_CANONICAL (main_type) = main_type;
+
   /* Make sure we have the canonical MAIN_TYPE. */
   hashval_t hashcode = type_hash_canon_hash (main_type);
   main_type = type_hash_canon (hashcode, main_type);
@@ -7122,7 +7129,7 @@ complete_array_type (tree *ptype, tree initial_value, 
bool do_default)
   /* Fix the canonical type.  */
   if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
   || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
-SET_TYPE_STRUCTURAL_EQUALITY (main_type);
+gcc_assert (TYPE_STRUCTURAL_EQUALITY_P (main_type));
   else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
   || (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
   != TYPE_DOMAIN (main_type)))
@@ -7130,8 +7137,6 @@ complete_array_type (tree *ptype, tree initial_value, 
bool do_default)
   = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
  TYPE_CANONICAL (TYPE_DOMAIN (main_type)),

[gcc r15-272] build: Derive object names in make_sunver.pl

2024-05-07 Thread Rainer Orth via Libstdc++-cvs
https://gcc.gnu.org/g:35b05a02de1e8aee7c754a20f50736977c71caca

commit r15-272-g35b05a02de1e8aee7c754a20f50736977c71caca
Author: Rainer Orth 
Date:   Tue May 7 13:14:05 2024 +0200

build: Derive object names in make_sunver.pl

The recent move of libgfortran object files to subdirs and the resulting
breakage of libgfortran.so symbol exports demonstrated how fragile
deriving object and archive names from their libtool counterparts in the
Makefiles is.  Therefore, this patch moves that step into
make_sunver.pl, considerably simplifying the Makefile rules to create
the version scripts.

Bootstrapped without regressions on i386-pc-solaris2.11 and
sparc-sun-solaris2.11, verifying that the version scripts are identical
except for the input filenames.

2024-05-06  Rainer Orth  

contrib:
* make_sunver.pl: Use File::Basename;
Skip -lLIB args.
Convert libtool object/archive names to underlying
objects/archives.

libatomic:
* Makefile.am [LIBAT_BUILD_VERSIONED_SHLIB_SUN]
(libatomic.map-sun): Pass $(libatomic_la_OBJECTS),
$(libatomic_la_LIBADD) to make_sunver.pl unmodified.
* Makefile.in: Regenerate.

libffi:
* Makefile.am [LIBFFI_BUILD_VERSIONED_SHLIB_SUN] (libffi.map-sun):
Pass $(libffi_la_OBJECTS), $(libffi_la_LIBADD) to make_sunver.pl
unmodified.
* Makefile.in: Regenerate.

libgfortran:
* Makefile.am [LIBGFOR_USE_SYMVER_SUN} (gfortran.ver-sun): Pass
$(libgfortran_la_OBJECTS), $(libgfortran_la_LIBADD) to
make_sunver.pl unmodified.
* Makefile.in: Regenerate.

libgomp:
* Makefile.am [LIBGOMP_BUILD_VERSIONED_SHLIB_SUN]
(libgomp.ver-sun): Pass $(libgomp_la_OBJECTS),
$(libgomp_la_LIBADD) to make_sunver.pl unmodified.
* Makefile.in: Regenerate.

libitm:
* Makefile.am [LIBITM_BUILD_VERSIONED_SHLIB_SUN] (libitm.map-sun):
Pass $(libitm_la_OBJECTS), $(libitm_la_LIBADD) to make_sunver.pl
unmodified.
* Makefile.in: Regenerate.

libquadmath:
* Makefile.am [LIBQUAD_USE_SYMVER_SUN] (quadmath.map-sun): Pass
$(libquadmath_la_OBJECTS), $(libquadmath_la_LIBADD) to
make_sunver.pl unmodified.
* Makefile.in: Regenerate.

libssp:
* Makefile.am [LIBSSP_USE_SYMVER_SUN] (ssp.map-sun): Pass
$(libssp_la_OBJECTS), $(libssp_la_LIBADD) to make_sunver.pl
unmodified.
* Makefile.in: Regenerate.

libstdc++-v3:
* src/Makefile.am [ENABLE_SYMVERS_SUN]
(libstdc++-symbols.ver-sun): Pass $(libstdc___la_OBJECTS),
$(libstdc___la_LIBADD) to make_sunver.pl unmodified.
* src/Makefile.in: Regenerate.

Diff:
---
 contrib/make_sunver.pl   | 15 +--
 libatomic/Makefile.am|  4 +---
 libatomic/Makefile.in|  4 +---
 libffi/Makefile.am   |  3 +--
 libffi/Makefile.in   |  3 +--
 libgfortran/Makefile.am  |  4 +---
 libgfortran/Makefile.in  |  4 +---
 libgomp/Makefile.am  |  4 +---
 libgomp/Makefile.in  |  4 +---
 libitm/Makefile.am   |  4 +---
 libitm/Makefile.in   |  4 +---
 libquadmath/Makefile.am  |  3 +--
 libquadmath/Makefile.in  |  3 +--
 libssp/Makefile.am   |  4 +---
 libssp/Makefile.in   |  4 +---
 libstdc++-v3/src/Makefile.am |  4 +---
 libstdc++-v3/src/Makefile.in |  4 +---
 17 files changed, 29 insertions(+), 46 deletions(-)

diff --git a/contrib/make_sunver.pl b/contrib/make_sunver.pl
index 32e639ed873..4dd184d64ea 100644
--- a/contrib/make_sunver.pl
+++ b/contrib/make_sunver.pl
@@ -17,6 +17,7 @@
 # GNU mangling style.
 
 use FileHandle;
+use File::Basename;
 use IPC::Open2;
 
 # Enforce C locale.
@@ -37,12 +38,22 @@ my @OBJECTS = ();
 # List of shared objects to omit from processing.
 my @SHAREDOBJS = ();
 
-# Filter out those input archives that have corresponding shared objects to
-# avoid adding all symbols matched in the archive to the output map.
 foreach $file (@ARGV) {
+# Filter out those input archives that have corresponding shared objects to
+# avoid adding all symbols matched in the archive to the output map.
 if (($so = $file) =~ s/\.a$/.so/ && -e $so) {
printf STDERR "omitted $file -> $so\n";
push (@SHAREDOBJS, $so);
+# Skip libraries.
+} elsif ($file =~ /^-l/) {
+   next;
+# Convert libtool object/archive names to underlying objects/archives.
+} elsif ($file =~ /\.l[ao]$/) {
+   my ($name, $path, $suffix) = fileparse($file, ".l[ao]");
+   $suffix =~ s/l//;
+   # Strip leading ./ prepended by fileparse.
+   $path =~ s%^\./%%;
+   push (@OBJECTS, "$

[gcc r15-273] Use unsigned for stack var indexes during RTL expansion

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:c69eda94f28384b7f30e2b40aebb097ef59e522f

commit r15-273-gc69eda94f28384b7f30e2b40aebb097ef59e522f
Author: Richard Biener 
Date:   Thu Apr 4 13:01:10 2024 +0200

Use unsigned for stack var indexes during RTL expansion

We're currently using size_t but at the same time storing them into
bitmaps which only support unsigned int index.  The following makes
it unsigned int throughout, saving memory as well.

* cfgexpand.cc (stack_var::representative): Use 'unsigned'
for stack var indexes instead of 'size_t'.
(stack_var::next): Likewise.
(EOC): Likewise.
(stack_vars_alloc): Likewise.
(stack_vars_num): Likewise.
(decl_to_stack_part): Likewise.
(stack_vars_sorted): Likewise.
(add_stack_var): Likewise.
(add_stack_var_conflict): Likewise.
(stack_var_conflict_p): Likewise.
(visit_op): Likewise.
(visit_conflict): Likewise.
(add_scope_conflicts_1): Likewise.
(stack_var_cmp): Likewise.
(part_hashmap): Likewise.
(update_alias_info_with_stack_vars): Likewise.
(union_stack_vars): Likewise.
(partition_stack_vars): Likewise.
(dump_stack_var_partition): Likewise.
(expand_stack_vars): Likewise.
(account_stack_vars): Likewise.
(stack_protect_decl_phase_1): Likewise.
(stack_protect_decl_phase_2): Likewise.
(asan_decl_phase_3): Likewise.
(init_vars_expansion): Likewise.
(estimated_stack_frame_size): Likewise.

Diff:
---
 gcc/cfgexpand.cc | 75 
 1 file changed, 37 insertions(+), 38 deletions(-)

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index afee064aa15..557cb28733b 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -320,22 +320,22 @@ public:
   unsigned int alignb;
 
   /* The partition representative.  */
-  size_t representative;
+  unsigned representative;
 
   /* The next stack variable in the partition, or EOC.  */
-  size_t next;
+  unsigned next;
 
   /* The numbers of conflicting stack variables.  */
   bitmap conflicts;
 };
 
-#define EOC  ((size_t)-1)
+#define EOC  ((unsigned)-1)
 
 /* We have an array of such objects while deciding allocation.  */
 static class stack_var *stack_vars;
-static size_t stack_vars_alloc;
-static size_t stack_vars_num;
-static hash_map *decl_to_stack_part;
+static unsigned stack_vars_alloc;
+static unsigned stack_vars_num;
+static hash_map *decl_to_stack_part;
 
 /* Conflict bitmaps go on this obstack.  This allows us to destroy
all of them in one big sweep.  */
@@ -343,7 +343,7 @@ static bitmap_obstack stack_var_bitmap_obstack;
 
 /* An array of indices such that stack_vars[stack_vars_sorted[i]].size
is non-decreasing.  */
-static size_t *stack_vars_sorted;
+static unsigned *stack_vars_sorted;
 
 /* The phase of the stack frame.  This is the known misalignment of
virtual_stack_vars_rtx from PREFERRED_STACK_BOUNDARY.  That is,
@@ -457,7 +457,7 @@ add_stack_var (tree decl, bool really_expand)
= XRESIZEVEC (class stack_var, stack_vars, stack_vars_alloc);
 }
   if (!decl_to_stack_part)
-decl_to_stack_part = new hash_map;
+decl_to_stack_part = new hash_map;
 
   v = &stack_vars[stack_vars_num];
   decl_to_stack_part->put (decl, stack_vars_num);
@@ -491,7 +491,7 @@ add_stack_var (tree decl, bool really_expand)
 /* Make the decls associated with luid's X and Y conflict.  */
 
 static void
-add_stack_var_conflict (size_t x, size_t y)
+add_stack_var_conflict (unsigned x, unsigned y)
 {
   class stack_var *a = &stack_vars[x];
   class stack_var *b = &stack_vars[y];
@@ -508,7 +508,7 @@ add_stack_var_conflict (size_t x, size_t y)
 /* Check whether the decls associated with luid's X and Y conflict.  */
 
 static bool
-stack_var_conflict_p (size_t x, size_t y)
+stack_var_conflict_p (unsigned x, unsigned y)
 {
   class stack_var *a = &stack_vars[x];
   class stack_var *b = &stack_vars[y];
@@ -537,7 +537,7 @@ visit_op (gimple *, tree op, tree, void *data)
   && DECL_P (op)
   && DECL_RTL_IF_SET (op) == pc_rtx)
 {
-  size_t *v = decl_to_stack_part->get (op);
+  unsigned *v = decl_to_stack_part->get (op);
   if (v)
bitmap_set_bit (active, *v);
 }
@@ -557,10 +557,10 @@ visit_conflict (gimple *, tree op, tree, void *data)
   && DECL_P (op)
   && DECL_RTL_IF_SET (op) == pc_rtx)
 {
-  size_t *v = decl_to_stack_part->get (op);
+  unsigned *v = decl_to_stack_part->get (op);
   if (v && bitmap_set_bit (active, *v))
{
- size_t num = *v;
+ unsigned num = *v;
  bitmap_iterator bi;
  unsigned i;
  gcc_assert (num < stack_vars_num);
@@ -627,7 +627,7 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool 
for_conflict)
   if (gimple_clobber_p (

[gcc r12-10419] AVR: Backport device support from v13.3.

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:ef10d72003f87ab2d88c852da75d407c0c990e99

commit r12-10419-gef10d72003f87ab2d88c852da75d407c0c990e99
Author: Georg-Johann Lay 
Date:   Tue May 7 14:00:43 2024 +0200

AVR: Backport device support from v13.3.

gcc/
* config/avr/avr-mcus.def: Add new MCUs (copy from gcc-13).
* doc/avr-mmcu.texi: Rebuild.

Diff:
---
 gcc/config/avr/avr-mcus.def | 79 +++--
 gcc/doc/avr-mmcu.texi   | 10 +++---
 2 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def
index db28d9b1b0a..876fecd8aa1 100644
--- a/gcc/config/avr/avr-mcus.def
+++ b/gcc/config/avr/avr-mcus.def
@@ -166,12 +166,15 @@ AVR_MCU ("at90pwm3b",ARCH_AVR4, AVR_ISA_NONE,  
"__AVR_AT90PWM3B__",
 AVR_MCU ("at90pwm81",ARCH_AVR4, AVR_ISA_NONE,  "__AVR_AT90PWM81__",
0x0100, 0x0, 0x2000, 0)
 /* Enhanced, > 8K, <= 64K.  */
 AVR_MCU ("avr5", ARCH_AVR5, AVR_ISA_NONE, NULL,
0x0060, 0x0, 0x4000, 0)
-AVR_MCU ("ata5702m322",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5702M322__",   
0x0200, 0x0, 0x1, 0)
+AVR_MCU ("ata5700m322",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5700M322__",   
0x0200, 0x8000, 0x1, 0)
+AVR_MCU ("ata5702m322",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5702M322__",   
0x0200, 0x8000, 0x1, 0)
 AVR_MCU ("ata5782",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5782__",   
0x0200, 0x8000, 0xd000, 0)
+AVR_MCU ("ata5787",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5787__",   
0x0200, 0x8000, 0xd200, 0)
 AVR_MCU ("ata5790",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5790__",   
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata5790n", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5790N__",  
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata5791",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5791__",   
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata5831",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5831__",   
0x0200, 0x8000, 0xd000, 0)
+AVR_MCU ("ata5835",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA5835__",   
0x0200, 0x8000, 0xd200, 0)
 AVR_MCU ("ata6613c", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA6613C__",  
0x0100, 0x0, 0x4000, 0)
 AVR_MCU ("ata6614q", ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA6614Q__",  
0x0100, 0x0, 0x8000, 0)
 AVR_MCU ("ata8210",  ARCH_AVR5, AVR_ISA_NONE, "__AVR_ATA8210__",   
0x0200, 0x8000, 0xd000, 0)
@@ -291,7 +294,7 @@ AVR_MCU ("atmega2560",   ARCH_AVR6, AVR_ISA_NONE, 
"__AVR_ATmega2560__",
 AVR_MCU ("atmega2561",   ARCH_AVR6, AVR_ISA_NONE, "__AVR_ATmega2561__",
0x0200, 0x0, 0x4, 0)
 AVR_MCU ("atmega256rfr2",ARCH_AVR6, AVR_ISA_NONE, "__AVR_ATmega256RFR2__", 
0x0200, 0x0, 0x4, 0)
 AVR_MCU ("atmega2564rfr2",   ARCH_AVR6, AVR_ISA_NONE, 
"__AVR_ATmega2564RFR2__",0x0200, 0x0, 0x4, 0)
-/* Xmega, 16K <= Flash < 64K, RAM <= 64K */
+/* Xmega, 16K <= Flash <= 64K, RAM <= 64K */
 AVR_MCU ("avrxmega2",ARCH_AVRXMEGA2, AVR_ISA_NONE, NULL,   
0x2000, 0x0, 0x9000, 0)
 AVR_MCU ("atxmega8e5",   ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_ATxmega8E5__",   0x2000, 0x0, 0x2800, 0)
 AVR_MCU ("atxmega16a4",  ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_ATxmega16A4__",  0x2000, 0x0, 0x5000, 0)
@@ -306,6 +309,23 @@ AVR_MCU ("atxmega16c4",  ARCH_AVRXMEGA2, AVR_ISA_RMW,  
"__AVR_ATxmega16C4__"
 AVR_MCU ("atxmega32a4u", ARCH_AVRXMEGA2, AVR_ISA_RMW,  
"__AVR_ATxmega32A4U__", 0x2000, 0x0, 0x9000, 0)
 AVR_MCU ("atxmega32c4",  ARCH_AVRXMEGA2, AVR_ISA_RMW,  
"__AVR_ATxmega32C4__",  0x2000, 0x0, 0x9000, 0)
 AVR_MCU ("atxmega32e5",  ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_ATxmega32E5__",  0x2000, 0x0, 0x9000, 0)
+AVR_MCU ("avr64da28",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA28__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64da32",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA32__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64da48",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA48__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64da64",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DA64__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db28",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB28__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db32",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB32__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db48",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB48__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64db64",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DB64__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64dd14",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DD14__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64dd20",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DD20__",0x6000, 0x0, 0x1, 0)
+AVR_MCU ("avr64dd28",ARCH_AVRXMEGA2, AVR_ISA_NONE, 
"__AVR_AVR64DD28__",0x6000, 0x0, 0x1, 0)
+A

[gcc r15-274] tree-optimization/110490 - bitcount for narrow modes

2024-05-07 Thread Stefan Schulze Frielinghaus via Gcc-cvs
https://gcc.gnu.org/g:e1f56c67a82172730c377a96a46e8d75445e6a48

commit r15-274-ge1f56c67a82172730c377a96a46e8d75445e6a48
Author: Stefan Schulze Frielinghaus 
Date:   Tue May 7 14:12:55 2024 +0200

tree-optimization/110490 - bitcount for narrow modes

Bitcount operations popcount, clz, and ctz are emulated for narrow modes
in case an operation is only supported for wider modes.  Beside that ctz
may be emulated via clz in expand_ctz.  Reflect this in
expression_expensive_p.

I considered the emulation of ctz via clz as not expensive since this
basically reduces to ctz (x) = c - (clz (x & ~x)) where c is the mode
precision minus 1 which should be faster than a loop.

gcc/ChangeLog:

PR tree-optimization/110490
* tree-scalar-evolution.cc (expression_expensive_p): Also
consider mode widening for popcount, clz, and ctz.

Diff:
---
 gcc/tree-scalar-evolution.cc | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc
index b0a5e09a77c..622c7246c1b 100644
--- a/gcc/tree-scalar-evolution.cc
+++ b/gcc/tree-scalar-evolution.cc
@@ -3458,6 +3458,28 @@ bitcount_call:
  && (optab_handler (optab, word_mode)
  != CODE_FOR_nothing))
  break;
+ /* If popcount is available for a wider mode, we emulate the
+operation for a narrow mode by first zero-extending the value
+and then computing popcount in the wider mode.  Analogue for
+ctz.  For clz we do the same except that we additionally have
+to subtract the difference of the mode precisions from the
+result.  */
+ if (is_a  (mode, &int_mode))
+   {
+ machine_mode wider_mode_iter;
+ FOR_EACH_WIDER_MODE (wider_mode_iter, mode)
+   if (optab_handler (optab, wider_mode_iter)
+   != CODE_FOR_nothing)
+ goto check_call_args;
+ /* Operation ctz may be emulated via clz in expand_ctz.  */
+ if (optab == ctz_optab)
+   {
+ FOR_EACH_WIDER_MODE_FROM (wider_mode_iter, mode)
+   if (optab_handler (clz_optab, wider_mode_iter)
+   != CODE_FOR_nothing)
+ goto check_call_args;
+   }
+   }
  return true;
}
  break;
@@ -3469,6 +3491,7 @@ bitcount_call:
  break;
}
 
+check_call_args:
   FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
if (expression_expensive_p (arg, cond_overflow_p, cache, op_cost))
  return true;


[gcc r15-275] Remove redundant check

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:cc2f3e408ee095653e6658b3126efce717a5586e

commit r15-275-gcc2f3e408ee095653e6658b3126efce717a5586e
Author: Richard Biener 
Date:   Mon Jan 8 08:15:51 2024 +0100

Remove redundant check

operand_equal_p already has checking code to verify the hash
is equal, avoid doing that again in gimplify_hasher::equal.

* gimplify.cc (gimplify_hasher::equal): Remove redundant
checking.

Diff:
---
 gcc/gimplify.cc | 4 
 1 file changed, 4 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 457b33a4293..7f94f5f5098 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -19593,9 +19593,5 @@ gimplify_hasher::equal (const elt_t *p1, const elt_t 
*p2)
   if (!operand_equal_p (t1, t2, 0))
 return false;
 
-  /* Only allow them to compare equal if they also hash equal; otherwise
- results are nondeterminate, and we fail bootstrap comparison.  */
-  gcc_checking_assert (hash (p1) == hash (p2));
-
   return true;
 }


[gcc r15-276] middle-end/27800 - avoid unnecessary temporary during gimplification

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:bed6ec161be8c5ca2f24195900ce3c9b81c3e141

commit r15-276-gbed6ec161be8c5ca2f24195900ce3c9b81c3e141
Author: Richard Biener 
Date:   Tue Feb 20 11:47:03 2024 +0100

middle-end/27800 - avoid unnecessary temporary during gimplification

This avoids a tempoary when gimplifying reg = a ? b : c, re-using
the LHS of an assignment if that's a register.

PR middle-end/27800
* gimplify.cc (gimplify_modify_expr_rhs): For a COND_EXPR
avoid a temporary from gimplify_cond_expr when the LHS is
a register by pushing the assignment into the COND_EXPR arms.

* gcc.dg/pr27800.c: New testcase.

Diff:
---
 gcc/gimplify.cc|  7 +--
 gcc/testsuite/gcc.dg/pr27800.c | 11 +++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 7f94f5f5098..b0ed58ed0f9 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -6078,8 +6078,11 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, 
tree *to_p,
  /* If we're assigning to a non-register type, push the assignment
 down into the branches.  This is mandatory for ADDRESSABLE types,
 since we cannot generate temporaries for such, but it saves a
-copy in other cases as well.  */
- if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
+copy in other cases as well.
+Also avoid an extra temporary and copy when assigning to
+a register.  */
+ if (!is_gimple_reg_type (TREE_TYPE (*from_p))
+ || (is_gimple_reg (*to_p) && !gimplify_ctxp->allow_rhs_cond_expr))
{
  /* This code should mirror the code in gimplify_cond_expr. */
  enum tree_code code = TREE_CODE (*expr_p);
diff --git a/gcc/testsuite/gcc.dg/pr27800.c b/gcc/testsuite/gcc.dg/pr27800.c
new file mode 100644
index 000..e92ebc22e6f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr27800.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+int iii (int a, int b, int c)
+{
+  return a ? b : c;
+}
+
+/* Verify we end up with two assignments and not an extra copy
+   resulting from another temporary generated from gimplify_cond_expr.  */
+/* { dg-final { scan-tree-dump-times " = " 2 "gimple" } } */


[gcc r15-277] libstdc++: Update ABI test to disallow adding to released symbol versions

2024-05-07 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:6e25ca387fbbb412a2e498e28ea5db28e033a318

commit r15-277-g6e25ca387fbbb412a2e498e28ea5db28e033a318
Author: Jonathan Wakely 
Date:   Thu Apr 11 15:35:11 2024 +0100

libstdc++: Update ABI test to disallow adding to released symbol versions

If we update the list of "active" symbols versions now, rather than when
adding a new symbol version, we will notice if new symbols get added to
the wrong version (as in PR 114692).

libstdc++-v3/ChangeLog:

* testsuite/util/testsuite_abi.cc: Update latest versions to
new versions that should be used in future.

Diff:
---
 libstdc++-v3/testsuite/util/testsuite_abi.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc 
b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index e4bf3cdc8e0..ec7c3df9ecc 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -254,8 +254,8 @@ check_version(symbol& test, bool added)
test.version_status = symbol::incompatible;
 
   // Check that added symbols are added in the latest pre-release version.
-  bool latestp = (test.version_name == "GLIBCXX_3.4.33"
-|| test.version_name == "CXXABI_1.3.15"
+  bool latestp = (test.version_name == "GLIBCXX_3.4.34"
+|| test.version_name == "CXXABI_1.3.16"
 || test.version_name == "CXXABI_FLOAT128"
 || test.version_name == "CXXABI_TM_1");
   if (added && !latestp)


[gcc r15-278] libstdc++: Use https instead of http in some comments

2024-05-07 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:9ebd123432873edf1551006be07381150fd617ea

commit r15-278-g9ebd123432873edf1551006be07381150fd617ea
Author: Jonathan Wakely 
Date:   Fri May 3 18:14:09 2024 +0100

libstdc++: Use https instead of http in some comments

libstdc++-v3/ChangeLog:

* include/backward/auto_ptr.h: Use https for URL in comment.
* include/bits/basic_ios.h: Likewise.
* include/std/iostream: Likewise.

Diff:
---
 libstdc++-v3/include/backward/auto_ptr.h | 2 +-
 libstdc++-v3/include/bits/basic_ios.h| 6 +++---
 libstdc++-v3/include/std/iostream| 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/include/backward/auto_ptr.h 
b/libstdc++-v3/include/backward/auto_ptr.h
index dccd459f1e5..271a64d1de0 100644
--- a/libstdc++-v3/include/backward/auto_ptr.h
+++ b/libstdc++-v3/include/backward/auto_ptr.h
@@ -265,7 +265,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  @endcode
*
*  But it doesn't work, and won't be fixed. For further details see
-   *  http://cplusplus.github.io/LWG/lwg-closed.html#463
+   *  https://cplusplus.github.io/LWG/lwg-closed.html#463
*/
   auto_ptr(auto_ptr_ref __ref) throw()
   : _M_ptr(__ref._M_ptr) { }
diff --git a/libstdc++-v3/include/bits/basic_ios.h 
b/libstdc++-v3/include/bits/basic_ios.h
index 44a77149112..258e6042b8f 100644
--- a/libstdc++-v3/include/bits/basic_ios.h
+++ b/libstdc++-v3/include/bits/basic_ios.h
@@ -408,7 +408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  with this stream, calls that buffer's @c pubimbue(loc).
*
*  Additional l10n notes are at
-   *  http://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html
+   *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html
   */
   locale
   imbue(const locale& __loc);
@@ -428,7 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  @endcode
*
*  Additional l10n notes are at
-   *  http://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html
+   *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html
   */
   char
   narrow(char_type __c, char __dfault) const
@@ -447,7 +447,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  @endcode
*
*  Additional l10n notes are at
-   *  http://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html
+   *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html
   */
   char_type
   widen(char __c) const
diff --git a/libstdc++-v3/include/std/iostream 
b/libstdc++-v3/include/std/iostream
index 0c6a2d8a4b3..4f4fa6880d5 100644
--- a/libstdc++-v3/include/std/iostream
+++ b/libstdc++-v3/include/std/iostream
@@ -50,7 +50,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
*  The `` header declares the eight *standard stream objects*.
*  For other declarations, see
-   *  http://gcc.gnu.org/onlinedocs/libstdc++/manual/io.html
+   *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/io.html
*  and the @link iosfwd I/O forward declarations @endlink
*
*  They are required by default to cooperate with the global C


[gcc r15-279] libstdc++: Constrain equality ops for std::pair, std::tuple, std::variant

2024-05-07 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:b72e7addf855aed66c0922f17efc85f26193f801

commit r15-279-gb72e7addf855aed66c0922f17efc85f26193f801
Author: Jonathan Wakely 
Date:   Wed Mar 27 15:24:05 2024 +

libstdc++: Constrain equality ops for std::pair, std::tuple, std::variant

Implement the changes from P2944R3 which add constraints to the
comparison operators of std::pair, std::tuple, and std::variant.

The paper also changes std::optional, but we already constrain its
comparisons using SFINAE on the return type. However, we need some
additional constraints on the [optional.comp.with.t] operators that
compare an optional with a value. The paper doesn't say to do that, but
I think it's needed because otherwise when the comparison for two
optional objects fails its constraints, the two overloads that are
supposed to be for comparing to a non-optional become the best overload
candidates, but are ambiguous (and we don't even get as far as checking
the constraints for satisfaction). I reported LWG 4072 for this.

The paper does not change std::expected, but probably should have done.
I'll submit an LWG issue about that and implement it separately.

Also add [[nodiscard]] to all these comparison operators.

libstdc++-v3/ChangeLog:

* include/bits/stl_pair.h (operator==): Add constraint.
* include/bits/version.def (constrained_equality): Define.
* include/bits/version.h: Regenerate.
* include/std/optional: Define feature test macro.
(__optional_rep_op_t): Use is_convertible_v instead of
is_convertible.
* include/std/tuple: Define feature test macro.
(operator==, __tuple_cmp, operator<=>): Reimplement C++20
comparisons using lambdas. Add constraints.
* include/std/utility: Define feature test macro.
* include/std/variant: Define feature test macro.
(_VARIANT_RELATION_FUNCTION_TEMPLATE): Add constraints.
(variant): Remove unnecessary friend declarations for comparison
operators.
* testsuite/20_util/optional/relops/constrained.cc: New test.
* testsuite/20_util/pair/comparison_operators/constrained.cc:
New test.
* testsuite/20_util/tuple/comparison_operators/constrained.cc:
New test.
* testsuite/20_util/variant/relops/constrained.cc: New test.
* testsuite/20_util/tuple/comparison_operators/overloaded.cc:
Disable for C++20 and later.
* testsuite/20_util/tuple/comparison_operators/overloaded2.cc:
Remove dg-error line for target c++20.

Diff:
---
 libstdc++-v3/include/bits/stl_pair.h   |  16 +-
 libstdc++-v3/include/bits/version.def  |   9 +
 libstdc++-v3/include/bits/version.h|  10 +
 libstdc++-v3/include/std/optional  |  50 ++--
 libstdc++-v3/include/std/tuple | 102 
 libstdc++-v3/include/std/utility   |   1 +
 libstdc++-v3/include/std/variant   |  28 +--
 .../20_util/optional/relops/constrained.cc | 258 +
 .../pair/comparison_operators/constrained.cc   |  48 
 .../tuple/comparison_operators/constrained.cc  |  50 
 .../tuple/comparison_operators/overloaded.cc   |   6 +-
 .../tuple/comparison_operators/overloaded2.cc  |   1 -
 .../20_util/variant/relops/constrained.cc  | 175 ++
 13 files changed, 679 insertions(+), 75 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_pair.h 
b/libstdc++-v3/include/bits/stl_pair.h
index 45317417c9c..0c1e5719a1a 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -1000,14 +1000,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template pair(_T1, _T2) -> pair<_T1, _T2>;
 #endif
 
-#if __cpp_lib_three_way_comparison && __cpp_lib_concepts
+#if __cpp_lib_three_way_comparison
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // 3865. Sorting a range of pairs
 
   /// Two pairs are equal iff their members are equal.
   template
-inline _GLIBCXX_CONSTEXPR bool
+[[nodiscard]]
+constexpr bool
 operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y)
+requires requires {
+  { __x.first == __y.first } -> __detail::__boolean_testable;
+  { __x.second == __y.second } -> __detail::__boolean_testable;
+}
 { return __x.first == __y.first && __x.second == __y.second; }
 
   /** Defines a lexicographical order for pairs.
@@ -1018,6 +1023,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* less than `Q.second`.
   */
   template
+[[nodiscard]]
 constexpr common_comparison_category_t<__detail::__synth3way_t<_T1, _U1>,
   __detail::__synth3way_t<_T2, _U2>>
 operator<=>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y)
@@ -1029,6 +1035,7 @@ _GLIBCXX_B

[gcc r15-280] Avoid re-allocating vector

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:cb4e2685a3e73474246adda356595f72fcd43827

commit r15-280-gcb4e2685a3e73474246adda356595f72fcd43827
Author: Richard Biener 
Date:   Wed Apr 17 13:20:40 2024 +0200

Avoid re-allocating vector

The following avoids re-allocating the var map BB vector by
pre-allocating it to the exact size needed when operating on the
whole function.

* tree-ssa-live.cc (init_var_map): Pre-allocate vec_bbs vector
to the correct size and use quick_push.

Diff:
---
 gcc/tree-ssa-live.cc | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/gcc/tree-ssa-live.cc b/gcc/tree-ssa-live.cc
index fa6be2fced3..e6ae551a457 100644
--- a/gcc/tree-ssa-live.cc
+++ b/gcc/tree-ssa-live.cc
@@ -113,8 +113,10 @@ init_var_map (int size, class loop *loop, bitmap bitint)
   map->outofssa_p = bitint == NULL;
   map->bitint = bitint;
   basic_block bb;
+  map->vec_bbs.reserve_exact (n_basic_blocks_for_fn (cfun)
+ - NUM_FIXED_BLOCKS);
   FOR_EACH_BB_FN (bb, cfun)
-   map->vec_bbs.safe_push (bb);
+   map->vec_bbs.quick_push (bb);
 }
   return map;
 }


[gcc r15-281] Fix block index check in insert_updated_phi_nodes_for

2024-05-07 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:bf10f0db20db1598157505b373098bc93c66b915

commit r15-281-gbf10f0db20db1598157505b373098bc93c66b915
Author: Richard Biener 
Date:   Thu Apr 4 15:16:28 2024 +0200

Fix block index check in insert_updated_phi_nodes_for

This replaces a >= 0 block index check with the appropriate 
NUM_FIXED_BLOCKs,
the check is from times ENTRY_BLOCK was negative.

* tree-into-ssa.cc (insert_updated_phi_nodes_for): Fix block
index check.

Diff:
---
 gcc/tree-into-ssa.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/tree-into-ssa.cc b/gcc/tree-into-ssa.cc
index d12a4a97f65..705e4119ba3 100644
--- a/gcc/tree-into-ssa.cc
+++ b/gcc/tree-into-ssa.cc
@@ -3301,7 +3301,7 @@ insert_updated_phi_nodes_for (tree var, bitmap_head *dfs,
 
  mark_block_for_update (bb);
  FOR_EACH_EDGE (e, ei, bb->preds)
-   if (e->src->index >= 0)
+   if (e->src->index >= NUM_FIXED_BLOCKS)
  mark_block_for_update (e->src);
}


[gcc r15-282] aarch64: Preserve mem info on change of base for ldp/stp [PR114674]

2024-05-07 Thread Alex Coplan via Gcc-cvs
https://gcc.gnu.org/g:74690ff96b263b8609639b7fbc5d6afd3f19cb98

commit r15-282-g74690ff96b263b8609639b7fbc5d6afd3f19cb98
Author: Alex Coplan 
Date:   Wed Apr 10 16:30:36 2024 +0100

aarch64: Preserve mem info on change of base for ldp/stp [PR114674]

The ldp/stp fusion pass can change the base of an access so that the two
accesses end up using a common base register.  So far we have been using
adjust_address_nv to do this, but this means that we don't preserve
other properties of the mem we're replacing.  It seems better to use
replace_equiv_address_nv, as this will preserve e.g. the MEM_ALIGN of the
mem whose address we're changing.

The PR shows that by adjusting the other mem we lose alignment
information about the original access and therefore end up rejecting an
otherwise viable pair when --param=aarch64-stp-policy=aligned is passed.
This patch fixes that by using replace_equiv_address_nv instead.

Notably this is the same approach as taken by
aarch64_check_consecutive_mems when a change of base is required, so
this at least makes things more consistent between the ldp fusion pass
and the peepholes.

gcc/ChangeLog:

PR target/114674
* config/aarch64/aarch64-ldp-fusion.cc (ldp_bb_info::fuse_pair):
Use replace_equiv_address_nv on a change of base instead of
adjust_address_nv on the other access.

gcc/testsuite/ChangeLog:

PR target/114674
* gcc.target/aarch64/pr114674.c: New test.

Diff:
---
 gcc/config/aarch64/aarch64-ldp-fusion.cc|  8 
 gcc/testsuite/gcc.target/aarch64/pr114674.c | 17 +
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-ldp-fusion.cc 
b/gcc/config/aarch64/aarch64-ldp-fusion.cc
index 0bc225dae7b..437f0aeb787 100644
--- a/gcc/config/aarch64/aarch64-ldp-fusion.cc
+++ b/gcc/config/aarch64/aarch64-ldp-fusion.cc
@@ -1722,11 +1722,11 @@ ldp_bb_info::fuse_pair (bool load_p,
adjust_amt *= -1;
 
   rtx change_reg = XEXP (change_pat, !load_p);
-  machine_mode mode_for_mem = GET_MODE (change_mem);
   rtx effective_base = drop_writeback (base_mem);
-  rtx new_mem = adjust_address_nv (effective_base,
-  mode_for_mem,
-  adjust_amt);
+  rtx adjusted_addr = plus_constant (Pmode,
+XEXP (effective_base, 0),
+adjust_amt);
+  rtx new_mem = replace_equiv_address_nv (change_mem, adjusted_addr);
   rtx new_set = load_p
? gen_rtx_SET (change_reg, new_mem)
: gen_rtx_SET (new_mem, change_reg);
diff --git a/gcc/testsuite/gcc.target/aarch64/pr114674.c 
b/gcc/testsuite/gcc.target/aarch64/pr114674.c
new file mode 100644
index 000..944784fd008
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr114674.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 --param=aarch64-stp-policy=aligned" } */
+typedef struct {
+   unsigned int f1;
+   unsigned int f2;
+} test_struct;
+
+static test_struct ts = {
+   123, 456
+};
+
+void foo(void)
+{
+   ts.f2 = 36969 * (ts.f2 & 65535) + (ts.f1 >> 16);
+   ts.f1 = 18000 * (ts.f2 & 65535) + (ts.f2 >> 16);
+}
+/* { dg-final { scan-assembler-times "stp" 1 } } */


[gcc r15-283] libstdc++: Simplify std::variant comparison operators

2024-05-07 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:6709e35457a30b2184fa8337aa4abdd2c0edaeb3

commit r15-283-g6709e35457a30b2184fa8337aa4abdd2c0edaeb3
Author: Jonathan Wakely 
Date:   Thu Mar 28 14:19:45 2024 +

libstdc++: Simplify std::variant comparison operators

libstdc++-v3/ChangeLog:

* include/std/variant (_VARIANT_RELATION_FUNCTION_TEMPLATE):
Simplify.

Diff:
---
 libstdc++-v3/include/std/variant | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 8072e1f17a8..bf05eec9a6b 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -1245,7 +1245,7 @@ namespace __variant
 # define _VARIANT_RELATION_FUNCTION_CONSTRAINTS(TYPES, OP)
 #endif
 
-#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \
+#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \
   template \
 _VARIANT_RELATION_FUNCTION_CONSTRAINTS(_Types, __OP) \
 constexpr bool \
@@ -1262,22 +1262,20 @@ namespace __variant
{ \
  auto& __this_mem = std::get<__rhs_index>(__lhs);  \
   __ret = __this_mem __OP __rhs_mem; \
+ return; \
 } \
- else \
-   __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
 } \
-  else \
-__ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
+ __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \
}, __rhs); \
   return __ret; \
 }
 
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal)
-  _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(<=)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(==)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(!=)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>=)
+  _VARIANT_RELATION_FUNCTION_TEMPLATE(>)
 
 #undef _VARIANT_RELATION_FUNCTION_TEMPLATE


[gcc r15-284] libstdc++: Fix for -std=c++23 -ffreestanding [PR114866]

2024-05-07 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:9927059bb88e966e0a45f09e4fd1193f93df708f

commit r15-284-g9927059bb88e966e0a45f09e4fd1193f93df708f
Author: Jonathan Wakely 
Date:   Thu May 2 12:14:52 2024 +0100

libstdc++: Fix  for -std=c++23 -ffreestanding [PR114866]

std::shared_ptr isn't declared for freestanding, so guard uses of it
with #if _GLIBCXX_HOSTED in .

libstdc++-v3/ChangeLog:

PR libstdc++/114866
* include/bits/out_ptr.h [!_GLIBCXX_HOSTED]: Don't refer to
shared_ptr, __shared_ptr or __is_shred_ptr.
* testsuite/20_util/headers/memory/114866.cc: New test.

Diff:
---
 libstdc++-v3/include/bits/out_ptr.h | 10 ++
 libstdc++-v3/testsuite/20_util/headers/memory/114866.cc |  4 
 2 files changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/bits/out_ptr.h 
b/libstdc++-v3/include/bits/out_ptr.h
index aeeb6640441..d74c9f52d3b 100644
--- a/libstdc++-v3/include/bits/out_ptr.h
+++ b/libstdc++-v3/include/bits/out_ptr.h
@@ -54,9 +54,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 class out_ptr_t
 {
+#if _GLIBCXX_HOSTED
   static_assert(!__is_shared_ptr<_Smart> || sizeof...(_Args) != 0,
"a deleter must be used when adapting std::shared_ptr "
"with std::out_ptr");
+#endif
 
 public:
   explicit
@@ -216,6 +218,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  [[no_unique_address]] _Del2 _M_del;
};
 
+#if _GLIBCXX_HOSTED
   // Partial specialization for std::shared_ptr.
   // This specialization gives direct access to the private member
   // of the shared_ptr, avoiding the overhead of storing a separate
@@ -274,6 +277,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
  using _Impl<_Smart, _Pointer, _Del, allocator>::_Impl;
};
+#endif
 
   using _Impl_t = _Impl<_Smart, _Pointer, _Args...>;
 
@@ -293,8 +297,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 class inout_ptr_t
 {
+#if _GLIBCXX_HOSTED
   static_assert(!__is_shared_ptr<_Smart>,
"std::inout_ptr can not be used to wrap std::shared_ptr");
+#endif
 
 public:
   explicit
@@ -320,11 +326,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 
 private:
+#if _GLIBCXX_HOSTED
   // Avoid an invalid instantiation of out_ptr_t, ...>
   using _Out_ptr_t
= __conditional_t<__is_shared_ptr<_Smart>,
  out_ptr_t,
  out_ptr_t<_Smart, _Pointer, _Args...>>;
+#else
+  using _Out_ptr_t = out_ptr_t<_Smart, _Pointer, _Args...>;
+#endif
   using _Impl_t = typename _Out_ptr_t::_Impl_t;
   _Impl_t _M_impl;
 };
diff --git a/libstdc++-v3/testsuite/20_util/headers/memory/114866.cc 
b/libstdc++-v3/testsuite/20_util/headers/memory/114866.cc
new file mode 100644
index 000..7cf6be0539d
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/headers/memory/114866.cc
@@ -0,0 +1,4 @@
+// { dg-options "-ffreestanding" }
+// { dg-do compile }
+// PR libstdc++/114866  & out_ptr in freestanding
+#include 


[gcc r15-285] libstdc++: Fix handling of incomplete UTF-8 sequences in _Unicode_view

2024-05-07 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:3f04f3939ea0ac8fdd766a60655d29de2ffb44e5

commit r15-285-g3f04f3939ea0ac8fdd766a60655d29de2ffb44e5
Author: Jonathan Wakely 
Date:   Wed May 1 17:09:39 2024 +0100

libstdc++: Fix handling of incomplete UTF-8 sequences in _Unicode_view

Eddie Nolan reported to me that _Unicode_view was not correctly
implementing the substitution of ill-formed subsequences with U+FFFD,
due to failing to increment the counter when the iterator reaches the
end of the sequence before a multibyte sequence is complete.  As a
result, the incomplete sequence was not completely consumed, and then
the remaining character was treated as another ill-formed sequence,
giving two U+FFFD characters instead of one.

To avoid similar mistakes in future, this change introduces a lambda
that increments the iterator and the counter together. This ensures the
counter is always incremented when the iterator is incremented, so that
we always know how many characters have been consumed.

libstdc++-v3/ChangeLog:

* include/bits/unicode.h (_Unicode_view::_M_read_utf8): Ensure
count of characters consumed is correct when the end of the
input is reached unexpectedly.
* testsuite/ext/unicode/view.cc: Test incomplete UTF-8
sequences.

Diff:
---
 libstdc++-v3/include/bits/unicode.h| 24 +++-
 libstdc++-v3/testsuite/ext/unicode/view.cc |  7 +++
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/bits/unicode.h 
b/libstdc++-v3/include/bits/unicode.h
index 29813b743dc..46238143fb6 100644
--- a/libstdc++-v3/include/bits/unicode.h
+++ b/libstdc++-v3/include/bits/unicode.h
@@ -261,9 +261,13 @@ namespace __unicode
   {
_Guard<_Iter> __g{this, _M_curr()};
char32_t __c{};
-   uint8_t __u = *_M_curr()++;
const uint8_t __lo_bound = 0x80, __hi_bound = 0xBF;
+   uint8_t __u = *_M_curr()++;
uint8_t __to_incr = 1;
+   auto __incr = [&, this] {
+ ++__to_incr;
+ return ++_M_curr();
+   };
 
if (__u <= 0x7F) [[likely]]  // 0x00 to 0x7F
  __c = __u;
@@ -281,8 +285,7 @@ namespace __unicode
else
  {
__c = (__c << 6) | (__u & 0x3F);
-   ++_M_curr();
-   ++__to_incr;
+   __incr();
  }
  }
else if (__u <= 0xEF) // 0xE0 to 0xEF
@@ -295,11 +298,10 @@ namespace __unicode
 
if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]]
  __c = _S_error();
-   else if (++_M_curr() == _M_last) [[unlikely]]
+   else if (__incr() == _M_last) [[unlikely]]
  __c = _S_error();
else
  {
-   ++__to_incr;
__c = (__c << 6) | (__u & 0x3F);
__u = *_M_curr();
 
@@ -308,8 +310,7 @@ namespace __unicode
else
  {
__c = (__c << 6) | (__u & 0x3F);
-   ++_M_curr();
-   ++__to_incr;
+   __incr();
  }
  }
  }
@@ -323,21 +324,19 @@ namespace __unicode
 
if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]]
  __c = _S_error();
-   else if (++_M_curr() == _M_last) [[unlikely]]
+   else if (__incr() == _M_last) [[unlikely]]
  __c = _S_error();
else
  {
-   ++__to_incr;
__c = (__c << 6) | (__u & 0x3F);
__u = *_M_curr();
 
if (__u < __lo_bound || __u > __hi_bound) [[unlikely]]
  __c = _S_error();
-   else if (++_M_curr() == _M_last) [[unlikely]]
+   else if (__incr() == _M_last) [[unlikely]]
  __c = _S_error();
else
  {
-   ++__to_incr;
__c = (__c << 6) | (__u & 0x3F);
__u = *_M_curr();
 
@@ -346,8 +345,7 @@ namespace __unicode
else
  {
__c = (__c << 6) | (__u & 0x3F);
-   ++_M_curr();
-   ++__to_incr;
+   __incr();
  }
  }
  }
diff --git a/libstdc++-v3/testsuite/ext/unicode/view.cc 
b/libstdc++-v3/testsuite/ext/unicode/view.cc
index ee23b0b1d8a..6f3c099bd84 100644
--- a/libstdc++-v3/testsuite/ext/unicode/view.cc
+++ b/libstdc++-v3/testsuite/ext/unicode/view.cc
@@ -55,6 +55,13 @@ test_illformed_utf8()
   VERIFY( std::ranges::equal(v5, 
u8"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41\uFFFD\uFFFD\x42"sv) );
   uc::_Utf8_view v6("\xe1\x80\xe2\xf0\x91\x92\xf1\xbf\x41"sv); // Table 3-11
   VERIFY( std::ranges::equal(v6, u8"\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv) );
+
+  uc::_Utf32_view v7("\xe1\x80"sv);
+  VERIFY( std::ranges::equal(v7, U

[gcc r15-286] AVR: target/114835 - Tweak popcountqi2

2024-05-07 Thread Georg-Johann Lay via Gcc-cvs
https://gcc.gnu.org/g:8d2c93fcfe1afc5291bbbe162c3b7ad5764f6d8d

commit r15-286-g8d2c93fcfe1afc5291bbbe162c3b7ad5764f6d8d
Author: Wolfgang Hospital 
Date:   Tue May 7 16:24:39 2024 +0200

AVR: target/114835 - Tweak popcountqi2

libgcc/
PR target/114835
* config/avr/lib1funcs.S (__popcountqi2): Use code that
is one instruction shorter / faster.

Diff:
---
 libgcc/config/avr/lib1funcs.S | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index af4d7d97016..4ac31fa104e 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -3050,21 +3050,21 @@ ENDF __popcountdi2
 ;; r24 = popcount8 (r24)
 ;; clobbers: __tmp_reg__
 DEFUN __popcountqi2
-mov  __tmp_reg__, r24
-andi r24, 1
-lsr  __tmp_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __zero_reg__
-lsr  __tmp_reg__
-adc  r24, __tmp_reg__
+mov  __tmp_reg__, r24; oeoeoeoe
+andi r24, 0xAA   ; o0o0o0o0
+lsr  r24 ; 0o0o0o0o
+;; Four values 0, 1 or 2: # bits set o+e
+sub  __tmp_reg__, r24; 44332211
+mov  r24, __tmp_reg__; 44332211
+andi r24, 0x33   ; 00330011
+eor  __tmp_reg__, r24; 44002200
+lsr  __tmp_reg__ ; 04400220
+lsr  __tmp_reg__ ; 00440022
+add  r24, __tmp_reg__; 04210421
+mov  __tmp_reg__, r24; h421l421
+swap __tmp_reg__ ; l421h421
+add  r24, __tmp_reg__; 84218421
+andi r24, 0xf; 8421 /17
 ret
 ENDF __popcountqi2
 #endif /* defined (L_popcountqi2) */


[gcc r14-10176] c++/modules: imported spec befriending class tmpl [PR114889]

2024-05-07 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:390bd23fd9c98dc40856beef05364f5d1c7b9d04

commit r14-10176-g390bd23fd9c98dc40856beef05364f5d1c7b9d04
Author: Patrick Palka 
Date:   Mon Apr 29 21:27:59 2024 -0400

c++/modules: imported spec befriending class tmpl [PR114889]

When adding to CLASSTYPE_BEFRIENDING_CLASSES as part of installing an
imported class definition, we need to look through TEMPLATE_DECL like
make_friend_class does.

Otherwise in the below testcase we won't add _Hashtable to
CLASSTYPE_BEFRIENDING_CLASSES of _Map_base, which leads to a bogus
access check failure for _M_hash_code.

PR c++/114889

gcc/cp/ChangeLog:

* module.cc (trees_in::read_class_def): Look through
TEMPLATE_DECL when adding to CLASSTYPE_BEFRIENDING_CLASSES.

gcc/testsuite/ChangeLog:

* g++.dg/modules/friend-8_a.H: New test.
* g++.dg/modules/friend-8_b.C: New test.

Reviewed-by: Jason Merrill 
(cherry picked from commit 22b20ac6c6aead2d3f36c413a77dd0b80adfec39)

Diff:
---
 gcc/cp/module.cc  |  2 ++
 gcc/testsuite/g++.dg/modules/friend-8_a.H | 23 +++
 gcc/testsuite/g++.dg/modules/friend-8_b.C |  9 +
 3 files changed, 34 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c35e70b8cb8..3bf863e15d4 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12498,6 +12498,8 @@ trees_in::read_class_def (tree defn, tree 
maybe_template)
  for (; friend_classes; friend_classes = TREE_CHAIN (friend_classes))
{
  tree f = TREE_VALUE (friend_classes);
+ if (TREE_CODE (f) == TEMPLATE_DECL)
+   f = TREE_TYPE (f);
 
  if (CLASS_TYPE_P (f))
{
diff --git a/gcc/testsuite/g++.dg/modules/friend-8_a.H 
b/gcc/testsuite/g++.dg/modules/friend-8_a.H
new file mode 100644
index 000..b07ea25adfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-8_a.H
@@ -0,0 +1,23 @@
+// PR c++/114889
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template
+struct _Hashtable;
+
+template
+struct _Map_base {
+  void f() {
+_Hashtable<_Key, _Val> __h;
+__h._M_hash_code(0);
+  }
+};
+
+template
+struct _Hashtable {
+  template friend struct _Map_base;
+protected:
+  void _M_hash_code(int);
+};
+
+inline _Hashtable m;
diff --git a/gcc/testsuite/g++.dg/modules/friend-8_b.C 
b/gcc/testsuite/g++.dg/modules/friend-8_b.C
new file mode 100644
index 000..b04280bc91a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-8_b.C
@@ -0,0 +1,9 @@
+// PR c++/114889
+// { dg-additional-options "-fmodules-ts" }
+
+import "friend-8_a.H";
+
+int main() {
+  _Map_base m;
+  m.f();
+}


[gcc/devel/rust/master] Rust: Make 'tree'-level 'MAIN_NAME_P' work

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:41c7e1d0a707f97327f097022e9e6fa7f6f13533

commit 41c7e1d0a707f97327f097022e9e6fa7f6f13533
Author: Thomas Schwinge 
Date:   Wed Apr 12 11:38:58 2023 +0200

Rust: Make 'tree'-level 'MAIN_NAME_P' work

'gcc/tree.h':

#define main_identifier_node
global_trees[TI_MAIN_IDENTIFIER]
#define MAIN_NAME_P(NODE) \
  (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node)

..., which is not initialized by default, but has to be set up by every 
front
end individually.  'MAIN_NAME_P' enables certain code optimizations, but is
especially also relevant for back ends that emit additional program entry 
setup
code for 'main'.

gcc/rust/
* backend/rust-compile-base.cc (HIRCompileBase::compile_function):
Handle 'main' specially.
* rust-lang.cc (grs_langhook_init): Initialize
'main_identifier_node'.

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 3 +++
 gcc/rust/rust-lang.cc | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 9650d1a47ee6..9b8a793a3c73 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -523,6 +523,9 @@ HIRCompileBase::compile_function (
 
   // we don't mangle the main fn since we haven't implemented the main shim
   bool is_main_fn = fn_name.compare ("main") == 0;
+  if (is_main_fn)
+/* So that 'MAIN_NAME_P' works.  */
+ir_symbol_name = fn_name;
   std::string asm_name = fn_name;
 
   unsigned int flags = 0;
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index f3532298aecc..9f1a914ed73f 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -38,6 +38,7 @@
 #include "rust-privacy-ctx.h"
 #include "rust-ast-resolve-item.h"
 #include "rust-optional.h"
+#include "stringpool.h"
 
 #include 
 // note: header files must be in this order or else forward declarations don't
@@ -124,6 +125,8 @@ grs_langhook_init (void)
whether char is signed.  */
   build_common_tree_nodes (false);
 
+  main_identifier_node = get_identifier ("main");
+
   // Builds built-ins for middle-end after all front-end built-ins are already
   // instantiated
   build_common_builtin_nodes ();


[gcc/devel/rust/master] Revert "Rust: Make 'tree'-level 'MAIN_NAME_P' work"

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:4e95a9117487c07f876f913499cb9954b6cd7d54

commit 4e95a9117487c07f876f913499cb9954b6cd7d54
Author: Thomas Schwinge 
Date:   Fri Apr 14 11:57:21 2023 +0200

Revert "Rust: Make 'tree'-level 'MAIN_NAME_P' work"

This reverts commit 41c7e1d0a707f97327f097022e9e6fa7f6f13533.

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 3 ---
 gcc/rust/rust-lang.cc | 3 ---
 2 files changed, 6 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 9b8a793a3c73..9650d1a47ee6 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -523,9 +523,6 @@ HIRCompileBase::compile_function (
 
   // we don't mangle the main fn since we haven't implemented the main shim
   bool is_main_fn = fn_name.compare ("main") == 0;
-  if (is_main_fn)
-/* So that 'MAIN_NAME_P' works.  */
-ir_symbol_name = fn_name;
   std::string asm_name = fn_name;
 
   unsigned int flags = 0;
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index 9f1a914ed73f..f3532298aecc 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -38,7 +38,6 @@
 #include "rust-privacy-ctx.h"
 #include "rust-ast-resolve-item.h"
 #include "rust-optional.h"
-#include "stringpool.h"
 
 #include 
 // note: header files must be in this order or else forward declarations don't
@@ -125,8 +124,6 @@ grs_langhook_init (void)
whether char is signed.  */
   build_common_tree_nodes (false);
 
-  main_identifier_node = get_identifier ("main");
-
   // Builds built-ins for middle-end after all front-end built-ins are already
   // instantiated
   build_common_builtin_nodes ();


[gcc/devel/rust/master] Rust: Make 'tree'-level 'MAIN_NAME_P' work

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:705de6d54ca95b8277a15fe9a2255af6168ae086

commit 705de6d54ca95b8277a15fe9a2255af6168ae086
Author: Thomas Schwinge 
Date:   Wed Apr 12 11:47:01 2023 +0200

Rust: Make 'tree'-level 'MAIN_NAME_P' work

'gcc/tree.h':

#define main_identifier_node
global_trees[TI_MAIN_IDENTIFIER]
#define MAIN_NAME_P(NODE) \
  (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node)

..., which is not initialized by default, but has to be set up by every 
front
end individually.  'MAIN_NAME_P' enables certain code optimizations, but is
especially also relevant for back ends that emit additional program entry 
setup
code for 'main'.

gcc/rust/
* backend/rust-compile-base.cc (HIRCompileBase::compile_function):
For 'main', initialize 'main_identifier_node'.

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 9650d1a47ee6..19bf24237724 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -523,6 +523,12 @@ HIRCompileBase::compile_function (
 
   // we don't mangle the main fn since we haven't implemented the main shim
   bool is_main_fn = fn_name.compare ("main") == 0;
+  if (is_main_fn)
+{
+  rust_assert (!main_identifier_node);
+  /* So that 'MAIN_NAME_P' works.  */
+  main_identifier_node = get_identifier (ir_symbol_name.c_str ());
+}
   std::string asm_name = fn_name;
 
   unsigned int flags = 0;


[gcc/devel/rust/master] borrowck: Add initial structure for borrowchecking

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:2bb559cea908d08eb6bc9faae4567de0ebfdccd6

commit 2bb559cea908d08eb6bc9faae4567de0ebfdccd6
Author: Jakub Dupak 
Date:   Wed Oct 18 19:09:34 2023 +0200

borrowck: Add initial structure for borrowchecking

gcc/rust/ChangeLog:

* Make-lang.in: Build borrowck.
* checks/errors/borrowck/rust-borrow-checker.cc: New file.
* checks/errors/borrowck/rust-borrow-checker.h: New file.
* checks/errors/borrowck/rust-function-collector.h: New file.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/Make-lang.in  |   7 +
 .../checks/errors/borrowck/rust-borrow-checker.cc  |  43 +
 .../checks/errors/borrowck/rust-borrow-checker.h   |  39 
 .../errors/borrowck/rust-function-collector.h  | 199 +
 4 files changed, 288 insertions(+)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index e6a2099f043c..f4b9eb5502e2 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -148,6 +148,7 @@ GRS_OBJS = \
 rust/rust-hir-type-check-stmt.o \
 rust/rust-hir-type-check-enumitem.o \
 rust/rust-hir-type-check-implitem.o \
+rust/rust-borrow-checker.o \
 rust/rust-hir-dot-operator.o \
 rust/rust-hir-path-probe.o \
 rust/rust-type-util.o \
@@ -371,6 +372,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \
-I $(srcdir)/rust/checks/lints \
-I $(srcdir)/rust/checks/errors \
-I $(srcdir)/rust/checks/errors/privacy \
+   -I $(srcdir)/rust/checks/errors/borrowck \
-I $(srcdir)/rust/util \
 -I $(srcdir)/rust/metadata \
-I $(srcdir)/../libgrust
@@ -448,6 +450,11 @@ rust/%.o: rust/checks/errors/privacy/%.cc
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
$(POSTCOMPILE)
 
+# build borrow checking pass files in rust folder
+rust/%.o: rust/checks/errors/borrowck/%.cc
+   $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
+   $(POSTCOMPILE)
+
 # build rust/metadata files in rust folder
 rust/%.o: rust/metadata/%.cc
$(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $<
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc 
b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
new file mode 100644
index ..a6086b8a6956
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
@@ -0,0 +1,43 @@
+// Copyright (C) 2020-2023 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-borrow-checker.h"
+#include "rust-function-collector.h"
+
+namespace Rust {
+namespace HIR {
+
+BorrowChecker::BorrowChecker () = default;
+
+void
+BorrowChecker::go (HIR::Crate &crate)
+{
+  FunctionCollector collector;
+  collector.go (crate);
+
+  for (auto func ATTRIBUTE_UNUSED : collector.get_functions ())
+{
+}
+
+  for (auto closure ATTRIBUTE_UNUSED : collector.get_closures ())
+{
+}
+}
+
+} // namespace HIR
+} // namespace Rust
\ No newline at end of file
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h 
b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
new file mode 100644
index ..7df5fe788a0b
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#ifndef RUST_HIR_BORROW_CHECK_H
+#define RUST_HIR_BORROW_CHECK_H
+
+#include "rust-hir.h"
+
+namespace Rust {
+namespace HIR {
+
+class BorrowChecker
+{
+public:
+  BorrowChecker ();
+
+  /** Perform borrow-checking using polonius on an entire crate */
+  void go (HIR::Crate &crate);
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_HIR_BORROW_CHECK_H
d

[gcc/devel/rust/master] borrowck: Execute only with CLI flag

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:dd23e4f8b9c63974a589557791ec50c18e5e72d3

commit dd23e4f8b9c63974a589557791ec50c18e5e72d3
Author: Jakub Dupak 
Date:   Thu Oct 19 11:37:41 2023 +0200

borrowck: Execute only with CLI flag

gcc/rust/ChangeLog:

* lang.opt: CLI flag.
* rust-session-manager.cc (Session::compile_crate): Guard execution.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/lang.opt| 4 
 gcc/rust/rust-session-manager.cc | 9 ++---
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
index 67285a6d92b2..83db5ec1711d 100644
--- a/gcc/rust/lang.opt
+++ b/gcc/rust/lang.opt
@@ -202,4 +202,8 @@ frust-name-resolution-2.0
 Rust Var(flag_name_resolution_2_0)
 Use the temporary and experimental name resolution pipeline instead of the 
stable one
 
+frust-borrowcheck
+Rust Var(flag_borrowcheck)
+Use the WIP borrow checker.
+
 ; This comment is to ensure we retain the blank line above.
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 2843b7d25cf2..96d5f4729165 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -667,9 +667,12 @@ Session::compile_crate (const char *filename)
   if (last_step == CompileOptions::CompileStep::BorrowCheck)
 return;
 
-  const bool dump_bir
-= options.dump_option_enabled (CompileOptions::DumpOption::BIR_DUMP);
-  HIR::BorrowChecker (dump_bir).go (hir);
+  if (flag_borrowcheck)
+{
+  const bool dump_bir
+   = options.dump_option_enabled (CompileOptions::DumpOption::BIR_DUMP);
+  HIR::BorrowChecker (dump_bir).go (hir);
+}
 
   if (saw_errors ())
 return;


[gcc/devel/rust/master] borrowck: Dump: proper comma separation

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:8eb8474add2999de3476a8172c9418b46b99b9b3

commit 8eb8474add2999de3476a8172c9418b46b99b9b3
Author: Jakub Dupak 
Date:   Wed Oct 18 22:38:30 2023 +0200

borrowck: Dump: proper comma separation

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-dump.cc (Dump::go): Use new print.
(print_comma_separated): Comma separation print.
(Dump::visit): Use new print.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/checks/errors/borrowck/rust-bir-dump.cc | 34 +---
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
index cebed2485a31..4571b2fe8577 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -28,15 +28,31 @@ get_tyty_name (TyTy::BaseType *tyty)
   return "unknown";
 }
 
+template 
 void
-Dump::go ()
+print_comma_separated (std::ostream &stream, const std::vector &collection,
+  FN printer)
 {
-  stream << "fn " << name << "(";
-  for (PlaceId arg : func.arguments)
+  if (collection.empty ())
+return;
+  printer (collection[0]);
+  for (auto it = collection.begin () + 1; it != collection.end (); ++it)
 {
-  stream << "_" << get_place_name (arg) << ": "
-<< get_tyty_name (place_db[arg].tyty) << ", ";
+  stream << ", ";
+  printer (*it);
 }
+}
+
+static constexpr bool FOLD_CFG = true;
+
+void
+Dump::go ()
+{
+  stream << "fn " << name << "(";
+  print_comma_separated (stream, func.arguments, [this] (PlaceId place_id) {
+stream << "_" << get_place_name (place_id) << ": "
+  << get_tyty_name (place_db[place_id].tyty);
+  });
   stream << ") -> " << get_tyty_name (place_db[RETURN_VALUE_PLACE].tyty)
 << " {\n";
 
@@ -182,11 +198,9 @@ void
 Dump::visit (InitializerExpr &expr)
 {
   stream << "{";
-  for (auto &place : expr.get_values ())
-{
-  visit_move_place (place);
-  stream << ", ";
-}
+  print_comma_separated (stream, expr.get_values (), [this] (PlaceId place_id) 
{
+visit_move_place (place_id);
+  });
   stream << "}";
 }


[gcc/devel/rust/master] borrowck: Create BIR builders (visitors)

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:9a45588f39d9710f2d7b5dec2e75d00531e7436d

commit 9a45588f39d9710f2d7b5dec2e75d00531e7436d
Author: Jakub Dupak 
Date:   Wed Oct 18 20:43:17 2023 +0200

borrowck: Create BIR builders (visitors)

gcc/rust/ChangeLog:

* Make-lang.in: Compile BIR expr visitor.
* checks/errors/borrowck/rust-borrow-checker.cc 
(BorrowChecker::go): Use BIR builder.
* rust-session-manager.cc (Session::compile_crate): Run borrow 
checker.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc: New file.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.h: New file.
* checks/errors/borrowck/rust-bir-builder-internal.h: New file.
* checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: New file.
* checks/errors/borrowck/rust-bir-builder-pattern.h: New file.
* checks/errors/borrowck/rust-bir-builder-struct.h: New file.
* checks/errors/borrowck/rust-bir-builder.h: New file.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/Make-lang.in  |   1 +
 .../errors/borrowck/rust-bir-builder-expr-stmt.cc  | 578 +
 .../errors/borrowck/rust-bir-builder-expr-stmt.h   | 150 ++
 .../errors/borrowck/rust-bir-builder-internal.h| 416 +++
 .../borrowck/rust-bir-builder-lazyboolexpr.h   | 243 +
 .../errors/borrowck/rust-bir-builder-pattern.h | 290 +++
 .../errors/borrowck/rust-bir-builder-struct.h  | 270 ++
 gcc/rust/checks/errors/borrowck/rust-bir-builder.h |  88 
 .../checks/errors/borrowck/rust-borrow-checker.cc  |   8 +-
 gcc/rust/rust-session-manager.cc   |   2 +-
 10 files changed, 2042 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index f4b9eb5502e2..1e462ef6a1bf 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -149,6 +149,7 @@ GRS_OBJS = \
 rust/rust-hir-type-check-enumitem.o \
 rust/rust-hir-type-check-implitem.o \
 rust/rust-borrow-checker.o \
+rust/rust-bir-builder-expr-stmt.o \
 rust/rust-hir-dot-operator.o \
 rust/rust-hir-path-probe.o \
 rust/rust-type-util.o \
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
new file mode 100644
index ..1487c853b49e
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -0,0 +1,578 @@
+// 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-bir-builder-expr-stmt.h"
+#include "rust-bir-builder-lazyboolexpr.h"
+#include "rust-bir-builder-pattern.h"
+#include "rust-bir-builder-struct.h"
+
+namespace Rust {
+namespace BIR {
+
+void
+ExprStmtBuilder::visit (HIR::ClosureExpr &expr)
+{
+  auto closure_ty = lookup_type (expr)->as ();
+  std::vector captures;
+  for (auto &capture : closure_ty->get_captures ())
+{
+  captures.push_back (ctx.place_db.lookup_variable (capture));
+}
+
+  // Not a coercion site.
+  return_expr (new InitializerExpr (std::move (captures)), lookup_type (expr));
+}
+
+void
+ExprStmtBuilder::visit (HIR::StructExprStructFields &fields)
+{
+  auto struct_ty
+= lookup_type (fields)->as ()->get_variants ().at (0);
+  auto init_values = StructBuilder (ctx, struct_ty).build (fields);
+  return_expr (new InitializerExpr (std::move (init_values)),
+  lookup_type (fields));
+}
+
+void
+ExprStmtBuilder::visit (HIR::StructExprStruct &expr)
+{
+  // There is no way to modify empty struct, which makes them constant.
+  return_place (ctx.place_db.get_constant (lookup_type (expr)));
+}
+
+void
+ExprStmtBuilder::visit (HIR::LiteralExpr &expr)
+{
+  // Different literal values of the same type are not distinguished.
+  return_place (ctx.place_db.get_constant (lookup_type (expr)));
+}
+
+void
+ExprStmtBuilder::visit (HIR::BorrowExpr &expr)
+{
+  auto operand = visit_expr (*expr.get_expr ());
+  return_expr (new BorrowExpr (operand), lookup_type (expr));
+}
+
+void
+ExprStmtBuilder::visit (HIR::DereferenceExpr &expr)
+{
+  auto operand = visit_expr (*expr.get_expr ());
+  return_place (operand);
+}
+
+void
+ExprStmtBuilder::visit (HIR::ErrorPropagationExpr &expr)
+{
+  rust_sorry_at (expr.get_loc

[gcc/devel/rust/master] borrowck: Dump: simplify cfg

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:c92e110f06c49931a169319e4fd679c8e76ffcde

commit c92e110f06c49931a169319e4fd679c8e76ffcde
Author: Jakub Dupak 
Date:   Wed Oct 18 22:50:02 2023 +0200

borrowck: Dump: simplify cfg

Add option to simplify cfg for better readability. Off by default.

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-dump.cc (simplify_cfg): Simplify 
cfg logic.
(Dump::go): Run simplify cfg.
* checks/errors/borrowck/rust-bir-dump.h: Option to simplify cfg.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/checks/errors/borrowck/rust-bir-dump.cc | 40 +---
 gcc/rust/checks/errors/borrowck/rust-bir-dump.h  |  7 +++--
 2 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
index 4571b2fe8577..709d36a7cd33 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -1,3 +1,4 @@
+#include 
 #include "rust-bir-dump.h"
 
 namespace Rust {
@@ -43,11 +44,39 @@ print_comma_separated (std::ostream &stream, const 
std::vector &collection,
 }
 }
 
-static constexpr bool FOLD_CFG = true;
+void
+simplify_cfg (Function &func, std::vector &bb_fold_map)
+{
+  // The BIR builder can generate many useless basic blocks, which contain only
+  // a goto.
+  // For actual borrow-checking, the folding has little value.
+
+  bool stabilized = false;
+  while (!stabilized)
+{
+  stabilized = true;
+  // BB0 cannot be folded as it is an entry block.
+  for (size_t i = 1; i < func.basic_blocks.size (); ++i)
+   {
+ const BasicBlock &bb = func.basic_blocks[bb_fold_map[i]];
+ if (bb.statements.empty () && bb.is_goto_terminated ())
+   {
+ bb_fold_map[i] = bb.successors.at (0);
+ stabilized = false;
+   }
+   }
+}
+}
 
 void
-Dump::go ()
+Dump::go (bool enable_simplify_cfg)
 {
+  // To avoid mutation of the BIR, we use indirection through bb_fold_map.
+  std::iota (bb_fold_map.begin (), bb_fold_map.end (), 0);
+
+  if (enable_simplify_cfg)
+simplify_cfg (func, bb_fold_map);
+
   stream << "fn " << name << "(";
   print_comma_separated (stream, func.arguments, [this] (PlaceId place_id) {
 stream << "_" << get_place_name (place_id) << ": "
@@ -71,13 +100,16 @@ Dump::go ()
 
   for (BasicBlockId id = 0; id < func.basic_blocks.size (); ++id)
 {
+  if (bb_fold_map[id] != id)
+   continue; // This BB was folded.
+
   if (func.basic_blocks[id].statements.empty ()
  && func.basic_blocks[id].successors.empty ())
continue;
 
   BasicBlock &bb = func.basic_blocks[id];
   stream << "\n";
-  stream << indentation << "bb" << id << ": {\n";
+  stream << indentation << "bb" << bb_fold_map[id] << ": {\n";
   for (auto &stmt : bb.statements)
{
  stream << indentation << indentation;
@@ -86,7 +118,7 @@ Dump::go ()
}
   stream << indentation << "} -> [";
   for (auto succ : bb.successors)
-   stream << "bb" << succ << ", ";
+   stream << "bb" << bb_fold_map[succ] << ", ";
   stream << "]\n";
 }
 
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-dump.h
index 7c24749fed55..1f8de045c22c 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.h
@@ -35,13 +35,16 @@ class Dump : public Visitor
   Function &func;
   const std::string &name;
 
+  std::vector bb_fold_map;
+
   PlaceId node_place = INVALID_PLACE;
 
 public:
   Dump (std::ostream &os, Function &func, const std::string &name)
-: stream (os), place_db (func.place_db), func (func), name (name)
+: stream (os), place_db (func.place_db), func (func), name (name),
+  bb_fold_map (func.basic_blocks.size ())
   {}
-  void go ();
+  void go (bool enable_simplify_cfg = false);
 
 protected:
   void visit (Node &node) override;


[gcc/devel/rust/master] borrowck: Dump improve jumps

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:97a0d40594a9e5c6c6b18a6548ecbfa22f181e5f

commit 97a0d40594a9e5c6c6b18a6548ecbfa22f181e5f
Author: Jakub Dupak 
Date:   Wed Oct 18 23:27:48 2023 +0200

borrowck: Dump improve jumps

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-dump.cc (Dump::go): Improve jumps 
dump.
(Dump::visit): Improve jumps dump.
* checks/errors/borrowck/rust-bir-dump.h (class Dump): Improve 
jumps dump.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/checks/errors/borrowck/rust-bir-dump.cc | 77 
 gcc/rust/checks/errors/borrowck/rust-bir-dump.h  |  4 +-
 2 files changed, 56 insertions(+), 25 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
index 709d36a7cd33..ba530983dade 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -6,13 +6,6 @@ namespace BIR {
 
 constexpr auto indentation = "";
 
-uint32_t
-get_place_name (PlaceId place_id)
-{
-  rust_assert (place_id >= FIRST_VARIABLE_PLACE);
-  return place_id - FIRST_VARIABLE_PLACE;
-}
-
 uint32_t
 get_lifetime_name (Lifetime lifetime_id)
 {
@@ -44,6 +37,28 @@ print_comma_separated (std::ostream &stream, const 
std::vector &collection,
 }
 }
 
+void
+renumber_places (const Function &func, std::vector &place_map)
+{
+  // Renumbering places to avoid gaps in the place id space.
+  // This is needed to match MIR shape.
+  size_t next_out_id = 0;
+
+  for (size_t in_id = FIRST_VARIABLE_PLACE; in_id < func.place_db.size ();
+   ++in_id)
+{
+  const Place &place = func.place_db[in_id];
+  if (place.kind == Place::VARIABLE || place.kind == Place::TEMPORARY)
+   {
+ place_map[in_id] = next_out_id++;
+   }
+  else
+   {
+ place_map[in_id] = INVALID_PLACE;
+   }
+}
+}
+
 void
 simplify_cfg (Function &func, std::vector &bb_fold_map)
 {
@@ -74,12 +89,16 @@ Dump::go (bool enable_simplify_cfg)
   // To avoid mutation of the BIR, we use indirection through bb_fold_map.
   std::iota (bb_fold_map.begin (), bb_fold_map.end (), 0);
 
+  std::iota (place_map.begin (), place_map.end (), 0);
+
   if (enable_simplify_cfg)
 simplify_cfg (func, bb_fold_map);
 
+  renumber_places (func, place_map);
+
   stream << "fn " << name << "(";
   print_comma_separated (stream, func.arguments, [this] (PlaceId place_id) {
-stream << "_" << get_place_name (place_id) << ": "
+stream << "_" << place_map[place_id] << ": "
   << get_tyty_name (place_db[place_id].tyty);
   });
   stream << ") -> " << get_tyty_name (place_db[RETURN_VALUE_PLACE].tyty)
@@ -93,33 +112,30 @@ Dump::go (bool enable_simplify_cfg)
  if (std::find (func.arguments.begin (), func.arguments.end (), id)
  != func.arguments.end ())
continue;
- stream << indentation << "let _" << get_place_name (id) << ": "
+ stream << indentation << "let _" << place_map[id] << ": "
 << get_tyty_name (place_db[id].tyty) << ";\n";
}
 }
 
-  for (BasicBlockId id = 0; id < func.basic_blocks.size (); ++id)
+  for (node_bb = 0; node_bb < func.basic_blocks.size (); ++node_bb)
 {
-  if (bb_fold_map[id] != id)
+  if (bb_fold_map[node_bb] != node_bb)
continue; // This BB was folded.
 
-  if (func.basic_blocks[id].statements.empty ()
- && func.basic_blocks[id].successors.empty ())
+  if (func.basic_blocks[node_bb].statements.empty ()
+ && func.basic_blocks[node_bb].successors.empty ())
continue;
 
-  BasicBlock &bb = func.basic_blocks[id];
+  BasicBlock &bb = func.basic_blocks[node_bb];
   stream << "\n";
-  stream << indentation << "bb" << bb_fold_map[id] << ": {\n";
+  stream << indentation << "bb" << bb_fold_map[node_bb] << ": {\n";
   for (auto &stmt : bb.statements)
{
  stream << indentation << indentation;
  visit (stmt);
  stream << ";\n";
}
-  stream << indentation << "} -> [";
-  for (auto succ : bb.successors)
-   stream << "bb" << bb_fold_map[succ] << ", ";
-  stream << "]\n";
+  stream << indentation << "}\n";
 }
 
   stream << "}\n\n";
@@ -131,19 +147,26 @@ Dump::visit (Node &node)
   switch (node.get_kind ())
 {
   case Node::Kind::ASSIGNMENT: {
-   stream << "_" << get_place_name (node.get_place ()) << " = ";
+   stream << "_" << place_map[node.get_place ()] << " = ";
node.get_expr ().accept_vis (*this);
break;
   }
 case Node::Kind::SWITCH:
-  stream << "switch ";
+  stream << "switchInt(";
   visit_move_place (node.get_place ());
+  stream << ") -> [";
+  print_comma_separated (stream, func.basic_blocks[node_bb].successors,
+[this] (BasicBlockId succ) {
+  stream << "bb" << bb_fold_map[succ];
+

[gcc/devel/rust/master] borrowck: BIR: handle break

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:85f924f470682b5c71b8bf501e6a143701303a93

commit 85f924f470682b5c71b8bf501e6a143701303a93
Author: Jakub Dupak 
Date:   Wed Oct 18 22:54:37 2023 +0200

borrowck: BIR: handle break

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
(ExprStmtBuilder::visit): Push ctx.
(ExprStmtBuilder::setup_loop): Common loop infractructure setup.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Loop ctx.
* checks/errors/borrowck/rust-bir-builder-internal.h (struct 
BuilderContext): Loop ctx.

Signed-off-by: Jakub Dupak 

Diff:
---
 .../errors/borrowck/rust-bir-builder-expr-stmt.cc  | 168 +++--
 .../errors/borrowck/rust-bir-builder-expr-stmt.h   |   2 +
 .../errors/borrowck/rust-bir-builder-internal.h|  66 +---
 3 files changed, 168 insertions(+), 68 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index 1487c853b49e..67b98e2254f9 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -258,11 +258,45 @@ ExprStmtBuilder::visit (HIR::FieldAccessExpr &expr)
 void
 ExprStmtBuilder::visit (HIR::BlockExpr &block)
 {
+  BasicBlockId end_bb;
+
+  if (block.has_label ())
+{
+  end_bb = new_bb ();
+  NodeId label
+   = block.get_label ().get_lifetime ().get_mappings ().get_nodeid ();
+  PlaceId label_var = ctx.place_db.add_temporary (lookup_type (block));
+  ctx.loop_and_label_stack.push_back ({false, label, label_var, end_bb, 
0});
+}
+
+  bool unreachable = false;
   for (auto &stmt : block.get_statements ())
 {
+  if (unreachable)
+   break;
   stmt->accept_vis (*this);
+  if (ctx.get_current_bb ().is_terminated ())
+   unreachable = true;
+}
+
+  if (block.has_label ())
+{
+  auto label_info = ctx.loop_and_label_stack.back ();
+  if (block.has_expr () && !unreachable)
+   {
+ push_assignment (label_info.label_var,
+  visit_expr (*block.get_final_expr ()));
+   }
+  if (!ctx.get_current_bb ().is_terminated ())
+   {
+ add_jump_to (end_bb);
+   }
+  ctx.current_bb = end_bb;
+  ctx.loop_and_label_stack.pop_back ();
+
+  return_place (label_info.label_var);
 }
-  if (block.has_expr ())
+  else if (block.has_expr () && !unreachable)
 {
   return_place (visit_expr (*block.get_final_expr ()));
 }
@@ -290,25 +324,36 @@ ExprStmtBuilder::visit (HIR::ContinueExpr &cont)
 void
 ExprStmtBuilder::visit (HIR::BreakExpr &brk)
 {
-  //  BuilderContext::LabelledBlockCtx block_ctx{};
-  //  NodeId label = UNKNOWN_NODEID;
-  //  if (brk.has_label ())
-  //{
-  //  if (!resolve_label (brk.get_label (), label))
-  //   return;
-  //}
-  //  if (!find_block_ctx (label, block_ctx))
-  //{
-  //  rust_error_at (brk.get_locus (), "unresolved labelled block");
-  //}
-  //
-  //  if (brk.has_break_expr ())
-  //{
-  //  brk.get_expr ()->accept_vis (*this);
-  //  push_assignment (block_ctx.label_var, new Operator<1> 
({translated}));
-  //}
-  //
-  //  add_jump_to (block_ctx.break_bb);
+  BuilderContext::LoopAndLabelInfo info;
+  if (brk.has_label ())
+{
+  NodeId label = resolve_label (brk.get_label ());
+  auto lookup
+   = std::find_if (ctx.loop_and_label_stack.rbegin (),
+   ctx.loop_and_label_stack.rend (),
+   [label] (const BuilderContext::LoopAndLabelInfo &info) {
+ return info.label == label;
+   });
+  rust_assert (lookup != ctx.loop_and_label_stack.rend ());
+  info = *lookup;
+}
+  else
+{
+  auto lookup
+   = std::find_if (ctx.loop_and_label_stack.rbegin (),
+   ctx.loop_and_label_stack.rend (),
+   [] (const BuilderContext::LoopAndLabelInfo &info) {
+ return info.is_loop;
+   });
+  rust_assert (lookup != ctx.loop_and_label_stack.rend ());
+  info = *lookup;
+}
+  if (brk.has_break_expr ())
+{
+  push_assignment (info.label_var, visit_expr (*brk.get_expr ()));
+}
+  add_jump_to (info.break_bb);
+  // No code allowed after break. No BB starts - would be empty.
 }
 
 void
@@ -370,60 +415,87 @@ ExprStmtBuilder::visit (HIR::UnsafeBlockExpr &expr)
   rust_sorry_at (expr.get_locus (), "unsafe blocks are not supported");
 }
 
+BuilderContext::LoopAndLabelInfo &
+ExprStmtBuilder::setup_loop (HIR::BaseLoopExpr &expr)
+{
+  NodeId label = (expr.has_loop_label ())
+  ? resolve_label (expr.get_loop_label ())
+  : UNKNOWN_NODEID;
+  PlaceId label_var = ctx.place_db.add_temporary (lookup_type (expr));
+
+  BasicBlockId continue_bb = new_bb ();
+  BasicBlockId break

[gcc/devel/rust/master] borrowck: Add CLI option for borrowck

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:7ac6f9b4c75cad8189611852c417e4f7483eaef9

commit 7ac6f9b4c75cad8189611852c417e4f7483eaef9
Author: Jakub Dupak 
Date:   Thu Oct 19 10:59:54 2023 +0200

borrowck: Add CLI option for borrowck

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-borrow-checker.cc 
(BorrowChecker::BorrowChecker): Opt dump.
(BorrowChecker::go): Opt dump.
* checks/errors/borrowck/rust-borrow-checker.h (class 
BorrowChecker): Opt dump.
* lang.opt: Add compile until borrowcheck.
* rust-session-manager.cc (Session::enable_dump): Add BIR.
(Session::compile_crate): Handle new options.
* rust-session-manager.h (struct CompileOptions): Add BIR.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc |  2 --
 gcc/rust/checks/errors/borrowck/rust-borrow-checker.h  |  5 -
 gcc/rust/lang.opt  |  7 +--
 gcc/rust/rust-session-manager.cc   | 14 +-
 gcc/rust/rust-session-manager.h|  3 +++
 5 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc 
b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
index a6086b8a6956..6c2922310423 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc
@@ -22,8 +22,6 @@
 namespace Rust {
 namespace HIR {
 
-BorrowChecker::BorrowChecker () = default;
-
 void
 BorrowChecker::go (HIR::Crate &crate)
 {
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h 
b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
index 7df5fe788a0b..549af3560e9b 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h
@@ -26,8 +26,11 @@ namespace HIR {
 
 class BorrowChecker
 {
+  bool enable_dump_bir;
+
 public:
-  BorrowChecker ();
+  explicit BorrowChecker (bool enable_dump_bir)
+: enable_dump_bir (enable_dump_bir){};
 
   /** Perform borrow-checking using polonius on an entire crate */
   void go (HIR::Crate &crate);
diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
index a77c0a903947..67285a6d92b2 100644
--- a/gcc/rust/lang.opt
+++ b/gcc/rust/lang.opt
@@ -190,10 +190,13 @@ EnumValue
 Enum(frust_compile_until) String(const) Value(8)
 
 EnumValue
-Enum(frust_compile_until) String(compilation) Value(9)
+Enum(frust_compile_until) String(borrowcheck) Value(9)
 
 EnumValue
-Enum(frust_compile_until) String(end) Value(10)
+Enum(frust_compile_until) String(compilation) Value(10)
+
+EnumValue
+Enum(frust_compile_until) String(end) Value(11)
 
 frust-name-resolution-2.0
 Rust Var(flag_name_resolution_2_0)
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index c674a18d1c92..2843b7d25cf2 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -51,6 +51,7 @@
 #include "selftest.h"
 #include "tm.h"
 #include "rust-target.h"
+#include "rust-borrow-checker.h"
 
 extern bool
 saw_errors (void);
@@ -313,7 +314,7 @@ Session::enable_dump (std::string arg)
"dump option was not given a name. choose %, %, "
"%, %, "
"%, %, %, %, "
-   "%, or %");
+   "%, % or %");
   return false;
 }
 
@@ -357,6 +358,10 @@ Session::enable_dump (std::string arg)
 {
   options.enable_dump_option (CompileOptions::HIR_DUMP_PRETTY);
 }
+  else if (arg == "bir")
+{
+  options.enable_dump_option (CompileOptions::BIR_DUMP);
+}
   else
 {
   rust_error_at (
@@ -659,6 +664,13 @@ Session::compile_crate (const char *filename)
 
   HIR::ConstChecker ().go (hir);
 
+  if (last_step == CompileOptions::CompileStep::BorrowCheck)
+return;
+
+  const bool dump_bir
+= options.dump_option_enabled (CompileOptions::DumpOption::BIR_DUMP);
+  HIR::BorrowChecker (dump_bir).go (hir);
+
   if (saw_errors ())
 return;
 
diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h
index 7e82291f95f9..2b1f6d00d9c9 100644
--- a/gcc/rust/rust-session-manager.h
+++ b/gcc/rust/rust-session-manager.h
@@ -221,6 +221,7 @@ struct CompileOptions
 TARGET_OPTION_DUMP,
 HIR_DUMP,
 HIR_DUMP_PRETTY,
+BIR_DUMP,
   };
 
   std::set dump_options;
@@ -254,6 +255,7 @@ struct CompileOptions
 Privacy,
 Unsafety,
 Const,
+BorrowCheck,
 Compilation,
 End,
   } compile_until
@@ -277,6 +279,7 @@ struct CompileOptions
 enable_dump_option (DumpOption::TARGET_OPTION_DUMP);
 enable_dump_option (DumpOption::HIR_DUMP);
 enable_dump_option (DumpOption::HIR_DUMP_PRETTY);
+enable_dump_option (DumpOption::BIR_DUMP);
   }
 
   void set_crate_name (std::string name)


[gcc/devel/rust/master] borrowck: Dump: handle infinite loops

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:8aac66b06e352ed869b76098dd07273d813128fc

commit 8aac66b06e352ed869b76098dd07273d813128fc
Author: Jakub Dupak 
Date:   Thu Oct 19 11:04:29 2023 +0200

borrowck: Dump: handle infinite loops

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-dump.cc (simplify_cfg): Detech 
infinite loops.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/checks/errors/borrowck/rust-bir-dump.cc | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
index ba530983dade..66870ddeb565 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -1,5 +1,6 @@
 #include 
 #include "rust-bir-dump.h"
+#include "rust-diagnostics.h"
 
 namespace Rust {
 namespace BIR {
@@ -76,7 +77,21 @@ simplify_cfg (Function &func, std::vector 
&bb_fold_map)
  const BasicBlock &bb = func.basic_blocks[bb_fold_map[i]];
  if (bb.statements.empty () && bb.is_goto_terminated ())
{
- bb_fold_map[i] = bb.successors.at (0);
+ auto dst = bb.successors.at (0);
+ if (bb_fold_map[dst] != dst)
+   {
+ rust_error_at (
+   UNKNOWN_LOCATION,
+   "BIR DUMP: Cannot fold CFG, because it contains an "
+   "infinite loop with no executable statements.");
+ rust_inform (UNKNOWN_LOCATION,
+  "Continuing with an unfolded CFG.");
+ // Reverting the fold map to the original state.
+ std::iota (bb_fold_map.begin (), bb_fold_map.end (), 0);
+ stabilized = true;
+ break;
+   }
+ bb_fold_map[i] = dst;
  stabilized = false;
}
}


[gcc/devel/rust/master] borrowck: Create Borrow-checker IR (BIR)

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:dfafead7c2a5f94d62fdd995b626d5a7cd23aaf2

commit dfafead7c2a5f94d62fdd995b626d5a7cd23aaf2
Author: Jakub Dupak 
Date:   Wed Oct 18 19:49:59 2023 +0200

borrowck: Create Borrow-checker IR (BIR)

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-borrow-checker.cc: Include to compile 
new code.
* checks/errors/borrowck/rust-bir-place.h: New file.
* checks/errors/borrowck/rust-bir-visitor.h: New file.
* checks/errors/borrowck/rust-bir.h: New file.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/checks/errors/borrowck/rust-bir-place.h   | 257 +
 gcc/rust/checks/errors/borrowck/rust-bir-visitor.h |  62 +
 gcc/rust/checks/errors/borrowck/rust-bir.h | 200 
 .../checks/errors/borrowck/rust-borrow-checker.cc  |   2 +
 4 files changed, 521 insertions(+)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h 
b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
new file mode 100644
index ..ce32f9262ceb
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -0,0 +1,257 @@
+// Copyright (C) 2020-2023 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_BIR_PLACE_H
+#define RUST_BIR_PLACE_H
+
+#include 
+#include "rust-mapping-common.h"
+#include "rust-system.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace BIR {
+
+/** A unique identifier for a place in the BIR. */
+using PlaceId = uint32_t;
+
+static constexpr PlaceId INVALID_PLACE = 0;
+static constexpr PlaceId RETURN_VALUE_PLACE = 1;
+static constexpr PlaceId FIRST_VARIABLE_PLACE = RETURN_VALUE_PLACE;
+
+/**
+ * A unique identifier for a lifetime in the BIR. Only to be used INTERNALLY.
+ */
+using LifetimeID = uint32_t;
+
+constexpr LifetimeID INVALID_LIFETIME_ID = 0;
+constexpr LifetimeID STATIC_LIFETIME_ID = 1;
+constexpr LifetimeID FIRST_NORMAL_LIFETIME_ID = 2;
+
+/** Representation of lifetimes in BIR. */
+struct Lifetime
+{
+  LifetimeID id = INVALID_LIFETIME_ID;
+
+  constexpr Lifetime (LifetimeID id) : id (id) {}
+  constexpr Lifetime (const Lifetime &) = default;
+  WARN_UNUSED_RESULT bool has_lifetime () const
+  {
+return id != INVALID_LIFETIME_ID;
+  }
+  LifetimeID operator() () const { return id; }
+};
+constexpr Lifetime NO_LIFETIME = {INVALID_LIFETIME_ID};
+constexpr Lifetime STATIC_LIFETIME = {STATIC_LIFETIME_ID};
+
+/**
+ * Representation of lvalues and constants in BIR.
+ * See bir bir design notes (in this directory) and the Polonius book.
+ */
+struct Place
+{
+  enum Kind
+  {
+INVALID,
+VARIABLE,
+TEMPORARY,
+CONSTANT,
+FIELD,
+INDEX,
+DEREF,
+  };
+
+  Kind kind;
+  uint32_t variable_or_field_index; // NodeId for VARIABLE
+  /** Data for traversing paths in the PlaceDB. */
+  struct Path
+  {
+PlaceId parent = INVALID_PLACE;
+PlaceId first_child = INVALID_PLACE;
+PlaceId next_sibling = INVALID_PLACE;
+
+Path (PlaceId parent, PlaceId first_child, PlaceId next_sibling)
+  : parent (parent), first_child (first_child), next_sibling (next_sibling)
+{}
+Path () = default;
+  } path;
+  /** Copy trait */
+  bool is_copy;
+  /** This place can be moved from safety. */
+  bool is_rvalue;
+  Lifetime lifetime;
+  TyTy::BaseType *tyty;
+
+  Place (Kind kind, uint32_t variable_or_field_index, const Path &path,
+bool is_copy, bool is_rvalue, const Lifetime &lifetime,
+TyTy::BaseType *tyty)
+: kind (kind), variable_or_field_index (variable_or_field_index),
+  path (path), is_copy (is_copy), is_rvalue (is_rvalue),
+  lifetime (lifetime), tyty (tyty)
+  {}
+};
+
+/** Allocated places and keeps track of paths. */
+class PlaceDB
+{
+  // Possible optimizations: separate variables to speedup lookup.
+  std::vector places;
+  std::unordered_map constants_lookup;
+
+public:
+  PlaceDB ()
+  {
+// Reserved index for invalid place.
+places.push_back (
+  {Place::INVALID, 0, {}, false, false, NO_LIFETIME, nullptr});
+  }
+
+  Place &operator[] (PlaceId id) { return places.at (id); }
+  const Place &operator[] (PlaceId id) const { return places.at (id); }
+
+  size_t size () const { return places.size (); }
+
+  PlaceId add_place (Place place, PlaceId last_sibling = 0)
+  {
+places.push_back (place);
+PlaceId new_place = plac

[gcc/devel/rust/master] borrowck: BIR continue

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:587c3b2b91db8034a6fc7f6c7ef6ba672147ecea

commit 587c3b2b91db8034a6fc7f6c7ef6ba672147ecea
Author: Jakub Dupak 
Date:   Wed Oct 18 23:01:06 2023 +0200

borrowck: BIR continue

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
(ExprStmtBuilder::visit): Continue.
(ExprStmtBuilder::setup_loop): Continue.

Signed-off-by: Jakub Dupak 

Diff:
---
 .../errors/borrowck/rust-bir-builder-expr-stmt.cc  | 50 ++
 1 file changed, 32 insertions(+), 18 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index 67b98e2254f9..9a850facff96 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -305,20 +305,32 @@ ExprStmtBuilder::visit (HIR::BlockExpr &block)
 void
 ExprStmtBuilder::visit (HIR::ContinueExpr &cont)
 {
-  //  BuilderContext::LabelledBlockCtx loop_ctx;
-  //  NodeId label = UNKNOWN_NODEID;
-  //  if (cont.has_label ())
-  //{
-  //  if (!resolve_label (cont.get_label (), label))
-  //   return;
-  //}
-  //
-  //  if (!find_block_ctx (label, loop_ctx))
-  //{
-  //  rust_error_at (cont.get_locus (), "unresolved loop label");
-  //}
-  //
-  //  add_jump_to (loop_ctx.continue_bb);
+  BuilderContext::LoopAndLabelInfo info;
+  if (cont.has_label ())
+{
+  NodeId label = resolve_label (cont.get_label ());
+  auto lookup
+   = std::find_if (ctx.loop_and_label_stack.rbegin (),
+   ctx.loop_and_label_stack.rend (),
+   [label] (const BuilderContext::LoopAndLabelInfo &info) {
+ return info.label == label;
+   });
+  rust_assert (lookup != ctx.loop_and_label_stack.rend ());
+  info = *lookup;
+}
+  else
+{
+  auto lookup
+   = std::find_if (ctx.loop_and_label_stack.rbegin (),
+   ctx.loop_and_label_stack.rend (),
+   [] (const BuilderContext::LoopAndLabelInfo &info) {
+ return info.is_loop;
+   });
+  rust_assert (lookup != ctx.loop_and_label_stack.rend ());
+  info = *lookup;
+}
+  add_jump_to (info.continue_bb);
+  // No code allowed after continue. No BB starts - would be empty.
 }
 
 void
@@ -418,9 +430,10 @@ ExprStmtBuilder::visit (HIR::UnsafeBlockExpr &expr)
 BuilderContext::LoopAndLabelInfo &
 ExprStmtBuilder::setup_loop (HIR::BaseLoopExpr &expr)
 {
-  NodeId label = (expr.has_loop_label ())
-  ? resolve_label (expr.get_loop_label ())
-  : UNKNOWN_NODEID;
+  NodeId label
+= (expr.has_loop_label ())
+   ? expr.get_loop_label ().get_lifetime ().get_mappings ().get_nodeid ()
+   : UNKNOWN_NODEID;
   PlaceId label_var = ctx.place_db.add_temporary (lookup_type (expr));
 
   BasicBlockId continue_bb = new_bb ();
@@ -439,7 +452,8 @@ ExprStmtBuilder::visit (HIR::LoopExpr &expr)
 
   ctx.current_bb = loop.continue_bb;
   (void) visit_expr (*expr.get_loop_block ());
-  add_jump_to (loop.continue_bb);
+  if (!ctx.get_current_bb ().is_terminated ())
+add_jump_to (loop.continue_bb);
 
   ctx.current_bb = loop.break_bb;
 }


[gcc/devel/rust/master] borrowck: BIR dump

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:f5b9bab688ae04d84ba83269b21e80d671453e45

commit f5b9bab688ae04d84ba83269b21e80d671453e45
Author: Jakub Dupak 
Date:   Wed Oct 18 22:36:38 2023 +0200

borrowck: BIR dump

gcc/rust/ChangeLog:

* Make-lang.in: Build BIR dump.
* checks/errors/borrowck/rust-borrow-checker.cc (mkdir_wrapped): 
Cross-platform mkdir.
(dump_function_bir): Save dump to file.
(BorrowChecker::go): Run dump during borrowck.
* checks/errors/borrowck/rust-bir-dump.cc: New file.
* checks/errors/borrowck/rust-bir-dump.h: New file.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/Make-lang.in  |   1 +
 gcc/rust/checks/errors/borrowck/rust-bir-dump.cc   | 239 +
 gcc/rust/checks/errors/borrowck/rust-bir-dump.h|  62 ++
 .../checks/errors/borrowck/rust-borrow-checker.cc  |  56 -
 4 files changed, 357 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 1e462ef6a1bf..facdd43fd518 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -150,6 +150,7 @@ GRS_OBJS = \
 rust/rust-hir-type-check-implitem.o \
 rust/rust-borrow-checker.o \
 rust/rust-bir-builder-expr-stmt.o \
+rust/rust-bir-dump.o \
 rust/rust-hir-dot-operator.o \
 rust/rust-hir-path-probe.o \
 rust/rust-type-util.o \
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
new file mode 100644
index ..cebed2485a31
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -0,0 +1,239 @@
+#include "rust-bir-dump.h"
+
+namespace Rust {
+namespace BIR {
+
+constexpr auto indentation = "";
+
+uint32_t
+get_place_name (PlaceId place_id)
+{
+  rust_assert (place_id >= FIRST_VARIABLE_PLACE);
+  return place_id - FIRST_VARIABLE_PLACE;
+}
+
+uint32_t
+get_lifetime_name (Lifetime lifetime_id)
+{
+  rust_assert (lifetime_id.id >= FIRST_NORMAL_LIFETIME_ID);
+  // Start from 1 as rustc does.
+  return lifetime_id.id - FIRST_NORMAL_LIFETIME_ID + 1;
+}
+
+std::string
+get_tyty_name (TyTy::BaseType *tyty)
+{
+  if (tyty)
+return tyty->get_name ();
+  return "unknown";
+}
+
+void
+Dump::go ()
+{
+  stream << "fn " << name << "(";
+  for (PlaceId arg : func.arguments)
+{
+  stream << "_" << get_place_name (arg) << ": "
+<< get_tyty_name (place_db[arg].tyty) << ", ";
+}
+  stream << ") -> " << get_tyty_name (place_db[RETURN_VALUE_PLACE].tyty)
+<< " {\n";
+
+  for (PlaceId id = FIRST_VARIABLE_PLACE; id < place_db.size (); ++id)
+{
+  const Place &place = place_db[id];
+  if (place.kind == Place::VARIABLE || place.kind == Place::TEMPORARY)
+   {
+ if (std::find (func.arguments.begin (), func.arguments.end (), id)
+ != func.arguments.end ())
+   continue;
+ stream << indentation << "let _" << get_place_name (id) << ": "
+<< get_tyty_name (place_db[id].tyty) << ";\n";
+   }
+}
+
+  for (BasicBlockId id = 0; id < func.basic_blocks.size (); ++id)
+{
+  if (func.basic_blocks[id].statements.empty ()
+ && func.basic_blocks[id].successors.empty ())
+   continue;
+
+  BasicBlock &bb = func.basic_blocks[id];
+  stream << "\n";
+  stream << indentation << "bb" << id << ": {\n";
+  for (auto &stmt : bb.statements)
+   {
+ stream << indentation << indentation;
+ visit (stmt);
+ stream << ";\n";
+   }
+  stream << indentation << "} -> [";
+  for (auto succ : bb.successors)
+   stream << "bb" << succ << ", ";
+  stream << "]\n";
+}
+
+  stream << "}\n\n";
+}
+void
+Dump::visit (Node &node)
+{
+  node_place = node.get_place ();
+  switch (node.get_kind ())
+{
+  case Node::Kind::ASSIGNMENT: {
+   stream << "_" << get_place_name (node.get_place ()) << " = ";
+   node.get_expr ().accept_vis (*this);
+   break;
+  }
+case Node::Kind::SWITCH:
+  stream << "switch ";
+  visit_move_place (node.get_place ());
+  break;
+case Node::Kind::RETURN:
+  stream << "return";
+  break;
+case Node::Kind::GOTO:
+  stream << "goto";
+  break;
+case Node::Kind::STORAGE_DEAD:
+  stream << "StorageDead(";
+  visit_move_place (node.get_place ());
+  stream << ")";
+  break;
+case Node::Kind::STORAGE_LIVE:
+  stream << "StorageLive(";
+  visit_move_place (node.get_place ());
+  stream << ")";
+  break;
+}
+  node_place = INVALID_PLACE;
+}
+
+void
+Dump::visit_place (PlaceId place_id)
+{
+  const Place &place = place_db[place_id];
+  switch (place.kind)
+{
+case Place::TEMPORARY:
+case Place::VARIABLE:
+  stream << "_" << get_place_name (place_id);
+  break;
+case Place::DEREF:
+  stream << "(";
+  stream << "*";
+  visit_place (place.path.parent);
+  stream << ")";

[gcc/devel/rust/master] borrowck: Make goto explicit.

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:449a3755412348d0f157c35da888ff07afc4f400

commit 449a3755412348d0f157c35da888ff07afc4f400
Author: Jakub Dupak 
Date:   Thu Oct 19 10:47:50 2023 +0200

borrowck: Make goto explicit.

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
(ExprStmtBuilder::visit): Use goto.
* checks/errors/borrowck/rust-bir-builder-internal.h: Explicit goto.
* checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Explicit 
goto.

Signed-off-by: Jakub Dupak 

Diff:
---
 .../errors/borrowck/rust-bir-builder-expr-stmt.cc  | 33 ++
 .../errors/borrowck/rust-bir-builder-internal.h|  7 +
 .../borrowck/rust-bir-builder-lazyboolexpr.h   |  7 ++---
 3 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index 9a850facff96..367aea7c2da3 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -329,7 +329,7 @@ ExprStmtBuilder::visit (HIR::ContinueExpr &cont)
   rust_assert (lookup != ctx.loop_and_label_stack.rend ());
   info = *lookup;
 }
-  add_jump_to (info.continue_bb);
+  push_goto (info.continue_bb);
   // No code allowed after continue. No BB starts - would be empty.
 }
 
@@ -364,7 +364,7 @@ ExprStmtBuilder::visit (HIR::BreakExpr &brk)
 {
   push_assignment (info.label_var, visit_expr (*brk.get_expr ()));
 }
-  add_jump_to (info.break_bb);
+  push_goto (info.break_bb);
   // No code allowed after break. No BB starts - would be empty.
 }
 
@@ -448,12 +448,12 @@ ExprStmtBuilder::visit (HIR::LoopExpr &expr)
 {
   auto loop = setup_loop (expr);
 
-  add_jump_to (loop.continue_bb);
+  push_goto (loop.continue_bb);
 
   ctx.current_bb = loop.continue_bb;
   (void) visit_expr (*expr.get_loop_block ());
   if (!ctx.get_current_bb ().is_terminated ())
-add_jump_to (loop.continue_bb);
+push_goto (loop.continue_bb);
 
   ctx.current_bb = loop.break_bb;
 }
@@ -463,7 +463,7 @@ ExprStmtBuilder::visit (HIR::WhileLoopExpr &expr)
 {
   auto loop = setup_loop (expr);
 
-  add_jump_to (loop.continue_bb);
+  push_goto (loop.continue_bb);
 
   ctx.current_bb = loop.continue_bb;
   auto cond_val = visit_expr (*expr.get_predicate_expr ());
@@ -472,7 +472,7 @@ ExprStmtBuilder::visit (HIR::WhileLoopExpr &expr)
 
   ctx.current_bb = body_bb;
   (void) visit_expr (*expr.get_loop_block ());
-  add_jump_to (loop.continue_bb);
+  push_goto (loop.continue_bb);
 
   ctx.current_bb = loop.break_bb;
 }
@@ -498,6 +498,8 @@ ExprStmtBuilder::visit (HIR::IfExpr &expr)
   ctx.current_bb = new_bb ();
   BasicBlockId then_start_block = ctx.current_bb;
   (void) visit_expr (*expr.get_if_block ());
+  if (!ctx.get_current_bb ().is_terminated ())
+push_goto (INVALID_BB); // Resolved later.
   BasicBlockId then_end_block = ctx.current_bb;
 
   ctx.current_bb = new_bb ();
@@ -508,7 +510,8 @@ ExprStmtBuilder::visit (HIR::IfExpr &expr)
   add_jump (if_block, then_start_block);
   add_jump (if_block, final_block);
 
-  if (!ctx.basic_blocks[then_end_block].is_terminated ())
+  auto &then_end_bb = ctx.basic_blocks[then_end_block];
+  if (then_end_bb.is_goto_terminated () && then_end_bb.successors.empty ())
 add_jump (then_end_block, final_block);
 }
 
@@ -523,11 +526,15 @@ ExprStmtBuilder::visit (HIR::IfExprConseqElse &expr)
   ctx.current_bb = new_bb ();
   auto then_res = visit_expr (*expr.get_if_block ());
   push_assignment (result, then_res);
+  if (!ctx.get_current_bb ().is_terminated ())
+push_goto (INVALID_BB); // Resolved later.
   BasicBlockId then_block = ctx.current_bb;
 
   ctx.current_bb = new_bb ();
   auto else_res = visit_expr (*expr.get_else_block ());
   push_assignment (result, else_res);
+  if (!ctx.get_current_bb ().is_terminated ())
+push_goto (INVALID_BB); // Resolved later.
   BasicBlockId else_block = ctx.current_bb;
 
   ctx.current_bb = new_bb ();
@@ -538,9 +545,12 @@ ExprStmtBuilder::visit (HIR::IfExprConseqElse &expr)
   add_jump (if_block, then_block);
   add_jump (if_block, else_block);
 
-  if (!ctx.basic_blocks[then_block].is_terminated ())
+  auto &then_bb = ctx.basic_blocks[then_block];
+  if (then_bb.is_goto_terminated () && then_bb.successors.empty ())
 add_jump (then_block, final_block);
-  if (!ctx.basic_blocks[else_block].is_terminated ())
+
+  auto &else_bb = ctx.basic_blocks[else_block];
+  if (else_bb.is_goto_terminated () && else_bb.successors.empty ())
 add_jump (else_block, final_block);
 }
 void
@@ -652,8 +662,8 @@ ExprStmtBuilder::visit (HIR::LetStmt &stmt)
 }
   else
 {
-  // TODO
-  rust_sorry_at (stmt.get_locus (), "pattern matching in let statements");
+  rust_sorry_at (stmt.get_locus (), "pattern matching in let statements "
+   "without initializer is not su

[gcc/devel/rust/master] borrowck: Dev notes

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:325dd9ed04bb3b73d52c35d065bca48c91995065

commit 325dd9ed04bb3b73d52c35d065bca48c91995065
Author: Jakub Dupak 
Date:   Tue Oct 24 08:32:20 2023 +0200

borrowck: Dev notes

gcc/rust/ChangeLog:

* checks/errors/borrowck/dev-notes.md: New file.

Signed-off-by: Jakub Dupak 

Diff:
---
 gcc/rust/checks/errors/borrowck/dev-notes.md | 40 
 1 file changed, 40 insertions(+)

diff --git a/gcc/rust/checks/errors/borrowck/dev-notes.md 
b/gcc/rust/checks/errors/borrowck/dev-notes.md
new file mode 100644
index ..2e170e761026
--- /dev/null
+++ b/gcc/rust/checks/errors/borrowck/dev-notes.md
@@ -0,0 +1,40 @@
+# Borrow-checker Development Notes
+
+## Testing BIR building
+
+There is no way to test BIR building directly, since it is a dead branch of 
the compilation pipeline.
+The only way to verify its generations is through manual inspection.
+The best way to inspect the BIR is to compare it with rustc's MIR.
+
+The following command will compile a rust file into a library and dump its MIR:
+
+```shell
+rustc --crate-type=lib -A dead_code -A unused -Z dump-mir="" 
+```
+
+The MIR dump directory `mir_dump` contains a dump before and after each MIR 
pass.
+We are interested in the one used for borrow-checking, which is called 
`..002-000.analysis.after.mir`.
+
+BIR dump is emitted to a `bir_dump` directory. With the following naming 
scheme: `..bir.dump`.
+
+At this point, MIR dump contains helper constructions that BIR does not 
contain yet (like storage live/dead annotations). To remove them from the MIR 
dump, run the following command:
+
+```shell
+awk -i inplace '!/^\s*(\/\/|StorageLive|StorageDead|FakeRead)/' mir_dump/*
+```
+
+To get the BIR dump into a similar format, run the following command:
+
+```shell
+./crab1  -frust-incomplete-and-experimental-compiler-do-not-use 
-frust-borrowcheck -frust-dump-bir -frust-compile-until=compilation
+```
+
+
+## TODO
+
+- scope handling, cleanup
+- switch coercions to adjustments from typechecking
+- operator overloading
+- match selection
+- let without an initializer
+- lifetime parameters
\ No newline at end of file


[gcc/devel/rust/master] borrowck: Refactor and BIR improvements

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:2a1a37344f0db01900e73f05fca71cdcf7a559c2

commit 2a1a37344f0db01900e73f05fca71cdcf7a559c2
Author: Jakub Dupak 
Date:   Thu Oct 19 15:26:35 2023 +0200

borrowck: Refactor and BIR improvements

gcc/rust/ChangeLog:

* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
(ExprStmtBuilder::setup_loop): Move.
(ExprStmtBuilder::get_label_ctx): Move.
(ExprStmtBuilder::get_unnamed_loop_ctx): Moved.
(ExprStmtBuilder::visit): BIR improvements.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Refactor.
* checks/errors/borrowck/rust-bir-builder-internal.h (class 
LifetimeResolver):
Refactor.
(struct BuilderContext): Move.Refactor.
(optional_from_ptr): Map on null ptr.
* checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h (class 
LazyBooleanExprBuilder):
Refactor.
* checks/errors/borrowck/rust-bir-builder-pattern.h: Refactor.
* checks/errors/borrowck/rust-bir-builder-struct.h (class 
StructBuilder): Refactor.
* checks/errors/borrowck/rust-bir-builder.h: Refactor.
* checks/errors/borrowck/rust-bir-dump.cc (Dump::go): Refactor.
(Dump::visit): Refactor.
(Dump::visit_place): Refactor.
(Dump::visit_move_place): Refactor.
(Dump::visit_lifetime): Refactor.
* checks/errors/borrowck/rust-bir-dump.h: Refactor.
* checks/errors/borrowck/rust-bir-place.h: Refactor.

Signed-off-by: Jakub Dupak 

Diff:
---
 .../errors/borrowck/rust-bir-builder-expr-stmt.cc  | 285 +-
 .../errors/borrowck/rust-bir-builder-expr-stmt.h   |  28 +-
 .../errors/borrowck/rust-bir-builder-internal.h| 319 -
 .../borrowck/rust-bir-builder-lazyboolexpr.h   |  89 +++---
 .../errors/borrowck/rust-bir-builder-pattern.h |  36 ++-
 .../errors/borrowck/rust-bir-builder-struct.h  |  22 +-
 gcc/rust/checks/errors/borrowck/rust-bir-builder.h |  10 +-
 gcc/rust/checks/errors/borrowck/rust-bir-dump.cc   |  57 ++--
 gcc/rust/checks/errors/borrowck/rust-bir-dump.h|   5 +-
 gcc/rust/checks/errors/borrowck/rust-bir-place.h   |  72 +++--
 10 files changed, 508 insertions(+), 415 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc 
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index 367aea7c2da3..96bc738964ed 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -25,6 +25,48 @@
 namespace Rust {
 namespace BIR {
 
+using LoopAndLabelCtx = BuilderContext::LoopAndLabelCtx;
+
+BuilderContext::LoopAndLabelCtx &
+ExprStmtBuilder::setup_loop (HIR::BaseLoopExpr &expr)
+{
+  NodeId label
+= (expr.has_loop_label ())
+   ? expr.get_loop_label ().get_lifetime ().get_mappings ().get_nodeid ()
+   : UNKNOWN_NODEID;
+  PlaceId label_var = take_or_create_return_place (lookup_type (expr));
+
+  BasicBlockId continue_bb = new_bb ();
+  BasicBlockId break_bb = new_bb ();
+  ctx.loop_and_label_stack.push_back (
+{true, label, label_var, break_bb, continue_bb});
+  return ctx.loop_and_label_stack.back ();
+}
+
+BuilderContext::LoopAndLabelCtx &
+ExprStmtBuilder::get_label_ctx (HIR::Lifetime &label)
+{
+  NodeId label_id = resolve_label (label);
+  auto lookup = std::find_if (ctx.loop_and_label_stack.rbegin (),
+ ctx.loop_and_label_stack.rend (),
+ [label_id] (LoopAndLabelCtx &info) {
+   return info.label == label_id;
+ });
+  rust_assert (lookup != ctx.loop_and_label_stack.rend ());
+  return *lookup;
+}
+
+LoopAndLabelCtx &
+ExprStmtBuilder::get_unnamed_loop_ctx ()
+{
+  auto lookup
+= std::find_if (ctx.loop_and_label_stack.rbegin (),
+   ctx.loop_and_label_stack.rend (),
+   [] (LoopAndLabelCtx &info) { return info.is_loop; });
+  rust_assert (lookup != ctx.loop_and_label_stack.rend ());
+  return *lookup;
+}
+
 void
 ExprStmtBuilder::visit (HIR::ClosureExpr &expr)
 {
@@ -34,8 +76,9 @@ ExprStmtBuilder::visit (HIR::ClosureExpr &expr)
 {
   captures.push_back (ctx.place_db.lookup_variable (capture));
 }
+  make_args (captures);
 
-  // Not a coercion site.
+  // Note: Not a coercion site for captures.
   return_expr (new InitializerExpr (std::move (captures)), lookup_type (expr));
 }
 
@@ -45,6 +88,7 @@ ExprStmtBuilder::visit (HIR::StructExprStructFields &fields)
   auto struct_ty
 = lookup_type (fields)->as ()->get_variants ().at (0);
   auto init_values = StructBuilder (ctx, struct_ty).build (fields);
+  make_args (init_values);
   return_expr (new InitializerExpr (std::move (init_values)),
   lookup_type (fields));
 }
@@ -59,7 +103,7 @@ ExprStmtBuilder::visit (HIR::StructExprStruct &expr)
 void
 ExprStmtBu

[gcc/devel/rust/master] Make proc macro definition cdecl

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:ff32f8fdcef87ef569fd072ee12c47237e8da2e7

commit ff32f8fdcef87ef569fd072ee12c47237e8da2e7
Author: Pierre-Emmanuel Patry 
Date:   Mon Sep 4 13:22:21 2023 +0200

Make proc macro definition cdecl

We need to make sure proc macros have the C abi in order to be called by
the compiler with dlopen.

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc (HIRCompileBase::setup_fndecl):
Add proc macro handlers dispatch.
(handle_proc_macro_common): Add a function for common behavior
between all kinds of proc macros.
* backend/rust-compile-base.h: Add function prototypes.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 47 +++
 gcc/rust/backend/rust-compile-base.h  | 12 +
 2 files changed, 59 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 7aab59baefec..1d1edfb20052 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -83,6 +83,13 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool 
is_main_entry_point,
= attr.get_path ().as_string () == Values::Attributes::NO_MANGLE;
   bool is_deprecated
= attr.get_path ().as_string () == Values::Attributes::DEPRECATED;
+  bool is_proc_macro
+   = attr.get_path ().as_string () == Values::Attributes::PROC_MACRO;
+  bool is_proc_macro_attribute
+   = attr.get_path ().as_string ()
+ == Values::Attributes::PROC_MACRO_ATTRIBUTE;
+  bool is_proc_macro_derive = attr.get_path ().as_string ()
+ == Values::Attributes::PROC_MACRO_DERIVE;
 
   if (is_inline)
{
@@ -108,9 +115,49 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool 
is_main_entry_point,
{
  handle_no_mangle_attribute_on_fndecl (fndecl, attr);
}
+  else if (is_proc_macro)
+   {
+ handle_proc_macro_attribute_on_fndecl (fndecl, attr);
+   }
+  else if (is_proc_macro_attribute)
+   {
+ handle_proc_macro_attribute_attribute_on_fndecl (fndecl, attr);
+   }
+  else if (is_proc_macro_derive)
+   {
+ handle_proc_macro_derive_attribute_on_fndecl (fndecl, attr);
+   }
 }
 }
 
+static void
+handle_proc_macro_common (tree fndecl, const AST::Attribute &attr)
+{
+  DECL_ATTRIBUTES (fndecl)
+= tree_cons (get_identifier ("cdecl"), NULL, DECL_ATTRIBUTES (fndecl));
+}
+
+void
+HIRCompileBase::handle_proc_macro_attribute_on_fndecl (
+  tree fndecl, const AST::Attribute &attr)
+{
+  handle_proc_macro_common (fndecl, attr);
+}
+
+void
+HIRCompileBase::handle_proc_macro_attribute_attribute_on_fndecl (
+  tree fndecl, const AST::Attribute &attr)
+{
+  handle_proc_macro_common (fndecl, attr);
+}
+
+void
+HIRCompileBase::handle_proc_macro_derive_attribute_on_fndecl (
+  tree fndecl, const AST::Attribute &attr)
+{
+  handle_proc_macro_common (fndecl, attr);
+}
+
 void
 HIRCompileBase::handle_cold_attribute_on_fndecl (tree fndecl,
 const AST::Attribute &attr)
diff --git a/gcc/rust/backend/rust-compile-base.h 
b/gcc/rust/backend/rust-compile-base.h
index 4a763a27862e..84775c870112 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -110,6 +110,18 @@ protected:
   static void handle_inline_attribute_on_fndecl (tree fndecl,
 const AST::Attribute &attr);
 
+  static void
+  handle_proc_macro_attribute_on_fndecl (tree fndecl,
+const AST::Attribute &attr);
+
+  static void
+  handle_proc_macro_attribute_attribute_on_fndecl (tree fndecl,
+  const AST::Attribute &attr);
+
+  static void
+  handle_proc_macro_derive_attribute_on_fndecl (tree fndecl,
+   const AST::Attribute &attr);
+
   static void handle_cold_attribute_on_fndecl (tree fndecl,
   const AST::Attribute &attr);


[gcc/devel/rust/master] Add const getter for tokentrees

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:b5118d1a6aa6dc2256d3f4620eb3185389531689

commit b5118d1a6aa6dc2256d3f4620eb3185389531689
Author: Pierre-Emmanuel Patry 
Date:   Wed Sep 6 14:09:25 2023 +0200

Add const getter for tokentrees

We often need to retrieve the underlying tokentree without modifying it,
this getter will help achieve this.

gcc/rust/ChangeLog:

* ast/rust-ast.h: Add const getter.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/ast/rust-ast.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index e5cadb673148..a2d088e05947 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -901,6 +901,11 @@ public:
 return token_trees;
   }
 
+  const std::vector> &get_token_trees () const
+  {
+return token_trees;
+  }
+
   DelimType get_delim_type () const { return delim_type; }
 };


[gcc/devel/rust/master] Change ABI setup and add gccrs_proc_macro attr

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:327a285500ac640f1d8257d11ea56bf4ab65ee47

commit 327a285500ac640f1d8257d11ea56bf4ab65ee47
Author: Pierre-Emmanuel Patry 
Date:   Mon Sep 4 14:23:10 2023 +0200

Change ABI setup and add gccrs_proc_macro attr

Change the way the ABI is setup on a function to avoid duplicates. ABI
is setup by the setup function only now. Add a new attribute to the
function "gccrs_proc_macro" in order to differentiate it from another
type of function.

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc (handle_proc_macro_common): Add
new attribute "gccrs_proc_macro" to all procedural macro
functions.
(get_abi): Add a function to retrieve the correct ABI depending
on wether the function is a proc macro or not.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 1d1edfb20052..78093a232ba9 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -133,8 +133,8 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool 
is_main_entry_point,
 static void
 handle_proc_macro_common (tree fndecl, const AST::Attribute &attr)
 {
-  DECL_ATTRIBUTES (fndecl)
-= tree_cons (get_identifier ("cdecl"), NULL, DECL_ATTRIBUTES (fndecl));
+  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("gccrs_proc_macro"),
+   NULL, DECL_ATTRIBUTES (fndecl));
 }
 
 void
@@ -591,6 +591,21 @@ HIRCompileBase::compile_function_body (tree fndecl,
 }
 }
 
+static ABI
+get_abi (const AST::AttrVec &outer_attrs,
+const HIR::FunctionQualifiers &qualifiers)
+{
+  bool is_proc_macro = std::any_of (outer_attrs.cbegin (), outer_attrs.cend (),
+   [] (const AST::Attribute &attr) {
+ auto path = attr.get_path ().as_string ();
+ return path == "proc_macro"
+|| path == "proc_macro_derive"
+|| path == "proc_macro_attribute";
+   });
+
+  return is_proc_macro ? ABI::CDECL : qualifiers.get_abi ();
+}
+
 tree
 HIRCompileBase::compile_function (
   const std::string &fn_name, HIR::SelfParam &self_param,
@@ -613,7 +628,7 @@ HIRCompileBase::compile_function (
 
   setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (),
visibility, qualifiers, outer_attrs);
-  setup_abi_options (fndecl, qualifiers.get_abi ());
+  setup_abi_options (fndecl, get_abi (outer_attrs, qualifiers));
 
   // conditionally mangle the function name
   bool should_mangle = should_mangle_item (fndecl);


[gcc/devel/rust/master] Add containers for proc macro collection mappings

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:e76f9223ed2860d49e1e11297d4cfdcebf27428f

commit e76f9223ed2860d49e1e11297d4cfdcebf27428f
Author: Pierre-Emmanuel Patry 
Date:   Wed Sep 6 14:34:45 2023 +0200

Add containers for proc macro collection mappings

Add one container for each kind of procedural macro mapping. Also add a
new structure to gather informations required for derive procedural
macros. Add different functions to fill those new containers.

gcc/rust/ChangeLog:

* backend/rust-compile-context.h (struct CustomDeriveInfo): Add
new derive procedural macro metadata information holder for
mappings.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-context.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-context.h 
b/gcc/rust/backend/rust-compile-context.h
index e60d32ca9411..c4bb8177b68c 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -38,6 +38,13 @@ struct fncontext
   TyTy::BaseType *retty;
 };
 
+struct CustomDeriveInfo
+{
+  tree fndecl;
+  std::string trait_name;
+  std::vector attributes;
+};
+
 class Context
 {
 public:
@@ -357,6 +364,18 @@ public:
 
   static hashval_t type_hasher (tree type);
 
+  void collect_attribute_proc_macro (tree fndecl)
+  {
+attribute_macros.push_back (fndecl);
+  }
+
+  void collect_bang_proc_macro (tree fndecl) { bang_macros.push_back (fndecl); 
}
+
+  void collect_derive_proc_macro (CustomDeriveInfo macro)
+  {
+custom_derive_macros.push_back (macro);
+  }
+
 private:
   Resolver::Resolver *resolver;
   Resolver::TypeCheckContext *tyctx;
@@ -381,6 +400,10 @@ private:
   std::map implicit_pattern_bindings;
   std::map main_variants;
 
+  std::vector custom_derive_macros;
+  std::vector attribute_macros;
+  std::vector bang_macros;
+
   // closure bindings
   std::vector closure_scope_bindings;
   std::map> closure_bindings;


[gcc/devel/rust/master] Reformat comments

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:80fe1c7b6f5a253655f7b5a8849b7d3c746cecf4

commit 80fe1c7b6f5a253655f7b5a8849b7d3c746cecf4
Author: Pierre-Emmanuel Patry 
Date:   Wed Sep 6 14:39:46 2023 +0200

Reformat comments

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc (HIRCompileBase::setup_abi_options):
Reformat uncorrectly formatted comments.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 78093a232ba9..cb8e650555da 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -252,8 +252,8 @@ HIRCompileBase::handle_deprecated_attribute_on_fndecl (
  auto key_value = converted_item->get_name_value_pair ();
  if (key_value.first.as_string ().compare ("since") == 0)
{
- // valid, but this is handled by Cargo and some third-party audit
- // tools
+ // valid, but this is handled by Cargo and some third-party
+ // audit tools
  continue;
}
  else if (key_value.first.as_string ().compare ("note") == 0)
@@ -373,10 +373,10 @@ HIRCompileBase::setup_abi_options (tree fndecl, ABI abi)
 case Rust::ABI::CDECL:
   // `decl_attributes` function (not the macro) has the side-effect of
   // actually switching the codegen backend to use the ABI we annotated.
-  // However, since `cdecl` is the default ABI GCC will be using, 
explicitly
-  // specifying that ABI will cause GCC to emit a warning saying the
-  // attribute is useless (which is confusing to the user as the attribute
-  // is added by us).
+  // However, since `cdecl` is the default ABI GCC will be using,
+  // explicitly specifying that ABI will cause GCC to emit a warning
+  // saying the attribute is useless (which is confusing to the user as
+  // the attribute is added by us).
   DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("cdecl"), NULL, DECL_ATTRIBUTES (fndecl));


[gcc/devel/rust/master] Collect procedural macros in the crate

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:573ca06d2a88c4cc27598c2f8597d8316f3fa418

commit 573ca06d2a88c4cc27598c2f8597d8316f3fa418
Author: Pierre-Emmanuel Patry 
Date:   Wed Sep 6 14:44:20 2023 +0200

Collect procedural macros in the crate

Collect informations on procedural macros in the compiled crate. For
attribute and bang procedural macros we only require the final address
as well as the name of the function. Derive procedural macros are a bit
different, we collect the fonction's address through it's fndecl tree as
well as the trait's name and the multiple attributes.

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc (HIRCompileBase::setup_fndecl):
Make the function non static in order to be able to access the
compile context. Also add the whole proc macro infomrmation
collection.
(get_attributes): Add a function to retrieve the different
attributes from a derive procedural macro definition attribute.
(get_trait_name): Add a function to retrieve the trait name from
a derive procedural macro definition attribute.
* backend/rust-compile-base.h: Add function prototypes.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 59 +++
 gcc/rust/backend/rust-compile-base.h  | 21 ++---
 2 files changed, 63 insertions(+), 17 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index cb8e650555da..9a7533a3b339 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -117,15 +117,15 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool 
is_main_entry_point,
}
   else if (is_proc_macro)
{
- handle_proc_macro_attribute_on_fndecl (fndecl, attr);
+ handle_bang_proc_macro_attribute_on_fndecl (fndecl, attr);
}
   else if (is_proc_macro_attribute)
{
- handle_proc_macro_attribute_attribute_on_fndecl (fndecl, attr);
+ handle_attribute_proc_macro_attribute_on_fndecl (fndecl, attr);
}
   else if (is_proc_macro_derive)
{
- handle_proc_macro_derive_attribute_on_fndecl (fndecl, attr);
+ handle_derive_proc_macro_attribute_on_fndecl (fndecl, attr);
}
 }
 }
@@ -138,24 +138,71 @@ handle_proc_macro_common (tree fndecl, const 
AST::Attribute &attr)
 }
 
 void
-HIRCompileBase::handle_proc_macro_attribute_on_fndecl (
+HIRCompileBase::handle_bang_proc_macro_attribute_on_fndecl (
   tree fndecl, const AST::Attribute &attr)
 {
   handle_proc_macro_common (fndecl, attr);
+  ctx->collect_bang_proc_macro (fndecl);
 }
 
 void
-HIRCompileBase::handle_proc_macro_attribute_attribute_on_fndecl (
+HIRCompileBase::handle_attribute_proc_macro_attribute_on_fndecl (
   tree fndecl, const AST::Attribute &attr)
 {
   handle_proc_macro_common (fndecl, attr);
+  ctx->collect_attribute_proc_macro (fndecl);
+}
+
+static std::vector
+get_attributes (const AST::Attribute &attr)
+{
+  std::vector result;
+
+  rust_assert (attr.get_attr_input ().get_attr_input_type ()
+  == Rust::AST::AttrInput::TOKEN_TREE);
+  const auto &tt
+= static_cast (attr.get_attr_input ());
+
+  // TODO: Should we rely on fixed index ? Should we search for the
+  // attribute tokentree instead ?
+  if (tt.get_token_trees ().size () > 3)
+{
+  rust_assert (tt.get_token_trees ()[3]->as_string () == "attributes");
+
+  auto attributes = static_cast (
+   tt.get_token_trees ()[4].get ());
+  auto &token_trees = attributes->get_token_trees ();
+
+  for (auto i = token_trees.cbegin () + 1; // Skip opening parenthesis
+  i < token_trees.cend ();
+  i += 2) // Skip comma and closing parenthesis
+   {
+ result.push_back ((*i)->as_string ());
+   }
+}
+  return result;
+}
+
+static std::string
+get_trait_name (const AST::Attribute &attr)
+{
+  rust_assert (attr.get_attr_input ().get_attr_input_type ()
+  == Rust::AST::AttrInput::TOKEN_TREE);
+  const auto &tt
+= static_cast (attr.get_attr_input ());
+  return tt.get_token_trees ()[1]->as_string ();
 }
 
 void
-HIRCompileBase::handle_proc_macro_derive_attribute_on_fndecl (
+HIRCompileBase::handle_derive_proc_macro_attribute_on_fndecl (
   tree fndecl, const AST::Attribute &attr)
 {
   handle_proc_macro_common (fndecl, attr);
+
+  attr.get_attr_input ().parse_to_meta_item ();
+  CustomDeriveInfo macro
+= {fndecl, get_trait_name (attr), get_attributes (attr)};
+  ctx->collect_derive_proc_macro (macro);
 }
 
 void
diff --git a/gcc/rust/backend/rust-compile-base.h 
b/gcc/rust/backend/rust-compile-base.h
index 84775c870112..ff6b30106e1b 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -102,24 +102,23 @@ protected:
 
   static tree unit_expression (Context *ctx, location_t locus);
 
-  static

[gcc/devel/rust/master] Add getters for proc macro mappings

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:c5dc4b0a5f4773c05ca4e8845df9b5cdeb978fc6

commit c5dc4b0a5f4773c05ca4e8845df9b5cdeb978fc6
Author: Pierre-Emmanuel Patry 
Date:   Fri Sep 8 11:23:51 2023 +0200

Add getters for proc macro mappings

Add three different getters, one for each proc macro type.

gcc/rust/ChangeLog:

* backend/rust-compile-context.h: Add getters.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-context.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-context.h 
b/gcc/rust/backend/rust-compile-context.h
index c4bb8177b68c..acfb360c3499 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -376,6 +376,16 @@ public:
 custom_derive_macros.push_back (macro);
   }
 
+  const std::vector &get_bang_proc_macros () const { return bang_macros; 
}
+  const std::vector &get_attribute_proc_macros () const
+  {
+return attribute_macros;
+  }
+  const std::vector &get_derive_proc_macros () const
+  {
+return custom_derive_macros;
+  }
+
 private:
   Resolver::Resolver *resolver;
   Resolver::TypeCheckContext *tyctx;


[gcc/devel/rust/master] Add utility function to build proc macro types

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:16c0f9c7fba577cb1c1c64d53468baeed81769a0

commit 16c0f9c7fba577cb1c1c64d53468baeed81769a0
Author: Pierre-Emmanuel Patry 
Date:   Fri Sep 15 11:08:13 2023 +0200

Add utility function to build proc macro types

Add some utility function to build proc macro entrypoint related types.
Those functions will help generate all required metadata in order for
proc macros to be expanded properly.

gcc/rust/ChangeLog:

* backend/rust-compile.cc (build_attribute_array): Add a function to
build the attribute array type.
(build_derive_proc_macro): Add a function to build the derive proc
macro type.
(build_bang_proc_macro): Add a function to build the bang proc macro
type.
(build_attribute_proc_macro): Add a function to build the attribute
proc macro type.
(build_proc_macro): Add a function to build the proc macro tagged 
union
type.
(build_proc_macro_buffer): Add a function to build the proc macro
buffer type.
(build_entrypoint): Add a function to build the proc macro 
entrypoint
type.
* backend/rust-compile.h: Add function prototype.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile.cc | 178 +++
 gcc/rust/backend/rust-compile.h  |   2 +
 2 files changed, 180 insertions(+)

diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 404b90aa01ac..90f12e585675 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -23,6 +23,7 @@
 #include "rust-compile-type.h"
 #include "rust-substitution-mapper.h"
 #include "rust-type-util.h"
+#include "rust-session-manager.h"
 
 namespace Rust {
 namespace Compile {
@@ -45,6 +46,183 @@ CompileCrate::go ()
 {
   for (auto &item : crate.get_items ())
 CompileItem::compile (item.get (), ctx);
+  auto crate_type
+= Rust::Session::get_instance ().options.target_data.get_crate_type ();
+  if (crate_type == TargetOptions::CrateType::PROC_MACRO)
+add_proc_macro_symbols ();
+}
+
+namespace {
+
+tree
+build_attribute_array (std::vector attributes)
+{
+  tree attribute_ptr = build_pointer_type (char_type_node);
+  tree attribute_type = build_qualified_type (attribute_ptr, TYPE_QUAL_CONST);
+  return build_array_type_nelts (attribute_type, attributes.size ());
+}
+
+// We're constructing the following structure:
+//
+// struct {
+// const char *trait_name;
+// const char **attributes;
+// std::uint64_t attr_size;
+// TokenStream (fndecl*) (TokenStream);
+// }
+tree
+build_derive_proc_macro (std::vector attributes)
+{
+  tree char_ptr = build_pointer_type (char_type_node);
+  tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
+  Backend::typed_identifier name_field
+= Backend::typed_identifier ("trait_name", const_char_type,
+BUILTINS_LOCATION);
+
+  // HACK: cannot use TREE_TYPE(fndecl) to retrieve the type, instead we're
+  // using a void pointer. We should probably find another way to achieve this.
+  // We cannot construct the type by ourselves because the function uses
+  // external TokenStream parameters and return type.
+  tree handle_ptr = build_pointer_type (void_type_node);
+  Backend::typed_identifier fndecl_field
+= Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION);
+
+  tree attribute_ptr = build_pointer_type (build_attribute_array (attributes));
+  tree const_attribute_type
+= build_qualified_type (attribute_ptr, TYPE_QUAL_CONST);
+
+  Backend::typed_identifier attributes_field
+= Backend::typed_identifier ("attributes", const_attribute_type,
+BUILTINS_LOCATION);
+
+  Backend::typed_identifier size_field
+= Backend::typed_identifier ("attr_size", unsigned_type_node,
+BUILTINS_LOCATION);
+
+  return Backend::struct_type (
+{name_field, attributes_field, size_field, fndecl_field});
+}
+
+// We're constructing the following structure:
+//
+// struct {
+// const char *name;
+// TokenStream (fndecl*) (TokenStream);
+// }
+tree
+build_bang_proc_macro ()
+{
+  tree char_ptr = build_pointer_type (char_type_node);
+  tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
+  Backend::typed_identifier name_field
+= Backend::typed_identifier ("name", const_char_type, BUILTINS_LOCATION);
+
+  // HACK: cannot use TREE_TYPE(fndecl) to retrieve the type, instead we're
+  // using a void pointer. We should probably find another way to achieve this.
+  // We cannot construct the type by ourselves because the function uses
+  // external TokenStream parameters and return type.
+  tree handle_ptr = build_pointer_type (void_type_node);
+  Backend::typed_identifier fndecl_field
+= Backend::typed_identifier ("fndecl", handle_pt

[gcc/devel/rust/master] Change proc macro entrypoint

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:b71fd2afa8316c3a247754963d801c4b7ca0050d

commit b71fd2afa8316c3a247754963d801c4b7ca0050d
Author: Pierre-Emmanuel Patry 
Date:   Wed Oct 4 12:01:44 2023 +0200

Change proc macro entrypoint

Change proc macro entrypoint from a fixed constant declaration to a
proper generation from the stable crate id. Although the stable crate id
is not in use yet, the mechanism to handle it is.

gcc/rust/ChangeLog:

* expand/rust-proc-macro.cc 
(CustomDeriveProcMacro::CustomDeriveProcMacro):
Remove constant string declaration.
(load_macros_array): Add call to the new generation function.
(generate_proc_macro_decls_symbol): Add a new function to generate 
the
entrypoint symbol name from the stable crate id.
(PROC_MACRO_DECLS_FMT_ARGS):
New macro to keep formats arguments in sync between each call.
* expand/rust-proc-macro.h (generate_proc_macro_decls_symbol): Add
function prototype.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/expand/rust-proc-macro.cc | 21 ++---
 gcc/rust/expand/rust-proc-macro.h  |  3 +++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/expand/rust-proc-macro.cc 
b/gcc/rust/expand/rust-proc-macro.cc
index 2fdfcb20b19b..3865b87b75b2 100644
--- a/gcc/rust/expand/rust-proc-macro.cc
+++ b/gcc/rust/expand/rust-proc-macro.cc
@@ -45,8 +45,6 @@ CustomDeriveProcMacro::CustomDeriveProcMacro 
(ProcMacro::CustomDerive macro)
 macro (macro.macro)
 {}
 
-const std::string PROC_MACRO_DECL_PREFIX = "__gccrs_proc_macro_decls_";
-
 namespace {
 
 ProcMacro::Literal
@@ -150,8 +148,10 @@ load_macros_array (std::string path)
 
   // FIXME: Add CrateStableId handling, right now all versions may be loaded,
   // even incompatible ones.
+  auto symbol_name = generate_proc_macro_decls_symbol (0 /* FIXME */);
+
   return *reinterpret_cast (
-dlsym (handle, PROC_MACRO_DECL_PREFIX.c_str ()));
+dlsym (handle, symbol_name.c_str ()));
 #else
   rust_sorry_at (UNDEF_LOCATION,
 "Procedural macros are not yet supported on windows host");
@@ -175,4 +175,19 @@ load_macros (std::string path)
array->macros + array->length);
 }
 
+std::string
+generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id)
+{
+#define PROC_MACRO_DECLS_FMT_ARGS  
\
+  "__gccrs_proc_macro_decls_%08x__", stable_crate_id
+  // Size could be hardcoded since we know the input size but I elected to
+  // calculate it everytime so we won't have any desync between code and data.
+  int size = std::snprintf (nullptr, 0, PROC_MACRO_DECLS_FMT_ARGS);
+  std::vector buf (size + 1);
+  std::sprintf (buf.data (), PROC_MACRO_DECLS_FMT_ARGS);
+#undef PROC_MACRO_DECLS_FMT_ARGS
+
+  return std::string (buf.cbegin (), buf.cend ());
+}
+
 } // namespace Rust
diff --git a/gcc/rust/expand/rust-proc-macro.h 
b/gcc/rust/expand/rust-proc-macro.h
index d994ed9bf5e0..6ffaaf6c099f 100644
--- a/gcc/rust/expand/rust-proc-macro.h
+++ b/gcc/rust/expand/rust-proc-macro.h
@@ -85,6 +85,9 @@ public:
 const std::vector
 load_macros (std::string path);
 
+std::string
+generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id);
+
 } // namespace Rust
 
 #endif /* ! RUST_PROC_MACRO_H */


[gcc/devel/rust/master] Add an explicit value to proc macro enum kind

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:5afa8b58b73d46091117867aff6f22703c2cb67f

commit 5afa8b58b73d46091117867aff6f22703c2cb67f
Author: Pierre-Emmanuel Patry 
Date:   Wed Sep 27 16:21:25 2023 +0200

Add an explicit value to proc macro enum kind

We'll need this value in the final binary, it should therefore be kept
explicit.

ChangeLog:

* libgrust/libproc_macro_internal/proc_macro.h (enum ProcmacroTag): 
Add
explicit value for proc macro tag enum.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 libgrust/libproc_macro_internal/proc_macro.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libgrust/libproc_macro_internal/proc_macro.h 
b/libgrust/libproc_macro_internal/proc_macro.h
index 457ec4693f64..9e142ffa79ff 100644
--- a/libgrust/libproc_macro_internal/proc_macro.h
+++ b/libgrust/libproc_macro_internal/proc_macro.h
@@ -66,7 +66,7 @@ struct Bang
 
 enum ProcmacroTag
 {
-  CUSTOM_DERIVE,
+  CUSTOM_DERIVE = 0,
   ATTR,
   BANG,
 };


[gcc/devel/rust/master] Add macro buffer global variable export

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:aee54e56a98da4179aa4f8553766fc8b252b0e01

commit aee54e56a98da4179aa4f8553766fc8b252b0e01
Author: Pierre-Emmanuel Patry 
Date:   Wed Sep 20 17:39:16 2023 +0200

Add macro buffer global variable export

Export a new symbol containing the proc macros.

gcc/rust/ChangeLog:

* backend/rust-compile-base.h: Make static function 
address_expression
public.
* backend/rust-compile.cc (CompileCrate::add_proc_macro_symbols): 
Add
new global variable in export function.
(build_bang_proc_macro): Add a function to build the bang proc macro
structure type.
(build_proc_macro): Add a function to build the proc macro structure
type.
(build_proc_macro_payload): Add a function to build the proc macro
union used in proc macro structures.
(init_derive_proc_macro): Add a function to initialize custom derive
proc macros.
(init_attribute_proc_macro): Add a function to initialize attribute
proc macros.
(init_bang_proc_macro): Add a function to initialize bang proc 
macros.
(init_proc_macro): Add a function to initialize proc macro 
structures.
(initialize_proc_macro_array): Add a function to initialize the proc
macro buffer array.
(CompileCrate::add_proc_macro_symbols): Add call to the new 
functions
to correctly initialize proc macros as well as their entrypoint.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-base.h |   4 +-
 gcc/rust/backend/rust-compile.cc | 252 ---
 2 files changed, 206 insertions(+), 50 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.h 
b/gcc/rust/backend/rust-compile-base.h
index ff6b30106e1b..cfe8c0e7b360 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -29,6 +29,8 @@ class HIRCompileBase
 public:
   virtual ~HIRCompileBase () {}
 
+  static tree address_expression (tree expr, location_t locus);
+
 protected:
   HIRCompileBase (Context *ctx) : ctx (ctx) {}
 
@@ -139,8 +141,6 @@ protected:
 
   static void setup_abi_options (tree fndecl, ABI abi);
 
-  static tree address_expression (tree expr, location_t locus);
-
   static tree indirect_expression (tree expr, location_t locus);
 
   static bool mark_addressable (tree, location_t);
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 90f12e585675..03aafc86e9cc 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -17,6 +17,7 @@
 // .
 
 #include "rust-compile.h"
+#include "libproc_macro_internal/proc_macro.h"
 #include "rust-compile-item.h"
 #include "rust-compile-implitem.h"
 #include "rust-hir-type-bounds.h"
@@ -28,6 +29,8 @@
 namespace Rust {
 namespace Compile {
 
+const std::string GCCRS_PROC_MACRO_SYMBOL_PREFIX = "__gccrs_proc_macro_";
+
 CompileCrate::CompileCrate (HIR::Crate &crate, Context *ctx)
   : crate (crate), ctx (ctx)
 {}
@@ -52,6 +55,8 @@ CompileCrate::go ()
 add_proc_macro_symbols ();
 }
 
+// This namespace brings multiple function to build and initialize multiple
+// structures that needs to get exposed in the final shared object binary.
 namespace {
 
 tree
@@ -71,7 +76,7 @@ build_attribute_array (std::vector attributes)
 // TokenStream (fndecl*) (TokenStream);
 // }
 tree
-build_derive_proc_macro (std::vector attributes)
+build_derive_proc_macro ()
 {
   tree char_ptr = build_pointer_type (char_type_node);
   tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
@@ -79,20 +84,13 @@ build_derive_proc_macro (std::vector 
attributes)
 = Backend::typed_identifier ("trait_name", const_char_type,
 BUILTINS_LOCATION);
 
-  // HACK: cannot use TREE_TYPE(fndecl) to retrieve the type, instead we're
-  // using a void pointer. We should probably find another way to achieve this.
-  // We cannot construct the type by ourselves because the function uses
-  // external TokenStream parameters and return type.
   tree handle_ptr = build_pointer_type (void_type_node);
   Backend::typed_identifier fndecl_field
 = Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION);
 
-  tree attribute_ptr = build_pointer_type (build_attribute_array (attributes));
-  tree const_attribute_type
-= build_qualified_type (attribute_ptr, TYPE_QUAL_CONST);
-
+  tree attribute_ptr = build_pointer_type (const_ptr_type_node);
   Backend::typed_identifier attributes_field
-= Backend::typed_identifier ("attributes", const_attribute_type,
+= Backend::typed_identifier ("attributes", attribute_ptr,
 BUILTINS_LOCATION);
 
   Backend::typed_identifier size_field
@@ -117,11 +115,7 @@ build_bang_proc_macro ()
   Backend::typed_identifier name_field

[gcc/devel/rust/master] Put common functions in their own namespace

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:a1ed0756c05fbd92d29f54d02556c75d4b1864c5

commit a1ed0756c05fbd92d29f54d02556c75d4b1864c5
Author: Pierre-Emmanuel Patry 
Date:   Wed Oct 4 18:48:04 2023 +0200

Put common functions in their own namespace

Half of the functions introduced recently had a similar goal while the
other half had a similar goal too. Introducing some namespace to separate
those will keep the code cleaner and avoid confusion.

gcc/rust/ChangeLog:

* backend/rust-compile.cc (build_attribute_array): Renamed from...
(attribute_array): ...to attribute array.
(build_derive_proc_macro): Likewise from...
(derive_proc_macro): ... to derive_proc_macro.
(build_bang_proc_macro): Likewise from...
(bang_proc_macro): ...to bang_proc_macro.
(build_attribute_proc_macro): Likewise from...
(attribute_proc_macro): ... to attribute_proc_macro.
(build_proc_macro_payload): Likewise from...
(proc_macro_payload): to proc_macro_payload.
(build_proc_macro): Likewise from...
(proc_macro): ...to proc_macro.
(build_proc_macro_buffer): Likewise from...
(proc_macro_buffer): ... to proc_macro_buffer.
(build_entrypoint): Likewise from...
(entrypoint): ...to entrypoint.
(init_derive_proc_macro): Renamed to it's shorter counterpart.
(init_attribute_proc_macro): Likewise.
(init_bang_proc_macro): Likewise.
(init_proc_macro): Likewise.
(initialize_proc_macro_array): Likewise.
(proc_macro_array): Likewise.
(CompileCrate::add_proc_macro_symbols): Update function calls.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile.cc | 162 ---
 1 file changed, 102 insertions(+), 60 deletions(-)

diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 03aafc86e9cc..24ac5dde1231 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -56,11 +56,23 @@ CompileCrate::go ()
 }
 
 // This namespace brings multiple function to build and initialize multiple
-// structures that needs to get exposed in the final shared object binary.
+// structures that needs to get exposed in the final shared library for
+// procedural macro crates.
+//
+// The compiler needs some additional metadata to find which function 
correspond
+// to the desired macro. The library shall expose one entrypoint symbol leading
+// to those metadata which in turn lead to the correct function.
+// This namespace describes how to build and initialize those metadata
+// structures. Those structure should be kept in sync with the structures in
+// libproc_macro_internal/proc_macro.h describing how they should be read.
 namespace {
 
+// Namespace containing all functions to build the different types.
+namespace build {
+
+// Build an array of attribute type for derive procedural macros.
 tree
-build_attribute_array (std::vector attributes)
+attribute_array (std::vector attributes)
 {
   tree attribute_ptr = build_pointer_type (char_type_node);
   tree attribute_type = build_qualified_type (attribute_ptr, TYPE_QUAL_CONST);
@@ -75,27 +87,26 @@ build_attribute_array (std::vector attributes)
 // std::uint64_t attr_size;
 // TokenStream (fndecl*) (TokenStream);
 // }
+// The resulting structure should be the same as `CustomDerive` in proc_macro.h
 tree
-build_derive_proc_macro ()
+derive_proc_macro ()
 {
   tree char_ptr = build_pointer_type (char_type_node);
   tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
-  Backend::typed_identifier name_field
-= Backend::typed_identifier ("trait_name", const_char_type,
-BUILTINS_LOCATION);
+  auto name_field = Backend::typed_identifier ("trait_name", const_char_type,
+  BUILTINS_LOCATION);
 
   tree handle_ptr = build_pointer_type (void_type_node);
-  Backend::typed_identifier fndecl_field
+  auto fndecl_field
 = Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION);
 
   tree attribute_ptr = build_pointer_type (const_ptr_type_node);
-  Backend::typed_identifier attributes_field
+  auto attributes_field
 = Backend::typed_identifier ("attributes", attribute_ptr,
 BUILTINS_LOCATION);
 
-  Backend::typed_identifier size_field
-= Backend::typed_identifier ("attr_size", unsigned_type_node,
-BUILTINS_LOCATION);
+  auto size_field = Backend::typed_identifier ("attr_size", unsigned_type_node,
+  BUILTINS_LOCATION);
 
   return Backend::struct_type (
 {name_field, attributes_field, size_field, fndecl_field});
@@ -107,8 +118,9 @@ build_derive_proc_macro ()
 // const char *name;
 // TokenStr

[gcc/devel/rust/master] Add array length to the proc macro buffer

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:3c6aca6cc174ac2881fb1783e0fda90c2b89bfc8

commit 3c6aca6cc174ac2881fb1783e0fda90c2b89bfc8
Author: Pierre-Emmanuel Patry 
Date:   Thu Oct 5 12:28:38 2023 +0200

Add array length to the proc macro buffer

The compiler cannot infer the array length from the type, we should
therefore hand it the information. The proc macro buffer missed that
information.

gcc/rust/ChangeLog:

* backend/rust-compile.cc (proc_macro_buffer): Update type builder 
with
array length information.
(proc_macro_array): Update type initializer with array length
information.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile.cc | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 24ac5dde1231..325e6eee2ba2 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -207,8 +207,14 @@ proc_macro ()
 tree
 proc_macro_buffer (tree proc_macro_type, size_t total_macro)
 {
-  // FIXME: Add the array length, build a structure containing an array
-  return build_array_type_nelts (proc_macro_type, total_macro);
+  auto length_field = Backend::typed_identifier ("length", unsigned_type_node,
+BUILTINS_LOCATION);
+
+  auto array_type = build_array_type_nelts (proc_macro_type, total_macro);
+  auto macros_field
+= Backend::typed_identifier ("macros", array_type, BUILTINS_LOCATION);
+
+  return Backend::struct_type ({length_field, macros_field});
 }
 
 // The entrypoint of a proc macro crate is a reference to the proc macro buffer
@@ -374,8 +380,15 @@ proc_macro_array (Context *ctx, tree 
proc_macro_buffer_type,
   index++;
 }
 
-  return Backend::array_constructor_expression (proc_macro_buffer_type, 
indexes,
-   ctors, BUILTINS_LOCATION);
+  auto length = build_int_cst (unsigned_type_node, ctors.size ());
+  auto array = Backend::array_constructor_expression (
+build_array_type_nelts (proc_macro_type, ctors.size ()), indexes, ctors,
+BUILTINS_LOCATION);
+  return Backend::constructor_expression (proc_macro_buffer_type,
+ false /* invariant */,
+ {length, array},
+ -1 /* Structure: No index */,
+ BUILTINS_LOCATION);
 }
 } // namespace init


[gcc/devel/rust/master] Move proc macro builders to their own file

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:4ac19a050193e0091a9556997780a0affb8a9621

commit 4ac19a050193e0091a9556997780a0affb8a9621
Author: Pierre-Emmanuel Patry 
Date:   Tue Oct 17 16:00:30 2023 +0200

Move proc macro builders to their own file

The code to build the required procedural macro symbols is rather long
and could be placed in it's own file.

gcc/rust/ChangeLog:

* Make-lang.in: Add gcc/rust/backend/rust-compile-proc-macro.cc to 
the
list of file to compile.
* backend/rust-compile.cc (attribute_array): Move to
rust-compile-proc-macro.cc
(derive_proc_macro): Likewise.
(bang_proc_macro): Likewise.
(attribute_proc_macro): Likewise.
(proc_macro_payload): Likewise.
(proc_macro): Likewise.
(proc_macro_buffer): Likewise.
(entrypoint): Likewise.
(proc_macro_array): Likewise.
(CompileCrate::add_proc_macro_symbols): Likewise.
* backend/rust-compile-proc-macro.cc: New file.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/Make-lang.in   |   1 +
 gcc/rust/backend/rust-compile-proc-macro.cc | 393 
 gcc/rust/backend/rust-compile.cc| 384 ---
 3 files changed, 394 insertions(+), 384 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index facdd43fd518..301c11a3dbcf 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -169,6 +169,7 @@ GRS_OBJS = \
 rust/rust-compile-intrinsic.o \
 rust/rust-compile-pattern.o \
 rust/rust-compile-fnparam.o \
+rust/rust-compile-proc-macro.o \
 rust/rust-base62.o \
 rust/rust-compile-item.o \
 rust/rust-compile-implitem.o \
diff --git a/gcc/rust/backend/rust-compile-proc-macro.cc 
b/gcc/rust/backend/rust-compile-proc-macro.cc
new file mode 100644
index ..91b38effaf27
--- /dev/null
+++ b/gcc/rust/backend/rust-compile-proc-macro.cc
@@ -0,0 +1,393 @@
+#include "rust-compile.h"
+#include "libproc_macro_internal/proc_macro.h"
+#include "rust-compile-context.h"
+#include "rust-compile-base.h"
+
+namespace Rust {
+namespace Compile {
+
+const std::string GCCRS_PROC_MACRO_SYMBOL_PREFIX = "__gccrs_proc_macro_";
+
+// This namespace brings multiple function to build and initialize multiple
+// structures that needs to get exposed in the final shared library for
+// procedural macro crates.
+//
+// The compiler needs some additional metadata to find which function 
correspond
+// to the desired macro. The library shall expose one entrypoint symbol leading
+// to those metadata which in turn lead to the correct function.
+// This namespace describes how to build and initialize those metadata
+// structures. Those structure should be kept in sync with the structures in
+// libproc_macro_internal/proc_macro.h describing how they should be read.
+namespace {
+
+// Namespace containing all functions to build the different types.
+namespace build {
+
+// Build an array of attribute type for derive procedural macros.
+tree
+attribute_array (std::vector attributes)
+{
+  tree attribute_ptr = build_pointer_type (char_type_node);
+  tree attribute_type = build_qualified_type (attribute_ptr, TYPE_QUAL_CONST);
+  return build_array_type_nelts (attribute_type, attributes.size ());
+}
+
+// We're constructing the following structure:
+//
+// struct {
+// const char *trait_name;
+// const char **attributes;
+// std::uint64_t attr_size;
+// TokenStream (fndecl*) (TokenStream);
+// }
+// The resulting structure should be the same as `CustomDerive` in proc_macro.h
+tree
+derive_proc_macro ()
+{
+  tree char_ptr = build_pointer_type (char_type_node);
+  tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
+  auto name_field = Backend::typed_identifier ("trait_name", const_char_type,
+  BUILTINS_LOCATION);
+
+  tree handle_ptr = build_pointer_type (void_type_node);
+  auto fndecl_field
+= Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION);
+
+  tree attribute_ptr = build_pointer_type (const_ptr_type_node);
+  auto attributes_field
+= Backend::typed_identifier ("attributes", attribute_ptr,
+BUILTINS_LOCATION);
+
+  auto size_field = Backend::typed_identifier ("attr_size", unsigned_type_node,
+  BUILTINS_LOCATION);
+
+  return Backend::struct_type (
+{name_field, attributes_field, size_field, fndecl_field});
+}
+
+// We're constructing the following structure:
+//
+// struct {
+// const char *name;
+// TokenStream (fndecl*) (TokenStream);
+// }
+// The resulting structure should be the same as `Bang` in proc_macro.h
+tree
+bang_proc_macro ()
+{
+  tree char_ptr = build_pointer_type (char_type_node);
+  tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
+ 

[gcc/devel/rust/master] Document proc macro token tree indices

2024-05-07 Thread Thomas Schwinge via Gcc-cvs
https://gcc.gnu.org/g:5d622b6a6d61743e054b226e441c755e1062c067

commit 5d622b6a6d61743e054b226e441c755e1062c067
Author: Pierre-Emmanuel Patry 
Date:   Mon Oct 23 15:00:54 2023 +0200

Document proc macro token tree indices

Multiple references to procedural macro token trees were left as magic
number in the code. This commit introduces some constexpr for those along
some explanation for the selected value.

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc (get_attributes): Add documentation 
for
indices 3 and 4.
(get_trait_name): Add documentation for index 1.

Signed-off-by: Pierre-Emmanuel Patry 

Diff:
---
 gcc/rust/backend/rust-compile-base.cc | 27 +++
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 9a7533a3b339..81ce0e919bd0 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -165,12 +165,24 @@ get_attributes (const AST::Attribute &attr)
 
   // TODO: Should we rely on fixed index ? Should we search for the
   // attribute tokentree instead ?
-  if (tt.get_token_trees ().size () > 3)
+
+  // Derive proc macros have the following format:
+  // #[proc_macro_derive(TraitName, attributes(attr1, attr2, attr3))]
+  //- - ~~-
+  //^0  ^1^2 ^3   ^4
+  // - "attributes" is stored at position 3 in the token tree
+  // - attribute are stored in the delimited token tree in position 4
+  constexpr size_t attr_kw_pos = 3;
+  constexpr size_t attribute_list_pos = 4;
+
+  if (tt.get_token_trees ().size () > attr_kw_pos)
 {
-  rust_assert (tt.get_token_trees ()[3]->as_string () == "attributes");
+  rust_assert (tt.get_token_trees ()[attr_kw_pos]->as_string ()
+  == "attributes");
 
   auto attributes = static_cast (
-   tt.get_token_trees ()[4].get ());
+   tt.get_token_trees ()[attribute_list_pos].get ());
+
   auto &token_trees = attributes->get_token_trees ();
 
   for (auto i = token_trees.cbegin () + 1; // Skip opening parenthesis
@@ -186,11 +198,18 @@ get_attributes (const AST::Attribute &attr)
 static std::string
 get_trait_name (const AST::Attribute &attr)
 {
+  // Derive proc macros have the following format:
+  // #[proc_macro_derive(TraitName, attributes(attr1, attr2, attr3))]
+  //- - ~~-
+  //^0  ^1^2 ^3   ^4
+  // - The trait name is stored at position 1
+  constexpr size_t trait_name_pos = 1;
+
   rust_assert (attr.get_attr_input ().get_attr_input_type ()
   == Rust::AST::AttrInput::TOKEN_TREE);
   const auto &tt
 = static_cast (attr.get_attr_input ());
-  return tt.get_token_trees ()[1]->as_string ();
+  return tt.get_token_trees ()[trait_name_pos]->as_string ();
 }
 
 void


  1   2   3   4   5   6   >