internal compiler error at dwarf2out.c:8362
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
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
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)
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)
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
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
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
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)
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)
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
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
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
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
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
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
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
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)
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)
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)
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