From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25913 invoked by alias); 27 Nov 2006 22:42:10 -0000 Received: (qmail 25902 invoked by uid 22791); 27 Nov 2006 22:42:09 -0000 X-Spam-Check-By: sourceware.org Received: from intrepid.190.195.192.in-addr.arpa (HELO intrepid.intrepid.com) (192.195.190.1) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 27 Nov 2006 22:42:03 +0000 Received: from winnie ([192.195.190.51]) by intrepid.intrepid.com (8.13.8/8.13.8) with ESMTP id kARMHtw3023324 for ; Mon, 27 Nov 2006 14:17:56 -0800 Message-Id: <200611272217.kARMHtw3023324@intrepid.intrepid.com> From: "Gary Funck" To: Subject: how to support C type qualifiers applied to arrays? Date: Mon, 27 Nov 2006 22:42:00 -0000 MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Office Outlook, Build 11.0.5510 X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2006-11/txt/msg00185.txt.bz2 Consider the following: [config: Fedora Core 5, x86_64, gdb 6.3 and GCC 4.1.] % cat -n const_array.c 1 const volatile int array[5] = {1,2,3,4,5}; 2 volatile int s; 3 4 int 5 main() 6 { 7 int i; 8 for (i = 0, s = 0; i < 5; ++i) s += array[i]; 9 } Above, what we'd like to see is that the qualifiers "const" and "volatile" on references to the array named 'array' are known to gdb. Not so: (gdb) ptype s type = volatile int (gdb) ptype array type = int [5] (gdb) ptype array[4] type = int The lack of c-v qualifiers on 'array' above, probably doesn't impact GDB or its users very much at the moment. However, it does impact the development of GDB support for an experimental dialect of "C" called UPC (see http://upc.gwu.edu), which is something that I'm working on at the moment. In UPC a new qualifier, "shared", is added to indicate that a variable is shared across all UPC threads. "shared" can be applied to scalars, arrays, structures and other "C" language objects. Thus, if 'array' above is to be shared, it would be declared: shared int array[5]; Accesses to UPC shared objects cannot generally be implemented as direct loads and stores. The UPC compiler also needs to know that an array indexing operation is being performed on a shared array, because UPC's indexing operation propagates over every thread (A[i+1] may index the data on the next thread in sequence from the thread with affinity to A[i], for example). GDB will need to know about the UPC "shared" qualifier as well so that GDB can properly access UPC shared objects. Extending C-V qualifiers to include other qualifiers within GDB isn't difficult. However, GDB's lack of support for C-V qualifiers on array types is a major obstacle to properly supporting accesses to UPC shared arrays. I'm wondering if anyone has looked at how GDB handles qualifiers on array types and array accesses, or if you can suggest how that might best be supported? ----- The discussion below adds detail, and explores a few alternatives. Running "objdump -W const_array", we can print out the DWARF information. Here is the declaration of "array": <1>: Abbrev Number: 7 (DW_TAG_variable) DW_AT_name : array DW_AT_decl_file : 1 DW_AT_decl_line : 1 DW_AT_type : DW_AT_external : 1 DW_AT_location : 9 byte block: 3 60 8 50 0 0 0 0 0 (DW_OP_addr: 500860) The type definition is at die offset . Following that reference, we see the chain of const and volatile: <1>: Abbrev Number: 8 (DW_TAG_const_type) DW_AT_type : <1>: Abbrev Number: 9 (DW_TAG_volatile_type) DW_AT_type : Where the underlying array type is given by : <1>: Abbrev Number: 5 (DW_TAG_array_type) DW_AT_sibling : DW_AT_type : <9a> <1><9a>: Abbrev Number: 4 (DW_TAG_base_type) DW_AT_name : int DW_AT_byte_size : 4 DW_AT_encoding : 5 (signed) There are two ways of looking at the debugging info. generated above: 1. The DWARF 2 info. accurately reflects the original declaration. 2. The "const" and "volatile" attributes should be propagated to the element type. Thus above, we should have seen the type of "array" (schematically) as: (array_type (domain int 5) (element_type (const (volatile (base_type int))))) ----- A few questions that arise: Q: Is GCC generating an inaccurate DWARF 2 representation to describe a qualified array type, or is GDB not interpreting the DWARF 2 information correctly? Q: Which representation (associating qualifiers with the array or with the array's ultimate element type) most accurately reflects "C" semantics? Due to the large installed GCC installed base (as well as that of other compilers which generate DWARF 2 information in a similar fashion to GCC), we maximize interoperability if we localize the representation issue to GDB, rather than going back to GCC to generate a different Dwarf 2 representation. Taking a look at read_tag_const_type() in dwarf2read.c: static void read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu) { struct type *base_type; if (die->type) { return; } base_type = die_type (die, cu); set_die_type (die, make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0), cu); } We see that make_cv_type() is called to qualify 'base_type' as "const". Make_cv_type() does this by setting a flag bit in the 'instance_flags' field of base_type. In our example above, 'base_type' is an array type. Thus, gdb applies the C-V qualifiers encoded in the DWARF 2 representation to the containing array type, but does not propagate these qualifiers to the element type. ----- In order to make GDB aware that an array type, or an indexed array element is qualified, two approaches come to mind: 1) Encode the fact that the array's elements are C-V qualified by propagating the C-V qualifiers down to the element type. If we know that base_type above isn't otherwise aliased (i.e., linked into some other type chain), we could try something like the following: base_type = die_type (die, cu); if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY) { struct type *final_array_type = type; struct type *final_elem_type TYPE_TARGET_TYPE (final_array_type); /* Propagate qualifiers down to the element type of an array. */ while (TYPE_CODE (final_elem_type) == TYPE_CODE_ARRAY) { final_array_type = final_elem_type; final_elem_type = TYPE_TARGET_TYPE (final_array_type); } final_elem_type = make_cv_type (1, TYPE_VOLATILE (final_elem_type), final_elem_type, 0); TYPE_TARGET_TYPE (final_array_type) = final_elem_type; } else { base_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0); } set_die_type (die, base_type, cu); If make_cv_type() were generalized to accept various qualifier flags, we could place the logic that propagates the C-V qualifiers into this new implementation of make_cv_type(), thus simplifying the callers like read_tag_const_type() above, so that they are unaware of the propagation. 2) Dynamically compute whether and array type or array indexing operation will result in a qualified type. This moves the calculation shown above into GDB's expression evaluation logic. Performing the propagation of type qualifiers in the expression evaluator is further complicated by the fact that the qualifier information will have to be propagated up and down the tree. For example: typedef const int c5_t[5]; typedef volatile c5_t v10_c5_t[10]; v10_c5_t A[20]; if we ask: ) ptype A[10] we'd probably expect to see: volatile const int [10][5] which traverses down the tree, to the element type in order to calculate the final type of the array elements. Thus, we might view the "const" and "volatile" qualifiers as being propagated up the tree to any referencing type or value expression. Similarly, ) ptype A[10][9] should yield volatile const int [5] which propagates the volatile attribute of A[10][9] down the expression tree and combines it with the const qualifier of the c5_t type. ----- I haven't looked at GDB's expression evaluator to determine if the dynamic calculation of the qualifiers is feasible or not. The dynamic calculation method has the advantage that it leaves the symbol readers alone and can also properly handle cross object file references (which are handled via symbolic tag references). I'd appreciate hearing any comments/ideas that you have on this topic, including whether I've properly characterized the problem and the proposed solutions.