While implementing PR56263 (Strict address-space checking for AVR), I
encountered the problem that pointer casts with address spaces are always
expanded as const_int 0.

The problem occurs if the attached patch that implements PR56263 and the
following code is compiled as

$ avr-gcc -Os flash-cast.c -S -mstrict-addr-space-subsets


#define PROGMEM __attribute__((__progmem__))

#define PSTR(s)                                                         \
  (__extension__                                                        \
   ({                                                                   \
     static const char __c[] PROGMEM = (s);                             \
     &__c[0];                                                           \
   }))

extern void print (const __memx char*, ...);

const __flash char *p;

void f (const char *c)
{
    c = (const char*) p;

    print ((const __flash char*) PSTR ("Hallo flash"));
}



The corresponding .expand dump reads:


f (const char * c)
{
  static const char __c[12] = "Hallo flash";
  const <address-space-1> char * _2;
  const <address-space-7> char * _3;

;;   basic block 2, loop depth 0
;;    pred:       ENTRY
  _2 = (const <address-space-1> char *) (&__c[0]);
  _3 = (const <address-space-7> char *) _2;
  print (_3); [tail call]
  return;
;;    succ:       EXIT

}


but the expression is always emit as (const_int 0).


Trying to track this issue, I ended up in build1_stat which enters the default
case for "code" (ADDR_SPACE_CONVERT_EXPR at that time) and returns the
following tree:


(gdb) p t
$62 = (tree) 0xb7bb4578
(gdb) pt
 <addr_space_convert_expr 0xb7bb4578
    type <pointer_type 0xb7bc3a80
        type <integer_type 0xb7bc3a20 char readonly sizes-gimplified
address-space-1 string-flag QI
            size <integer_cst 0xb7b3a1a4 constant 8>
            unit size <integer_cst 0xb7b3a1b8 constant 1>
            align 8 symtab 0 alias set -1 canonical type 0xb7bc3a20 precision 8
min <integer_cst 0xb7b3a1e0 -128> max <integer_cst 0xb7b3a208 127>
            pointer_to_this <pointer_type 0xb7bc3a80>>
        unsigned HI
        size <integer_cst 0xb7b3a08c constant 16>
        unit size <integer_cst 0xb7b3a0a0 constant 2>
        align 8 symtab 0 alias set -1 canonical type 0xb7bc3a80>
    readonly constant
    arg 0 <addr_expr 0xb7bb449c
        type <pointer_type 0xb7b4f2a0 type <integer_type 0xb7b4f240 char>
            public unsigned HI size <integer_cst 0xb7b3a08c 16> unit size
<integer_cst 0xb7b3a0a0 2>
            align 8 symtab 0 alias set -1 canonical type 0xb7b4f2a0
            pointer_to_this <pointer_type 0xb7b4f840>>
        readonly constant
        arg 0 <array_ref 0xb7b465a0 type <integer_type 0xb7b4f240 char>
            readonly arg 0 <var_decl 0xb7bcd05c __c>
            arg 1 <integer_cst 0xb7b3a460 constant 0>
            flash-cast.c:18:128>
        flash-cast.c:18:124>>

Problem is the arg 1 <integer_cst 0xb7b3a460 constant 0> at the end which leads
to the expansion of 0.

The call chain is:

#0  build1_stat (code=ADDR_SPACE_CONVERT_EXPR, type=0xb7bc3a80,
node=0xb7bb449c) at ../../../gcc.gnu.org/trunk/gcc/tree.c:3848
(gdb) bt
#0  build1_stat (code=ADDR_SPACE_CONVERT_EXPR, type=0xb7bc3a80,
node=0xb7bb449c) at ../../../gcc.gnu.org/trunk/gcc/tree.c:3848
#1  0x08286be0 in gimple_assign_rhs_to_tree (stmt=0xb7bc2c30) at
../../../gcc.gnu.org/trunk/gcc/cfgexpand.c:86
#2  0x0837047f in expand_expr_real_1 (exp=0xb7b972f8, target=0x0,
tmode=VOIDmode, modifier=EXPAND_STACK_PARM, alt_rtl=0x0) at
../../../gcc.gnu.org/trunk/gcc/expr.c:9274
#3  0x083762f2 in expand_expr_real (exp=0xb7b972f8, target=0x0, tmode=VOIDmode,
modifier=EXPAND_STACK_PARM, alt_rtl=0x0) at
../../../gcc.gnu.org/trunk/gcc/expr.c:7863
#4  0x08376a7e in expand_expr (exp=0xb7b972f8, target=0x0, mode=VOIDmode,
modifier=EXPAND_STACK_PARM) at ../../../gcc.gnu.org/trunk/gcc/expr.h:444
#5  0x0836ae96 in expand_expr_real_2 (ops=0xbfffca10, target=0x0,
tmode=VOIDmode, modifier=EXPAND_STACK_PARM) at
../../../gcc.gnu.org/trunk/gcc/expr.c:8150
#6  0x08376234 in expand_expr_real_1 (exp=0xb7bb4564, target=0x0,
tmode=VOIDmode, modifier=EXPAND_STACK_PARM, alt_rtl=0x0) at
../../../gcc.gnu.org/trunk/gcc/expr.c:10491
#7  0x083762f2 in expand_expr_real (exp=0xb7bb4564, target=0x0, tmode=VOIDmode,
modifier=EXPAND_STACK_PARM, alt_rtl=0x0) at
../../../gcc.gnu.org/trunk/gcc/expr.c:7863
#8  0x083704a6 in expand_expr_real_1 (exp=0xb7b97320, target=0x0,
tmode=VOIDmode, modifier=EXPAND_STACK_PARM, alt_rtl=0x0) at
../../../gcc.gnu.org/trunk/gcc/expr.c:9274
#9  0x083762f2 in expand_expr_real (exp=0xb7b97320, target=0x0, tmode=VOIDmode,
modifier=EXPAND_STACK_PARM, alt_rtl=0x0) at
../../../gcc.gnu.org/trunk/gcc/expr.c:7863
#10 0x0826ae1a in expand_expr (exp=0xb7b97320, target=0x0, mode=VOIDmode,
modifier=EXPAND_STACK_PARM) at ../../../gcc.gnu.org/trunk/gcc/expr.h:444
#11 0x0826c215 in store_one_arg (arg=0xbfffd130, argblock=0x0, flags=0,
variable_size=0, reg_parm_stack_space=0) at
../../../gcc.gnu.org/trunk/gcc/calls.c:4500
#12 0x08274d79 in expand_call (exp=0xb7b46640, target=0x0, ignore=1) at
../../../gcc.gnu.org/trunk/gcc/calls.c:3040
#13 0x08375088 in expand_expr_real_1 (exp=0xb7b46640, target=0x0,
tmode=VOIDmode, modifier=EXPAND_NORMAL, alt_rtl=0x0) at
../../../gcc.gnu.org/trunk/gcc/expr.c:10209
#14 0x0828cb86 in expand_call_stmt (stmt=0xb7fde140) at
../../../gcc.gnu.org/trunk/gcc/cfgexpand.c:2114

...


The problem comes apparent in #5 expand_expr_real_2

         if (targetm.addr_space.subset_p (as_to, as_from)
             || targetm.addr_space.subset_p (as_from, as_to))
           {
             op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
             op0 = targetm.addr_space.convert (op0, treeop0_type, type);
             gcc_assert (op0);
             return op0;
           }

where op0 is const0_rtx and targetm.addr_space.convert cannot recover from that.

Maybe someone can help me fixing the root cause?

the incoming "node" in build1_stat has already arg 1 <integer_cst constant 0>

Thanks.

Johann

Index: config/avr/avr.opt
===================================================================
--- config/avr/avr.opt	(revision 196495)
+++ config/avr/avr.opt	(working copy)
@@ -74,3 +74,7 @@ When accessing RAM, use X as imposed by
 msp8
 Target Report RejectNegative Var(avr_sp8) Init(0)
 The device has no SPH special function register. This option will be overridden by the compiler driver with the correct setting if presence/absence of SPH can be deduced from -mmcu=MCU.
+
+mstrict-addr-space-subsets
+Target Report Var(avr_strict_addr_space_subsets) Init(0)
+An address space is regarded as a subset of an other address space only if it is physically a subset of the latter.  Without this option, each address space is a subset of any other address space.
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 196495)
+++ config/avr/avr.c	(working copy)
@@ -10757,11 +10757,11 @@ avr_addr_space_convert (rtx src, tree ty
 
 static bool
 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
-                         addr_space_t superset ATTRIBUTE_UNUSED)
+                         addr_space_t superset)
 {
-  /* Allow any kind of pointer mess.  */
+  /* Allow any kind of pointer mess without -mstrict-addr-space-subsets  */
 
-  return true;
+  return superset == ADDR_SPACE_MEMX || !avr_strict_addr_space_subsets;
 }
 
 
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 196495)
+++ doc/invoke.texi	(working copy)
@@ -514,7 +514,7 @@ Objective-C and Objective-C++ Dialects}.
 @emph{AVR Options}
 @gccoptlist{-mmcu=@var{mcu} -maccumulate-args -mbranch-cost=@var{cost} @gol
 -mcall-prologues -mint8 -mno-interrupts -mrelax @gol
--mstrict-X -mtiny-stack}
+-mstrict-addr-space-subsets -mstrict-X -mtiny-stack}
 
 @emph{Blackfin Options}
 @gccoptlist{-mcpu=@var{cpu}@r{[}-@var{sirevision}@r{]} @gol
@@ -11614,6 +11614,14 @@ proper's command line, because the compi
 or architecture has an 8-bit stack pointer and thus no @code{SPH}
 register or not.
 
+@item -mstrict-addr-space-subsets
+@opindex mstrict-addr-space-subsets
+As address space is treated as subset of an other address space only
+if it is physically a part of the latter.  This will result in more
+restrictive address space checking and respective pointer casts.
+Without this option, each address space is treated as subset of any other
+address space.
+
 @item -mstrict-X
 @opindex mstrict-X
 Use address register @code{X} in a way proposed by the hardware.  This means
#define PROGMEM __attribute__((__progmem__))

#define PSTR(s)                                                         \
  (__extension__                                                        \
   ({                                                                   \
     static const char __c[] PROGMEM = (s);                             \
     &__c[0];                                                           \
   }))

extern void print (const __memx char*, ...);

const __flash char *p;

void f (const char *c)
{
    c = (const char*) p;

    print ((const __flash char*) PSTR ("Hallo flash"));
}

Reply via email to