Hi!
In Nvidia PTX, "A state space is a storage area with particular
characteristics. All variables reside in some state space. [...]".
These include:
.const Shared, read-only memory.
.global Global memory, shared by all threads.
Implemented via 'TARGET_ENCODE_SECTION_INFO', GCC/nvptx then uses
special-cased instructions for accessing the respective memory regions.
Now, given a 'const' array (with whatever element type; not interesting
here), like:
extern int * const arr[];
..., for GCC/C compilation, we access this as '.const' memory: GCC/nvptx
'DATA_AREA_CONST', but for GCC/C++ compilation, we access it as
'DATA_AREA_GLOBAL', and then fault at run time due to mismatch with the
definition, which actually is '.const' for both C and C++ compilation.
The difference is, when we get to 'TARGET_ENCODE_SECTION_INFO', that for
C we've got 'TREE_READONLY(decl)', but for C++ we don't.
C:
Breakpoint 3, nvptx_encode_section_info (decl=0x7ffff7824720,
rtl=0x7ffff7843180, first=1) at ../../source-gcc/gcc/config/nvptx/nvptx.cc:468
468 {
(gdb) call debug_tree(decl)
<var_decl 0x7ffff7824720 arr
type <array_type 0x7ffff77f7f18
type <pointer_type 0x7ffff77f7d20 type <integer_type 0x7ffff76fa5e8
int>
readonly unsigned DI
size <integer_cst 0x7ffff76eb600 constant 64>
unit-size <integer_cst 0x7ffff76eb618 constant 8>
align:64 warn_if_not_align:0 symtab:0 alias-set -1
canonical-type 0x7ffff77f7d20>
BLK
align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7ffff77f7f18>
readonly used public external read BLK
source-gcc/gcc/testsuite/gcc.target/nvptx/const-1-2.c:8:20
align:64 warn_if_not_align:0 context <translation_unit_decl
0x7ffff783a100 source-gcc/gcc/testsuite/gcc.target/nvptx/const-1-2.c>
(mem/u/c:BLK (symbol_ref:DI ("arr") <var_decl 0x7ffff7824720 arr>) [1
arr+0 A64]) chain <function_decl 0x7ffff7819f00 main>>
Note 'readonly' ('TREE_READONLY') in the third-last line,
and '/u' (RTL 'MEM_READONLY_P') in the last line.
C++:
Breakpoint 3, nvptx_encode_section_info (decl=0x7ffff783fa18,
rtl=0x7ffff7844a50, first=1) at ../../source-gcc/gcc/config/nvptx/nvptx.cc:468
468 {
(gdb) call debug_tree(decl)
<var_decl 0x7ffff783fa18 arr
type <array_type 0x7ffff782f738
type <pointer_type 0x7ffff782fe70 type <integer_type 0x7ffff77015e8
int>
readonly unsigned type_6 DI
size <integer_cst 0x7ffff76eb900 constant 64>
unit-size <integer_cst 0x7ffff76eb918 constant 8>
align:64 warn_if_not_align:0 symtab:0 alias-set -1
canonical-type 0x7ffff782fe70>
type_6 BLK
align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7ffff782f738>
used public external read decl_2 BLK
source-gcc/gcc/testsuite/g++.target/nvptx/const-1-2.C:14:20
align:64 warn_if_not_align:0 context <translation_unit_decl
0x7ffff76fe000 source-gcc/gcc/testsuite/g++.target/nvptx/const-1-2.C>
(mem/c:BLK (symbol_ref:DI ("arr") <var_decl 0x7ffff783fa18 arr>) [1
arr+0 A64]) chain <function_decl 0x7ffff7830600 __cxa_call_terminate>>
Note no 'readonly' ('!TREE_READONLY') in the third-last line,
and no '/u' (RTL '!MEM_READONLY_P') in the last line.
Is this difference expected?
Now, for example, in 'gcc/config/avr/avr.cc', I found code like:
tree node0 = node;
/* For C++, we have to peel arrays in order to get correct
determination of readonlyness. */
do
node0 = TREE_TYPE (node0);
while (TREE_CODE (node0) == ARRAY_TYPE);
if (error_mark_node == node0)
return;
[...]
if (!TYPE_READONLY (node0)
&& !TREE_READONLY (node))
{
That is, in our case, instead of just looking at 'TREE_READONLY (node)',
we need:
if (TREE_READONLY (node) || TYPE_READONLY (node0))
[DATA_AREA_CONST]
else
[DATA_AREA_GLOBAL]
Is this indeed what we have to do? (It would appear to work in the case
analyzed above, but I've not yet checked for other fallout.)
Grüße
Thomas