Hello,

The attached patch is a proposal to plug a hole in create_trace_edges
(dwarf2cfi.c), which doesn't handle casesi dispatch insns.

The visible misbehavior we observed is a failure in a cross configuration
of a recent acats test for Ada, a very simplified sketch of which is provided
below.

This was with gcc-7 on a port which has been deprecated since then, but ISTM
the problem remains latent for other ports.

Essentially, we had a jump insn like:

   if X <= 4                      -- for case values
     set pc *(&label_59 + kind * 4)  -- 0 .. 4
   else
     set pc &label_151

for the case statement, and the tablejump_p processing code in
create_trace_edges only gets through the first 5 possible targets.

The missing edge in the re-created control-flow graph eventually materialized
as missing .cfi_remember_state/.cfi_restore_state pairs in the output, which
resulted in bogus exception handling behavior.

The insn pattern corresponds to the one handled in patch_jump_insn
(cfgrtl.c). The proposed patch extracts the pattern recognition code
in a separate function and uses it in both patch_jump_insn and
create_trace_edges.

This fixed our problem on the cross port (arm-vxworks6) and we
have been running with it for all our gcc-7 and gcc-8 ports since
then, about 6 months ago now.

It also bootstraps and regression tests fine with mainline
on x86_64-linux.

Ok, to commit ?

Thanks in advance!

With Kind Regards,

Olivier

2019-08-09  Olivier Hainque  <hain...@adacore.com>

        * rtl.h (tablejump_casesi_pattern): New helper, casesi
        recognition logic originating from code in cfgrtl.c.
        * cfgrtl.c (patch_jump_insn): Use it.
        * dwarf2cfi.c (create_trace_edges): Handle casesi patterns.

--

with Ada.Assertions;
package body Casesi is

   function Process (X : Natural) return String is
   begin
      case X is
         when 0 => raise Ada.Assertions.Assertion_Error;
         when 1 => raise Ada.Assertions.Assertion_Error;
         when 2 => return (1 .. 4 => 'T');
         when 3 => return (2 .. 8 => 'T');
         when 4 => return "hello";
         when others => return (1 .. 0 => <>);
      end case;
   end;

   procedure Try (X : Natural) is
   begin
      declare
         Code : String := Process (X);
      begin
         if X < 2 then
            raise Program_Error;
         end if;
      end;
   exception
      when Ada.Assertions.Assertion_Error => null;
   end;
end;

package Casesi is
   procedure Try (X : Natural);
end;

with Casesi;
procedure Test_Casesi is
begin
   Casesi.Try (1);
   Casesi.Try (2);
   Casesi.Try (3);
end;

Attachment: casesi.diff
Description: Binary data

Reply via email to