internal compiler error at dwarf2out.c:8362

2005-04-12 Thread Martin Koegler
I'm working on a GCC port and hit the error

x.c:2: internal compiler error: in modified_type_die, at dwarf2out.c:8362

while compiling 

typedef unsigned char GROUP9_T[3];
typedef GROUP9_T EGROUP9_T __attribute ((eeprom));

with dwarf-2 debugging information. The eeprom attribute is defined so:

static tree
m68hc05_handle_eeprom_attribute (tree * node, tree name,
 tree args ATTRIBUTE_UNUSED,
 int flags ATTRIBUTE_UNUSED,
 bool * no_add_attrs)
{
  if (DECL_P (*node))
{
  if (TREE_CODE (*node) == TYPE_DECL)
{
  /* This is really a decl attribute, not a type attribute,
 but try to handle it for GCC 3.0 backwards compatibility.  */

  tree type = TREE_TYPE (*node);
  tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
  tree newtype = build_type_attribute_variant (type, attr);

  TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
  TREE_TYPE (*node) = newtype;
}
}
  return NULL_TREE;
}

const struct attribute_spec m68hc05_attribute_table[] = {
  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
  {"eeprom", 0, 0, false, true, false, m68hc05_handle_eeprom_attribute},
  {NULL, 0, 0, false, false, false, NULL}
};

Without dwarf-2 debugging, the file compiles.

Internal, the type looks so, when the function is called, which aborts:

Breakpoint 1, modified_type_die (type=0xb7f51288, is_const_type=0, 
is_volatile_type=0, context_die=0xb7f6bac4)
at ../.././gcc/dwarf2out.c:8258
8258  enum tree_code code = TREE_CODE (type);
(gdb) call debug_tree(type)
 
unit size 
align 8 symtab -1208530080 alias set -1 precision 8 min  max 
pointer_to_this >
BLK
size  
constant invariant 24>
unit size  constant invariant 3>
align 8 symtab 0 alias set -1
attributes >
domain 
unit size 
align 8 symtab -1208530132 alias set -1 precision 16 min 
 max >
HI size  unit size 
align 8 symtab 0 alias set -1 precision 16 min  max >>

The GCC core is gcc version 4.1.0 20050412 (experimental).

The bug only happens, if the base type of the second typedef is an array.

As I have not found the use of a port specific type attribute in GCC, I don't 
know,
how I can reproduce it on a official GCC port.

As I have not changed the tree based core and debugging output, the bug should 
be also present 
in the current CVS version.

Any ideas, how to handle this bug?

mfg Martin Kögler
[EMAIL PROTECTED]


Re: internal compiler error at dwarf2out.c:8362

2005-04-14 Thread Martin Koegler
On Wed, Apr 13, 2005 at 01:55:07PM -0700, James E Wilson wrote:
> Martin Koegler wrote:
> >  tree type = TREE_TYPE (*node);
> >  tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
> >  tree newtype = build_type_attribute_variant (type, attr);
> >  TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
> >  TREE_TYPE (*node) = newtype;
> 
> You shouldn't be trying to build your own types in a machine dependent 
> attribute handler function.  The compiler's type system is determined by 
> front-ends mainly, and some middle-end infrastructure, and isn't your 
> domain to mess with.  This stuff is subject to change, at which point 
> your code may break.
> 
> There are a number of subtleties in the type system relating to arrays, 
> so it isn't surprising that you are having trouble with them.  For 
> instance, you can't apply some kinds of type modifiers to array types, 
> they have to be applied to the array element types instead.
> 
> I think the problem with your code is that you are setting 
> TYPE_MAIN_VARIANT to point at the original type.  TYPE_MAIN_VARIANT is 
> only supposed to be used in the presence of type qualifiers like const 
> and volatile, to point at the unqualified type.  But you have no type 
> qualifiers here, and hence TYPE_MAIN_VARIANT should point at itself.

I changed the attribute handler to only return NULL_TREE in any case, but
the result is still the same (using the same gcc core).

The problem seems to be, that in the code
  gen_type_die (type, context_die);

  /* We have to get the type_main_variant here (and pass that to the
 `lookup_type_die' routine) because the ..._TYPE node we have
 might simply be a *copy* of some original type node (where the
 copy was created to help us keep track of typedef names) and
 that copy might have a different TYPE_UID from the original
 ..._TYPE node.  */
  if (TREE_CODE (type) != VECTOR_TYPE)
mod_type_die = lookup_type_die (type_main_variant (type));

gen_type_type does not change TYPE_SYMTAB_DIE(type), so the following lookup 
fails
(type has the same value as type_main_variant (type)).

gen_type_die does the following in this case:
gen_type_die calls gen_decl_die (TYPE_NAME (type), context_die). gen_decl_die 
calls
gen_typedef_die passing TYPE_NAME(type) (which is the GROUP9_T).
gen_typedef_die immediatly returns, because this type has already been written.

Here dumps of the types, while compiling 
typedef unsigned char GROUP9_T[3];
typedef GROUP9_T EGROUP9_T __attribute ((eeprom));

with dwarf2 debugging output.

When calling, the attribute handler, the type looks so:

Breakpoint 1, m68hc05_handle_eeprom_attribute (node=0xb7f51220, 
name=0xb7f74bc8, args=0x0, flags=0, no_add_attrs=0xbff60c8b "")
at ../.././gcc/config/m68hc05/m68hc05.c:1690
1690  return NULL_TREE;
(gdb) call debug_tree(*node)
 
unit size 
align 8 symtab -1208530080 alias set -1 precision 8 min  max 
pointer_to_this >
BLK
size  
constant invariant 24>
unit size  constant invariant 3>
align 8 symtab -1208567256 alias set -1
domain 
unit size 
align 8 symtab -1208530132 alias set -1 precision 16 min 
 max >
HI size  unit size 
align 8 symtab 0 alias set -1 precision 16 min  max >>

In modified_type_die, the qualified type looks so:
(gdb) call debug_tree(qualified_type)
 
unit size 
align 8 symtab -1208530080 alias set -1 precision 8 min  max 
pointer_to_this >
BLK
size  
constant invariant 24>
unit size  constant invariant 3>
align 8 symtab 0 alias set -1
attributes >
domain 
unit size 
align 8 symtab -1208530132 alias set -1 precision 16 min 
 max >
HI size  unit size 
align 8 symtab 0 alias set -1 precision 16 min  max >>

The typename of the type looks:
(gdb) call debug_tree(type_name)
 
unit size 
align 8 symtab -1208530080 alias set -1 precision 8 min 
 max 
pointer_to_this >
BLK
size 
unit size 
align 8 symtab -1208567256 alias set -1
domain 
HI
size 
unit size 
align 8 symtab 0 alias set -1 precision 16 min  max >>
asm_written VOID file x.c line 1
align 1
result 
asm_written BLK size  unit size 
align 8 symtab -1208530236 alias set -1 domain >>

DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)) is
 
unit size 
align 8 symtab -1208530080 alias set -1 precision 8 min  max 
pointer_to_this >
asm_written BLK
size  
constant invariant 24>
unit size  constant invariant 3>
align 8 

Re: internal compiler error at dwarf2out.c:8362

2005-04-16 Thread Martin Koegler
On Thu, Apr 14, 2005 at 03:02:36PM -0700, James E Wilson wrote:
> Martin Koegler wrote:
> >I changed the attribute handler to only return NULL_TREE in any case, but
> >the result is still the same (using the same gcc core).
> 
> But you are still creating the types in the attribute function right? 
> If so, that is probably why you still have a problem.
No, the first statement in the attribut handler is return NULL_TREE, so it
can not create a type.

I added to the i386 version the following code (using a unmodified gcc for the 
rest):
[EMAIL PROTECTED]:/tmp/gcc/gcc]$cvs diff -u config/i386/i386.c
Index: config/i386/i386.c
===
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.808
diff -u -r1.808 i386.c
--- config/i386/i386.c  12 Apr 2005 01:46:28 -  1.808
+++ config/i386/i386.c  16 Apr 2005 12:37:52 -
@@ -1608,9 +1608,19 @@
 #endif
 }


+
+static tree
+m68hc05_handle_eeprom_attribute (tree * node, tree name,
+tree args ATTRIBUTE_UNUSED,
+int flags ATTRIBUTE_UNUSED,
+bool * no_add_attrs)
+{
+  return NULL_TREE;
+}
 /* Table of valid machine attributes.  */
 const struct attribute_spec ix86_attribute_table[] =
 {
+  {"eeprom", 0, 0, false, true, false, m68hc05_handle_eeprom_attribute},
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   /* Stdcall attribute says callee is responsible for popping arguments
  if they are not variable.  */

This creates a usedless attribute named eeprom, and I think, that this code
should not contain any error.

Then it fails for at the line (the latest CVS version as well as 20050412):
$cat x.c
typedef unsigned char GROUP9_T[3];
typedef GROUP9_T EGROUP9_T __attribute ((eeprom));
$./cc1 --version
GNU C version 4.1.0 20050416 (experimental) (i686-pc-linux-gnu)
compiled by GNU C version 4.1.0 20050302 (experimental).
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
$./cc1 -g x.c
x.c:2: internal compiler error: in modified_type_die, at dwarf2out.c:8362
Please submit a full bug report,
with preprocessed source if appropriate.
See http://gcc.gnu.org/bugs.html> for instructions.

So the problem is in the core or I have defined the attribute in i386.c in a
wrong way. Correct me, if my modification is not allowed or does an other
forbidden thing.

> You mentioned that this works for all types except array types.  Instead 
> of trying to figure out why array types don't work, perhaps you should 
> figure out why other types do work, and then maybe you can understand 
> why array types don't work.
> 
> Looking at this, I see that you have two array types, both with the same 
> typename which points at the same type decl.  It doesn't seem right for 
> two different types to both claim to be the same typedef.  That doesn't 
> seem to be an issue though.

I tried to compare the differences on the modified i386 with the file:
typedef unsigned char uchar;
typedef uchar euchar __attribute ((eeprom));
typedef unsigned char GROUP9_T[3];
typedef GROUP9_T EGROUP9_T __attribute ((eeprom));
The only difference I have noticed, is that GROUP9_T has no TYPE_NAME, but 
uchar has.
type->type.type_main_variant equals type in any case.

typedef usigned char uchar;
(gdb) call debug_tree(type)
  
constant invariant 8>
unit size  constant invariant 1>
align 8 symtab 0 alias set -1 precision 8 min  
max >
(gdb) call debug_tree(type->type.name)
 
unit size 
align 8 symtab 0 alias set -1 precision 8 min  max >
VOID file  line 0
align 1>
(gdb) call debug_tree(type->type.name->decl.result)

(gdb) call debug_tree(type->type.main_variant)
  
constant invariant 8>
unit size  constant invariant 1>
align 8 symtab 0 alias set -1 precision 8 min  
max >


typedef uchar euchar __attribute((eeprom));
(gdb) call debug_tree(type)
  
constant invariant 8>
unit size  constant invariant 1>
align 8 symtab 0 alias set -1
attributes > precision 8 min 
 max >
(gdb) call debug_tree(type->type.name)
 
unit size 
align 8 symtab -1208520444 alias set -1 precision 8 min  max >
asm_written VOID file x1.c line 1
align 1
result  unit size 
align 8 symtab -1208520392 alias set -1 precision 8 min  max >>
(gdb) call debug_tree(type->type.name->decl.result)
  
constant invariant 8>
unit size  constant invariant 1>
align 8 symtab -1208520392 alias set -1 precision 8 min  max >
(gdb) call debug_tree(type->type.main_variant)
  
constant invariant 8>
unit size  constant invariant 1>
align 8 symtab 0 alias set -1
attributes > precision 8 min 
 max >


typedef unsigned char GROUP9_T[3];
(gdb) call debug_tree(t

different address spaces (was Re: internal compiler error at dwarf2out.c:8362)

2005-04-19 Thread Martin Koegler
James E Wilson wrote:
>Björn Haase wrote: 
>>In case that one should not use machine specific atttributes, *is* 
>>there a standard way for GCC how to implement different address spaces? 
>
>Use section attributes to force functions/variables into different sections, 
>and then use linker scripts to place different sections into different address 
>spaces. You can define machine dependent attributes as short-hand for a 
>section 
>attribute, and presumably the eeprom attribute is an example of that.
> 
>The only thing wrong with the eeprom attribute is that it is trying to create 
>its own 
>types. It is not necessary to create new types in order to get variables 
>placed into 
>special sections. There is nothing wrong with the concept of having an eeprom 
>attribute.

Placing variables in a specfic section is only a part of the problem.
With eg. the AVR progmem attribute, the data is only placed in the Flash memory.
If you want to access it, you need to pass the address to function, which
does the read or write operation (The last version, I used was 3.x based, so
this may have change).

I want to accomplish with the eeprom attribute, a transparent access to such 
memory
regions, where for variables, whose type has this attribute, or pointers, which 
point to
a type, which has this attribute, different RTL is generated, which calls these 
functions
implicitly.

This approach is not perfect (assign a pointer having not this attribute to a
pointer having this attribute using a type cast).

For placing variables, I use the section attribute, so I can support multiple
eeprom regions. This is a specific requirement for my project, as some eeprom 
data
must be put in the region 0x100-0x1ff, whereas other data can be but at any 
eeprom
location.

For the AVR port, two such attributes would be needed (eeprom and progmem).

My prototype for the m68hc05 does currently the following (based on GCC 4.1):
* A predicate was created, which checks for MEM expression, if the type, either
in the memory attributes or in the register attributes for (mem:XX (reg:XX 
..)),  
contains the eeprom attribute
*The move expander check, if a operand matches the eeprom predicate. If this is 
true,
a different RTL is generated (in my case a call the the library function).
*All other insns reject such an operand, so I had not to change them
*In set_mem_attributes_minus_bitpos, I always store the expression.
 This has caused for my port no regression. As now a register/memory attribute
 may contain an expression, that is not a DECL, I also had to comment out
 one assertion and add that case to the debug print function:

Index: emit-rtl.c
===
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.436
diff -u -r1.436 emit-rtl.c
--- emit-rtl.c  25 Mar 2005 02:23:57 -  1.436
+++ emit-rtl.c  13 Apr 2005 10:41:34 -
@@ -1420,7 +1420,7 @@

   /* ARRAY_REFs, ARRAY_RANGE_REFs and BIT_FIELD_REFs should already
  have been resolved here.  */
-  gcc_assert (DECL_P (expr1));
+  /* gcc_assert (DECL_P (expr1)); */

   /* Decls with different pointers can't be equal.  */
   return 0;
@@ -1449,6 +1449,9 @@
   if (t == NULL_TREE)
 return;

+  if (expr == NULL_TREE)
+expr = t;
+
   type = TYPE_P (t) ? t : TREE_TYPE (t);
   if (type == error_mark_node)
 return;
Index: print-rtl.c
===
RCS file: /cvs/gcc/gcc/gcc/print-rtl.c,v
retrieving revision 1.121
diff -u -r1.121 print-rtl.c
--- print-rtl.c 3 Apr 2005 10:27:44 -   1.121
+++ print-rtl.c 13 Apr 2005 10:41:34 -
@@ -116,6 +116,10 @@
 }
   else if (TREE_CODE (expr) == RESULT_DECL)
 fputs (" ", outfile);
+  else if (!DECL_P(expr))
+{
+  print_node_brief(outfile,"",expr,0);
+}
   else
 {
   fputc (' ', outfile);

For my test cases, this is working.

mfg Martin Kögler
PS: Please CC me on replies


Re: different address spaces (was Re: internal compiler error at dwarf2out.c:8362)

2005-04-21 Thread Martin Koegler
On Wed, Apr 20, 2005 at 06:42:08PM -0700, James E Wilson wrote:
> Martin Koegler wrote:
> > Placing variables in a specfic section is only a part of the problem.
>
> I am aware of that.  There are already many targets that have special 
> handling for section attributes, that result in different code being 
> generated when a section attribute is present.  Mostly these have to do 
> with generating different kinds of address and/or addressing modes 
> though, and your case sounds more complicated.  Handling different kinds 
> of addresses can be done by setting SYMBOL_REF_FLAGS on a symbol_ref.

I also thought about using the SYMBOL_REF_FLAGS, but this would not have
worked for pointers in all cases.

> >My prototype for the m68hc05 does currently the following (based on GCC 
> >4.1):
> 
> It looks like a reasonable plan.
> 
> It relies on MEM_EXPR always being set, which may not be true.  But if 
> there are places creating MEMs from decls without setting MEM_EXPR, then 
> they probably should be fixed.  MEMs created for things like spills to 
> stack slots may not have MEM_EXPR set, but then they can't possibly have 
> the eeprom attribute either, so that is OK.

This not important for my solution, as the conversation is done while
creating the RTL. After the expand pass, the RTL contains library calls,
instead of the writes to the eeprom. RTL based optimiziations should have
no problem with them. I don't think, that an RTL optimizer can even create a
new store expression to the eeprom, if non is present in the RTL (the library
calls are not recognizable as such a expression).

> >+  if (expr == NULL_TREE)
> >+expr = t;
> 
> This is setting MEM_EXPR to a type.

Yes, this may happen, I should change the code. My RTL expander has even
no problem with only a type in MEM_EXPR.

> I see that this does work by accident, because MEM_EXPR can be either a 
> decl or a COMPONENT_REF, and all of the code that excludes 
> COMPONENT_REFs will also happen to excludes types.
> 
> I don't think it is a good idea in general though.  Overloading a field 
> to have either an expression or a type may result in confusion later.
> 
> Presumably this is only a problem because some MEMs don't have the 
> MEM_EXPR field set, in which case a better solution is to find the 
> places that forget to set it and fix them.

In my test cases, set_mem_attributes_minus_bitpos can be called with eg.
 
unit size 
align 8 symtab 0 alias set 2
attributes > precision 16 min 
 max 
pointer_to_this >

arg 0 
public unsigned HI size  unit size 

align 8 symtab 0 alias set -1>

arg 0 
used unsigned ignored HI file t10.c line 15 size  unit size 
align 8 context 
(reg:HI 27 [ D.1314 ]) chain >
arg 1 >>

as t. Such an expression will not be stored in the original code.
Tree based optimizer create in higher optimization levels statements
like *(y+10)=3; which result in this expression.

So, how to change this function? As a MEM_EXPR may only be a DECL or a 
COMPONENT_REF,
storing a indriect_ref of a plus_expr is also not valid. This is, why I had to 
change
the other functions.

I peronally like to stay for my port at my current solution, until I hit a 
problem
or I find a more compilant way for solving this issue. Storing also types has
the advantage, that even in that case, the replacement will work.

If I would change the code to
if(expr ==NULL_TREE&&INDIRECT_REF_P(t))
expr=t;
I could miss some cases (I have mostly worked on RTL level, so I don't know
what other tree expressions are relevant for me).

mfg Martin Kögler
[EMAIL PROTECTED]



Proposal: GCC core changes for different address spaces

2005-04-23 Thread Martin Koegler
After some discussion, how to create transparent access to different
memory transparently, I propose the following solution:

We change the GCC core to store the type of each memory expression
in the MEM rtx. Backends can use this type information to create a diffent RTL
or output a different assembler instruction. The details, how this is done, is
the choice of the port.
A limitation will be, that some RTL passes change or create memory references 
and
thereby destroy the type attribute.

James E Wilson also wrote, that this type information my help for other 
problems:
>For instance, taking the address of packed data and then
>dereferencing it fails, because we have no way to mark MEMs as pointing
>to packed data.

In GCC, a backend could use this in the following way:
It defines an attribute (eg. eeprom), which is added to variables and types. 
The GCC core keeps in all tree based representation already track of such an 
attribute.
Through the type attribute, this information will be available for machine 
description,
which can use this information to generate different instructions.
A backend may need multiple of such attributes (avr: progmem and eeprom).

For implementing the type attributes, I propose:
Add the field "tree type;" to "struct mem_attrs". This field holds the type, if 
present,
or 0, if no type information is available.

To access it, I propose:
#define MEM_TYPE(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->type)

set_mem_attributes_minus_bitpos will set MEM_TYPE, if it is not already set, so 
the tree to RTL expander adds automatically the type information.

All functions, which copy the memory attributes, will also copy the type 
information.
A function set_mem_type to set the type information will be added.

Open questions are:
*Do we need to print the type information and how verbose in print_rtx?
*What to do, if the reload pass copy the REG_EXPR to a MEM_EXPR 
(set_mem_attrs_from_reg)?
If REG_EXPR, copy the type of REG_EXPR, else keep the old type? Or add type 
information
also to REG_ATTRS?

Before I start experimenting with this, I want other people opinions, how 
acceptable this proposal will be
for GCC mainline or if it can be improved.

A discouraged solution, because it need a change of the interpretation of 
MEM_EXPR, was:
We allow GCC to store in MEM_EXPR not only a DECL or COMPONENT_REF. In the 
case, something
is stored in MEM_EXPR, the type information is present. In any other case, a 
type will be stored in it
(or maybe the full tree expression, which may give additional information to an 
optimizer).
GCC seems to have with this solution no problem, as far as my experiments have 
shown. An asseration
and a missing case in the RTX output need to be changed for my GCC port.

mfg Martin Kögler


Re: Proposal: GCC core changes for different address spaces

2005-04-24 Thread Martin Koegler
On Sat, Apr 23, 2005 at 02:26:54PM -0400, Paul Schlie wrote:
> - sound's good, and a natural generalization of current mem ref attributes.
> 
> (However ideally, function parameter and result value references would need
>  to be similarly qualify-able in order to enable the proper attributes to
>  be associated and enforced when references to such attributed objects are
>  passed-to/returned-from function calls; as otherwise the object's storage
>  reference attribute will be lost; which could in theory could be enabled
>  by allowing the qualification an arbitrary variable, parameter, result
>  storage type reference as a natural extension; thereby allowing the
>  specification of a pointer parameter to a static const value be specified
>  as "(static const)*", as opposed to being parsed as "static (const *) by
>  default which specifies a static pointer parameter which is prohibited,
>  therefore wouldn't introduce an ambiguity if the optionally enabled.)

Function calls and their return values are also represented in the tree 
representation.
There the attributes are available as part of the type representation. Type
compatibility between acutual and formal parameters is also handled by GCC 
front/middle end using the tree representation.

The only point, where some type information about function parameters may be 
missing, is
the call of library functions, which are created by an RTL optimizer. The formal
parameters of a libary call are known. If a RTL expression can be used as an
acutal parameter, is checked by GCC already in some way. 

Can tell me, who you would change the RTL and give an concrete example, 
how to use your changes and what befit they have.

mfg Martin Kögler


Fixing of bug 18877

2005-04-24 Thread Martin Koegler
I discovered an out of bound access in reload.c, which can happen under
certain conditions (bug 18877).

The problem is, that in decompose (reload.c) assumes, that true_regnum
returns only value < 0 for pseudo registers, which is in certain 
situations not true (all available register in use and a "=&rm" constraint
is still in a pseudo register).

The fix is quite simple and was included in the bug report about 4 month ago.
I raised also this issue on gcc-patches 
(http://gcc.gnu.org/ml/gcc-patches/2004-12/msg01390.html),
but the problem still remains in the mainline cvs version.

It can be used to cause a segmentation fault:
Try http://www.auto.tuwien.ac.at/~mkoegler/gcc/t2.c.gz,
it is gziped, because it is about 300k uncompressed(1k compressed).
I tested it with GNU C version 4.1.0 20050416 (experimental) 
(i686-pc-linux-gnu).

Under normal conditions, the bug will cause, that an arbitrary memory
value is used as register count. In my test case, the 
asm volatile("#":"=r"(l1):"r"(l1));
cause, that the pseudo register number of l2 gets so high,
that this memory access will result in a crash.

What can I do, to get the fix in the CVS?

mfg Martin Kögler
[EMAIL PROTECTED]


Propagating attributes for to structure elements (needed for different address spaces)

2005-04-25 Thread Martin Koegler
My current aproach, checking for the eeprom attribute in the GCC calculated 
types,
is not sufficient in some situations:
struct y1 {
int x;
};
struct x {
struct y1 y;
};
typedef struct x ax __attribute__ ((eeprom));
void test1(ax* x)
{
x->y.x=1;
}
In this case, while expanding x->y.x=1, the type of x->y is integer.
Even the expression, which the MEM_EXPR gets, contains not the information,
that the eeprom attribute is present. Similar problems occure, if pointers
to elements of structures (or pointer to array elements) are used.

The solution would be to add also for the base type of an array the eeprom 
attribute.
Additonally all elements of structures and unions must also have the eeprom 
attribute added.

As this is quite complicated to handle for a programmer, I tried to do this 
automatically
in the attribute handler:
static tree
m68hc05_handle_eeprom_attribute (tree * node, tree name,
 tree args ATTRIBUTE_UNUSED,
 int flags ATTRIBUTE_UNUSED,
 bool * no_add_attrs)
{
  gcc_assert(TYPE_P(*node));

  tree* type = (node);
  tree attr = tree_cons (name, args, NULL_TREE);
  tree* field;
  switch(TREE_CODE(*type))
{
case ARRAY_TYPE:
  *type=copy_node(*type);
  decl_attributes(&TREE_TYPE(*type),attr,0);
  break;
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
  *type=copy_node(*type);
  for (field = &TYPE_FIELDS (*type); *field; field = &TREE_CHAIN (*field))
{
  decl_attributes(field,attr,0);
}
}

  return NULL_TREE;
}
This code is not correct, as it does not handle a lot of side effects and 
problems.
If I neglect the problems (DWARF-2 output totally broken, pointer type 
warnings,...), it
makes GCC pass the type information with the neccessary attribute information to
the RTL expanders.

Another alternative would be to implement backend specific qualifiers (like 
volatile) in the tree representation.
This would need large changes in GCC (at each location, where a new tree 
expression is created, these qualifiers
would also need to be set).

Any better ideas, how to solve this?

mfg Martin Kögler


Re: Propagating attributes for to structure elements (needed for different address spaces)

2005-04-25 Thread Martin Koegler
On Mon, Apr 25, 2005 at 03:22:31PM +, Joseph S. Myers wrote:
> On Mon, 25 Apr 2005, Martin Koegler wrote:
> 
> > The solution would be to add also for the base type of an array the 
> > eeprom attribute. Additonally all elements of structures and unions must 
> > also have the eeprom attribute added.
> 
> The solution is to implement DTR18037 named address spaces.  Naturally 
> such implementation involves implementing the proper semantics for the 
> types of structure element references.

As I don't know DTR18037 and have no access to it (even Google finds nothing 
useable about it), I
cannot say something about it.

I intend to create different address spaces in GCC using attributes, with only 
small changes in the core.
As I test my ideas on my m68hc05 port, I describe my intended semantics using 
it,
which is (apart for the problem with the incorrect types) already working:


// shortcut for the attribute to write more compact
#define E __attribute__ ((eeprom))

// An integer in the eeprom
// for my port, I do the section selection using an other attribute
int x E;

typedef int eint E;
struct x{
int x;
int y;
}
struct y{
int x;
struct x y;
}
typedef struct y ey E;

struct y z E;
struct y z1;
int a[5] E;

eint* a1;
int* a2;
int tmp;

tmp=z.y.x; //do a load from the eeprom, in my case the same as a normal load
z.y.x=2; //do a store to the eeprom

a2=&z.y.x; //assignment of incompatible pointers
*a2=1; //undefined

a1=&z.y.x; 
*a1=1; // write to eeprom at z.y.x

a[2]=1; // write to eeprom
a1=a+1; // ok
*a1=3; // write to a[1] in eeprom
a2=a+1 //assignment of incomatible pointers
*a1=3 //undefined
 
void test(ey* ptr)
{
ptr->x=1; // write to eeprom
}

test(&z); //call test with z -> write 1 to z.x in the eeprom.

z1=z // fails currently with a type error, but this should also work (copy from 
eeprom to z1)

In the case of my port, a read using a normal pointer, which is load from a 
eeprom pointer, will succeed,
in the case of AVR, such a operation will also be undefined.

mfg Martin Kögler
[EMAIL PROTECTED]



different address spaces

2005-04-27 Thread Martin Koegler
I have redone the implementation of the eeprom attribute in my prototype.
It is now a cleaner solution, but requires larger changes in the core,
but the changes in the core should not affect any backend/frontend, if
it does not uses them (except a missing case in tree_copy_mem_area, which
will cause an assertion to fail).

The patches are against the CVS of 20050412.

The changes in the core are:
1) MEM_REF_FLAGS introduced 
(http://www.auto.tuwien.ac.at/~mkoegler/gcc/memref.patch)
The flags are stored in u.fld[2].rt_int of MEM.
A new target hook is introduced, which takes an expression, decl or type
and calculates the target specific MEM_REF_FLAGS.

In set_mem_attributes_minus_bitops (as well es set_mem_attr_from reg),
MEM_REF_FLAGS is initialized from the provided expression.

The most relevant diffs are:
Index: rtl.def
===
RCS file: /cvs/gcc/gcc/gcc/rtl.def,v
retrieving revision 1.100
diff -u -r1.100 rtl.def
--- rtl.def 22 Jan 2005 22:48:57 -  1.100
+++ rtl.def 27 Apr 2005 17:46:53 -
@@ -385,8 +385,9 @@

 /* A memory location; operand is the address.  The second operand is the
alias set to which this MEM belongs.  We use `0' instead of `w' for this
-   field so that the field need not be specified in machine descriptions.  */
-DEF_RTL_EXPR(MEM, "mem", "e0", RTX_OBJ)
+   field so that the field need not be specified in machine descriptions.
+   the third the memory flags */
+DEF_RTL_EXPR(MEM, "mem", "e00", RTX_OBJ)

 /* Reference to an assembler label in the code for this function.
The operand is a CODE_LABEL found in the insn chain.
Index: rtl.h
===
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.543
diff -u -r1.543 rtl.h
--- rtl.h   25 Mar 2005 02:23:57 -  1.543
+++ rtl.h   27 Apr 2005 17:46:53 -
@@ -1080,6 +1080,9 @@
in the block and provide defaults if none specified.  */
 #define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1)

+/* A set of flags on a mem */
+#define MEM_REF_FLAGS(RTX) X0INT ((RTX), 2)
+
 /* The register attribute block.  We provide access macros for each value
in the block and provide defaults if none specified.  */
 #define REG_ATTRS(RTX) X0REGATTR (RTX, 2)
Index: target.h
===
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.131
diff -u -r1.131 target.h
--- target.h12 Apr 2005 06:33:23 -  1.131
+++ target.h27 Apr 2005 17:46:53 -
@@ -514,6 +514,9 @@
  to be checked for va_list references.  */
   bool (*stdarg_optimize_hook) (struct stdarg_info *ai, tree lhs, tree rhs);

+  /* extracts MEM_REF_FLAGS out of a tree expression */
+  int (*extract_mem_ref_flags) (tree t);
+
   /* Functions relating to calls - argument passing, returns, etc.  */
   struct calls {
 bool (*promote_function_args) (tree fntype);
Index: emit-rtl.c
===
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.436
diff -u -r1.436 emit-rtl.c
--- emit-rtl.c  25 Mar 2005 02:23:57 -  1.436
+++ emit-rtl.c  27 Apr 2005 17:46:50 -
@@ -1449,6 +1453,8 @@
   if (t == NULL_TREE)
 return;

+  MEM_REF_FLAGS(ref) = targetm.extract_mem_ref_flags (t);
+
   type = TYPE_P (t) ? t : TREE_TYPE (t);
   if (type == error_mark_node)
 return;
@@ -1685,6 +1691,10 @@
 = get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg),
 GEN_INT (REG_OFFSET (reg)),
 MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
+
+  if(REG_EXPR (reg))
+MEM_REF_FLAGS(mem) = targetm.extract_mem_ref_flags (REG_EXPR (reg));
+
 }

 /* Set the alias set of MEM to SET.  */

2) Handling of the eeprom attribute 
(http://www.auto.tuwien.ac.at/~mkoegler/gcc/addr.patch)
As my old solution had too much problem, I tried a clean implementation, which 
provided
something, like in DTR18037.

First a new type for storing memory address spaces was introduced. At the 
moment, it is implemented
as an integer. The value 0 is used as NO_MEM_AREA, which means, that no memory 
has been
assiged. This value is useful for finding missing initialization of a memory 
address space variable.
Value 1 is DEFAULT_MEM_AREA, which is the usually adress space, including stack 
and data segement.
As the memory area is only used in the backend code, the EEPROM address space 
is not defined here.
As I have not changed the parser, the address space is initialized using an 
attribute.

The address space attribute has been adden to the following tree constructs:
*TYPE_MEM_AREA: memory area of the pointer target, for other types unused
*DECL_MEM_AREA: memory area, where a variable is located (used for var_decls)
*EXPR_MEM_AREA: current memory area. Basically it is only needed for 
component_ref, indirect_ref
or an array_ref. As eg. a compound_expr may appear in place of a of a decl, 
such expre

Re: different address spaces

2005-04-28 Thread Martin Koegler
On Thu, Apr 28, 2005 at 12:37:48PM -0400, Paul Schlie wrote:
> > Martin Koegler wrote:
> > I have redone the implementation of the eeprom attribute in my prototype.
> > It is now a cleaner solution, but requires larger changes in the core,
> > but the changes in the core should not affect any backend/frontend, if
> > it does not uses them (except a missing case in tree_copy_mem_area, which
> > will cause an assertion to fail).
> > ...
> > +void
> > +tree_copy_mem_area (tree to, tree from)
> > 
> 
> Alternatively might it make sense to utilize the analogy defined in rtl.h?
> 
>   /* Copy the attributes that apply to memory locations from RHS to LHS.  */
>   #define MEM_COPY_ATTRIBUTES(LHS, RHS)\
> (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS),\
>  MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS),\
>  MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS),\
>  MEM_NOTRAP_P (LHS) = MEM_NOTRAP_P (RHS),\
>  MEM_READONLY_P (LHS) = MEM_READONLY_P (RHS),\
>  MEM_KEEP_ALIAS_SET_P (LHS) = MEM_KEEP_ALIAS_SET_P (RHS),\
>  MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
> 
> As unfortunately GCC already inconsistently maintains and copies attributes
> to memory references, it seems that introducing yet another function to do
> so will only likely introduce more inconsistency.
> 
> Therefore wonder if it may be best to simply define MEM_ATTRS as you have
> done, and then consistently utilize MEM_COPY_ATTRIBUTES to properly copy
> attributes associated with memory references when new ones as may need to
> be constructed (as all effective address optimizations should be doing, as
> otherwise the attributes associated with the original reference will be
> lost). I.e.:
> 
> Instead of: (as occasionally incorrectly done)
>  rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));// some EA
>  emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1)); // lose attribs
>  emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx)); // new EA
> 
> Something like this is necessary:
> 
>  rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));// some EA
>  rtx mem_1 = gen_rtx_MEM (QImode, addr1); // gen mem
>  MEM_COPY_ATTRIBUTES (mem_1, operands[1]);// copy attributes
>  emit_move_insn (tmp_reg_rtx, mem_1); // read value
>  emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx)); // new EA
>
If you want to use the memory attributes after all reload and optimization
passes, GCC will need to be extended with the missing set of the memory
attributes. This is not my goal (I try to provide the correct
MEM_REF_FLAGS for the RTL expand pass with all necessary earlier steps
to get the adress spaces information).

Correcting all this, will be a lot of work. We may not forget the machine 
description,
which can also create MEMs.

I have updated my patch.

For the MEM_AREA for the tree, I have eliminated many explicit set operation
of this attribute (build3_COMPONENT_REF and build4_ARRAY_REF completly).

For certain tree codes, the build{1,2,3,4} automatically generate the correct
value of MEM_AREA out of their parameters. Only for INDIRECT_REF, this is
not possible.

If we want get every time the correct attribues, we need to add a source for
the memory attributes to gen_rtx_MEM. For an automtic generation of the
memory attributes, to few information is in the RTL available.

I have added compatibilty checking for memory areas as well as correct handling 
of
them for ?:.

The new version is at http://www.auto.tuwien.ac.at/~mkoegler/gcc/gcc1.patch

mfg Martin Kögler 


Re: different address spaces

2005-04-28 Thread Martin Koegler
On Thu, Apr 28, 2005 at 03:43:22PM -0400, Paul Schlie wrote:
> > For the MEM_AREA for the tree, I have eliminated many explicit set operation
> > of this attribute (build3_COMPONENT_REF and build4_ARRAY_REF completly).
> > 
> > For certain tree codes, the build{1,2,3,4} automatically generate the 
> > correct
> > value of MEM_AREA out of their parameters. Only for INDIRECT_REF, this is
> > not possible.
> 
> - if the original mem ref attributes derived from their originally enclosed
>   symbol were maintained, any arbitrary type of memory reference would work.

Can an optimizer theoretically not change fundamentally the structure of a 
memory
reference, so that the attributes will not be valid any more?

For adress spaces, the biggest problem can be, if access operations to different
address spaces are joined:

eg:
if(???)
{
REG_1=...;
REG_1+=4;
do((MEM REG_1));
}
else
{
REG_2=...;
REG_2+=4;
do((MEM REG_2));
}
where REG_1 and REG_2 are pointer to different address spaces.

to:
if()
REG_1=...;
else
REG_1=...;
REG_1+=4;
do((MEM REG_1));

to eg. save space.

Even at tree level, such an change could be done by an optimizer,
if he does not take care of the address spaces.

For RTL level, a problem could be, if some information about
eg how the data is packed, would be stored in the memory attributes.

If an optimizer decides, that not the original pointer value is important, but
pointer to an address inside the data would be more useful, then simply
copying the attributes may give a wrong view about the new MEM.

Because of my experiments with GCC, I conclude, that if we want any kind of
attributes (either in tree or RTL), everything, which deal with it, need
to know about all needed side effects, which can be a problem for
backend specific attributes.

Introducing support for named address spaces in GCC would not be a big problem,
it should be no change for non aware backends as frontends. It could be written
in such way, that an bug in this code cause no regression for not address space 
using targets.

The big amount of work will be, to verify that no optimizer will introduce
wrong optimizations.

For my patch, I am still not sure, if I even handle all the MEM_AREA correct 
in all sitations or if I need to add the MEM_AREA to other expression too.

mfg Martin Kögler


Incomplete instatitiation of virtual registers

2005-05-01 Thread Martin Koegler
I notice, that your last change in function.c forgets virtual
registers in the RTL in some conditions. In older version (the last I used was 
20050412),
this has not happend.

In 01.sibling, I have the instruction:
(insn 10 8 12 1 (set (mem/f/i:HI (plus:HI (reg/f:HI 23 virtual-stack-vars)
(const_int -2 [0xfffe])) [0 b+0 S2 A8 ])
(plus:HI (reg/f:HI 23 virtual-stack-vars)
(const_int -6 [0xfffa]))) -1 (nil)
(nil))

In 03.jump, it is replaced with
(insn 10 8 12 1 (set (mem/f/i:HI (plus:HI (reg/f:HI 23 virtual-stack-vars)
(const_int -2 [0xfffe])) [0 b+0 S2 A8 ])
(plus:HI (reg/f:HI 6 VFP)
(const_int -6 [0xfffa]))) 73 {addhi3} (nil)
(nil))

The left virtual-stack-vars causes other problems in the reload pass.

I noticed this in my GCC port, I don't know, if such RTL expressions can
occure in offical versions.

A simple workaround is to rerun the instanication, if anything changes:
Index: function.c
===
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.616
diff -u -p -r1.616 function.c
--- function.c  30 Apr 2005 03:17:53 -  1.616
+++ function.c  1 May 2005 15:11:22 -
@@ -1528,6 +1528,8 @@ instantiate_virtual_regs_in_insn (rtx in
   if (recog_memoized (insn) < 0)
fatal_insn_not_found (insn);
 }
+  if(any_change)
+instantiate_virtual_regs_in_insn (insn);
 }

 /* Subroutine of instantiate_decls.  Given RTL representing a decl,


mfg Martin Kögler


Re: Incomplete instatitiation of virtual registers

2005-05-04 Thread Martin Koegler
On Tue, May 03, 2005 at 05:44:47PM -0700, James E Wilson wrote:
> Martin Koegler wrote:
> >I notice, that your last change in function.c forgets virtual
> >registers in the RTL in some conditions. In older version (the last I used 
> >was 20050412),
> >this has not happend.
> 
> Patches should go to gcc-patches instead of the gcc list.
> 
> If you want us to continue accepting patches from you, then you need to 
> fill out a copyright assignment form.
> 
> Recursively calling instantiate_virtual_regs_in_insn does not look 
> right.  We need a better explanation of what is going wrong here.  Since 
> we don't have a copy of your port, you will have to explain in detail 
> what happens as virtual register instantiation is happening, in order to 
> explain how this occurs.  Normally, we would ask for a testcase, but 
> that won't work in this case.

In that case, I didn't want to get this patch in GCC. In only wanted to
inform, that the code forgets some registers and that a rerun of 
instantiate_virtual_regs_in_insn solves the problem. I don't know, 
if a bug report is ok in such a case (as I have not reproduced it in
a offical version), so I send a mail to Richard Henderson, who did
the last change with CC to the GCC list.

> It is also possible that this is a bug in your port, if you are 
> accidentally emitting the virtual register yourself somehow during or 
> after virtual register instantiation.

I discovered the problem, while running a regression test, after
I have updated the GCC core. Many compilations failed in
refers_to_regno_for_reload_p. It turned out, that the instantiations
forget some registers. Adding the two lines of code, it worked again.

For that instruction, instantiate_virtual_regs_in_insn
enters if(set), then if (GET_CODE (SET_SRC (set)) == PLUS 
is entered, where if (safe_insn_predicate (insn_code, 1, new) is entered.
It then jumps to verify, without changing the destination, because it is
MEM expression. After the verify label, no more change of the destination will 
happen.

As far as I have seen, instantiate_virtual_regs_in_insn is called
for each instruction only once.

Richard Henderson wrote:
> I'd like to see the define_insn for {addhi3}.  I'm a bit confused as
> to how I could have missed iterating over what appears like it ought
> to be match_operand 0.

(define_insn_and_split "addhi3"
[(set (match_operand:HI 0 "regmemptne_operand" "=&rATQ,&rRBU,&rRBU")
  (plus:HI
(match_operand:HI 1 "regmemimmpt_operand" "rATQi,0,rATQI")
(match_operand:HI 2 "regmemimmst_operand" "rRBUi,rRBUi,0")
))]
)


I put the patches and new files for the m68hc05 Port again CVS Versions
of GCC, Binutils, GDB and newlib of 20050501 at:
http://www.auto.tuwien.ac.at/~mkoegler/m68hc05/m68hc05.tar.gz (120k)

It is a development shapshot and requires still a lot of work.
I have some not yet published documenations about the internals of the GCC port 
(predicates, constraints,...),
if it is needed.

Patching and compiling everything, except GCC, is described at
http://www.auto.tuwien.ac.at/~mkoegler/index.php/bcus and nested pages.

For compiling m68hc05-gcc, a patch (gcc.patch) plus the files in 
gcc/config/m68hc05 are needed.
(In addition to config.sub.patch for adding the processor)

mfg Martin Kögler
[EMAIL PROTECTED]



Re: Incomplete instatitiation of virtual registers

2005-05-04 Thread Martin Koegler
On Wed, May 04, 2005 at 01:02:18AM -0700, Richard Henderson wrote:
> On Wed, May 04, 2005 at 09:50:49AM +0200, Martin Koegler wrote:
> > For that instruction, instantiate_virtual_regs_in_insn
> > enters if(set), then if (GET_CODE (SET_SRC (set)) == PLUS 
> > is entered, where if (safe_insn_predicate (insn_code, 1, new) is entered.
> > It then jumps to verify, without changing the destination, because it is
> > MEM expression. After the verify label, no more change of the destination
> > will happen.
> 
> Ah, yes.  Try the following patch.

For the test case, I analyzed, this patch works. I have started a regression 
test.
Will take some time, before I can tell you the final result.

mfg Martin Kögler


Re: Incomplete instatitiation of virtual registers

2005-05-05 Thread Martin Koegler
On Wed, May 04, 2005 at 01:02:18AM -0700, Richard Henderson wrote:
> On Wed, May 04, 2005 at 09:50:49AM +0200, Martin Koegler wrote:
> > For that instruction, instantiate_virtual_regs_in_insn
> > enters if(set), then if (GET_CODE (SET_SRC (set)) == PLUS 
> > is entered, where if (safe_insn_predicate (insn_code, 1, new) is entered.
> > It then jumps to verify, without changing the destination, because it is
> > MEM expression. After the verify label, no more change of the destination
> > will happen.
> 
> Ah, yes.  Try the following patch.

Regression test with this patch has finished without any more problem
related to the change in the register instantiation.

>From my point of view, this patch can be used as fix for my problem.

mfg Martin Kögler


named address spaces (update)

2005-06-29 Thread Martin Koegler
I continued to work on the support for named address spaces in GCC. I
managed to move much of the managing code for the namespace attribute
into the create funtions of tree nodes, so in most cases, only the
language frontends need to assign and check the named address spaces.

I moved to creation of the namespace list to the gen-modes program
(all examples are taken out of my m68hc05 GCC port
http://www.auto.tuwien.ac.at/~mkoegler/index.php/gcc ). A named
address space is allocated with NAMESPACE(name) in the mode definition
file of the port, eg:

NAMESPACE(EEPROM);
NAMESPACE(LORAM);

(I know, that the NAMESPACE is not the correct naming, but named
address space is a bit too long. Any suggestions?)

This will result in the address spaces EEPROMspace and LORAMspace.  By
default the address spaces DEFAULTspace and NONEspace are generated.
DEFAULTspace is the normal memory, NONEspace an invalid address space
to catch errors.

Index: genmodes.c
===
RCS file: /cvs/gcc/gcc/gcc/genmodes.c,v
retrieving revision 1.17
diff -u -r1.17 genmodes.c
--- genmodes.c  1 Jun 2005 02:55:50 -   1.17
+++ genmodes.c  19 Jun 2005 13:02:16 -
@@ -104,6 +104,87 @@
 static struct mode_adjust *adj_alignment;
 static struct mode_adjust *adj_format;
 
+/* named address space */
+struct namespace_data
+{
+  struct namespace_data *next; /* next this class - arbitrary order */
+
+  const char *name;/* printable mode name without suffix */
+  const char *file;/* file and line of definition, */
+  unsigned int line;   /* for error reporting */
+};
+
+static struct namespace_data *namespaces = 0;
+static int n_namespaces = 0;
+static htab_t namespaces_by_name;
+
+/* Utility routines.  */
+static inline struct namespace_data *
+find_namespace (const char *name)
+{
+  struct mode_data key;
+
+  key.name = name;
+  return (struct namespace_data *) htab_find (namespaces_by_name, &key);
+}
+
+static struct namespace_data *
+new_namespace (const char *name,
+  const char *file, unsigned int line)
+{
+  struct namespace_data *m;
+
+  m = find_namespace (name);
+  if (m)
+{
+  error ("%s:%d: duplicate definition of namespace \"%s\"",
+trim_filename (file), line, name);
+  error ("%s:%d: previous definition here", m->file, m->line);
+  return m;
+}
+
+  m = XNEW (struct namespace_data);
+  memset (m, 0, sizeof (struct namespace_data));
+  m->name = name;
+  if (file)
+m->file = trim_filename (file);
+  m->line = line;
+
+  m->next = namespaces;
+  namespaces = m;
+  n_namespaces++;
+
+  *htab_find_slot (namespaces_by_name, m, INSERT) = m;
+  
+  return m;
+}
+
+static hashval_t
+hash_namespace (const void *p)
+{
+  const struct namespace_data *m = (const struct namespace_data *)p;
+  return htab_hash_string (m->name);
+}
+
+static int
+eq_namespace (const void *p, const void *q)
+{
+  const struct namespace_data *a = (const struct namespace_data *)p;
+  const struct namespace_data *b = (const struct namespace_data *)q;
+
+  return !strcmp (a->name, b->name);
+}
+
+#define NAMESPACE(N) make_namespace(#N, __FILE__, __LINE__)
+
+static void
+make_namespace (const char *name,
+   const char *file, unsigned int line)
+{
+  new_namespace (name, file, line);
+}
+
+
 /* Mode class operations.  */
 static enum mode_class
 complex_class (enum mode_class c)
@@ -769,6 +850,7 @@
 {
   int c;
   struct mode_data *m, *first, *last;
+  struct namespace_data *n;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
   HAVE_EXTRA_MODES ? " and " : "",
@@ -827,6 +909,23 @@
 #if 0 /* disabled for backward compatibility, temporary */
   printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const");
 #endif
+
+  puts ("\
+\n\
+enum namespace_type\n{\n");
+
+  for (n = namespaces; n; n = n->next)
+  {
+   int count_;
+   printf ("  %sspace,%n", n->name, &count_);
+   printf ("%*s/* %s:%d */\n", 27 - count_, "",
+trim_filename (n->file), n->line);
+  }
+
+  puts ("\
+  MAX_NAMESPACE,\n\
+  NUM_NAMESPACES = MAX_NAMESPACE\n\
+};\n");
   puts ("\
 \n\
 #endif /* insn-modes.h */");
@@ -866,6 +965,19 @@
 }
 
 static void
+emit_namespace_name (void)
+{
+  struct namespace_data *m;
+
+  print_decl ("char *const", "namespace_name", "NUM_NAMESPACES");
+
+  for (m = namespaces; m; m = m->next)
+printf ("  \"%s\",\n", m->name);
+
+  print_closer ();
+}
+
+static void
 emit_mode_name (void)
 {
   int c;
@@ -1190,6 +1302,7 @@
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
+  emit_namespace_name ();
   emit_mode_class ();
   emit_mode_precision ();
   emit_mode_size ();
@@ -1233,6 +1346,7 @@
 }
 
   modes_by_name = htab_create_alloc (64, hash_mode, eq_mode, 0, xcalloc, free);
+  namespaces_by_name = htab_create_alloc (64, hash_namespace, eq_namespace, 0, 
xcalloc, free);
 
   create_modes ();
   complete_all_modes ();
Index: machmode.de

Re: named address spaces (update)

2005-07-03 Thread Martin Koegler
On Fri, Jul 01, 2005 at 06:49:18PM -0700, James E Wilson wrote:
> Martin Koegler wrote:
> >I continued to work on the support for named address spaces in GCC.
> 
> An possible issue is the effect on gcc memory usage and compile time.  I 
> see you increased the size of MEM rtl which will increase memory usage. 
>  Also, there seem to be a lot of hooks in commonly called functions 
> which may slow down gcc.  Most users won't be happy if gcc gets slower 
> in order to implement an obscure feature that most don't need.  It would 
> be useful to measure the effect on compile time performance, and try to 
> reduce it if it is too much.

Named address spaces will need some bits to store information about them
in the RTL as well as in the tree nodes. I could change the patch, that
it only creates code on target, which support it. But I do not like this
idea, because future enhancements (like support for different sized pointers)
will probably require bigger changes in the core, which will get more difficult,
if only some architectures use it.

If have not done any benchmarks yet, as I am working on improving my m68hc05 GCC
port. I ran the GCC testsuite (only for the C frontend) with my patches on the
i386 frontend and it took about 45 minutes complete on a modern P4 system (I 
have 
not collected more information, so it says nothing).

> It would be helpful if you used -p when running diff.  That includes 
> function names in the output, which makes the patch easier to read. 
> Also, a ChangeLog entry would help.

The next time, I send an update, I will try to produced a better readable patch.

> I see lots of places where you haven't followed the GNU coding
> conventions.  This will matter if you are serious about getting this
> patch into the FSF tree.  Comments need to start with a capital letter
> and end with a period.  Functions must have a comment before them that
> explains what they do, and what their arguments are.  Spaces before open
> parentheses.  Spaces before and after operators like = and !=.

I have not cared about any formating conventions yet, as it is a preview
patch (and the mentioned errors are no technical problem).

Merging this patch will need a backend, which supports it. I do not intend to
try to include my m68hc05 port in the GCC mainline, as I know no (potential) 
user 
base for this port (except my BCU SDK).

So this patch will need an other backend, problably avr, over which it will 
find its way in the GCC CVS.

> namespace means something different in C++.  I don't think it is wise to
> reuse it here.  addressspace or addrspace makes more sense.

In my working tree, I switch to addrspace:
ADDRSPACE (EEPROM, HI);

I also added an information about the minimum pointer size to 
start to work on non Pmode pointer.

> In previous threads, Joseph Myers pointed you at a formal proposal to 
> extend the ISO C language with a similar feature.  Have you looked at 
> this?  If we are adding this feature, it would be best if we followed 
> the standard, instead of inventing our own incompatible extensions.

Yes, I took it as base for the semantics (e.g. showed the need for the addrspace
merge functions).

I have not changed the C frontend to support address space attributes, so the 
specified
syntax is not implemented. Instead I currently use GCC attributes. The 
attribute handlers 
in my backend only set the address space, without allocation variables into a 
specific section
or detecting errors (eg. parameters with EERPOM attribute).

> It isn't clear why you want both decl and type attributes.  If we are 
> doing this right, it seems that it should just be a type attribute (type 
> qualifier?), and then for decls you can get the info from their type.

My first implementation used a GCC type attribute to store the address space
of the current value. I had serveral problems:
* DWARF2 errors on arrays (#21106)
* need to rewrite recursivly each element of type (which my contain structures, 
  unions, ...) if a address space is set
  In http://gcc.gnu.org/ml/gcc/2005-04/msg01438.html, this was rated as bad 
idea.

  If the address space is set, it would be possible, that only the the address 
space
  is only stored in the top level node and every code, which access a part of 
the type,
  would duplicate the subtree and store the correct address space in the new 
top. This would
  require bigger changes, than the current solution.
 
Now, I do not store the address space of variables in the type to
avoid all propagation problems, I had in former implementations.
Only for pointers, I store the address space, the pointer points to, in the 
type.
I do the propagation while creating the different tree expression now (by 
storing the
address space of the result in the expression).

Using this approach, it is not possible to create something like typedef int 
eint __attribute__ (eeprom);

Re: named address spaces (update)

2005-07-10 Thread Martin Koegler
On Thu, Jul 07, 2005 at 09:45:04PM -0400, Paul Schlie wrote:
> James E Wilson writes:
> >> On Sun, 2005-07-03 at 07:31, Martin Koegler wrote:
> >> * need to rewrite recursivly each element of type (which my contain
> >> structures, unions, ...) if a address space is set
> >>   In http://gcc.gnu.org/ml/gcc/2005-04/msg01438.html, this was rated as
> >> bad idea.
> >
> > It is possible I was wrong.  Conceptually, this doesn't seem much
> > different than existing type qualifiers const/volatile, for which case
> > we must already have a solution.  Maybe similar treatment will work for
> > named address spaces?

Address spaces are similar to the const/volatile type qualifier. Const
and volatile flags are present in each tree expression (not only in the type).
For expressions and decls I store them in a similar way.

Only for types, I do not store the address space of the value, as this is the
more complicated way. For each structure, it must be made sure that, that all 
elements
are declared in the same address space. Also the propgation of the address space
from structures to their elements (and subelements) must be done in some way.

Implementing a correct propagation (including the correct handling of the 
variant
handling), will need more time, than I currently have.

> > Otherwise, these answers all seem very reasonable.
> 
> Is there any reasonable solution to the problem which presents itself when
> attempting to pass address space qualified pointers as arguments to, or
> being returned from, a function; as it seems that unless there's a mechanism
> by which "C" can either select overloaded functions as a function of it's
> qualified argument and/or return value types, or automatically generate
> variants of a given function as may be required based upon it's arguments
> memory space designation; it's not clear how named address spaces can be
> truly useful if references to them can't be effectively utilized by
> functions? (but hopefully I'm misunderstanding something)
> 
> For example (for the sake of argument):
> 
> ROM const int = 5;  // which may require a specific load inst to access.
> RAM1 const int = 6; // which may require a different load inst to access.
> RAM2 int;   // which may require yet a different load/store inst.
> 
> RAM2 int* foo(RAM2 int* x, ROM const int* y)
> {
>   *x = *y;   // loads from ROM const int* y.
>return x;
> }
> 
> RAM2 int* foo(RAM2 int* x, RAM1 const int* y)
> {
>   *x = *y;// loads from RAM1 cons int* y.
>return x;
> }
> 
> Which represents only 2 of several possible permutations of
> ROM RAM1 RAM2 address space argument combinations, which seems both
> painful and error prone to have to replicate, and presumes that the
> compiler is capable of resolving their selection at compile time, as
> may be necessary for the correct code generation of unique address
> space argument reference access?

According to my understanding, in C, a parameter can only have one
address space and may not have any overloader variants. So you will 
need different function names to deal with the different address spaces.

In some situations, not all permutations are neccessary, as one address
space may be part of another, in which case it is possible to create the
functions only for the bigger address space.

Overloading (and automatic generation of permutations) will require the
C++ frontend.

mfg Martin Kögler