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")); }