> From: Martin Koegler <[EMAIL PROTECTED]> >> 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.
- Yes, I simply observe (below) that only literal/static-const-data pointer qualification need be expressible as an extension to function parameter and result type specifications, without needing to introduce new keyword qualifiers, or alter the semantics of any existing valid program. > 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. - If I understand you correctly, I agree that in-lined function calls may potentially be able resolve an argument's true nature, and treat dereferences to it appropriately but this is likely too restrictive; alternatively there may be some mechanism to attempt to identify the type of reference passed at run-time but likely at a severe loss of efficiency, therefore not likely acceptable. Therefore it seems that the only generally correct and efficient solution is to enable the (static const, i.e. literal) qualification of a pointer, as it represents the only data class which has no standardized way to qualify a pointer parameter as pointing to, because by default a storage class is presumed to be associated with the parameter itself although illegal, not qualifying it (which could be considered a useful and backward compatible extension, thereby enabling function parameter and result type pointers to be qualified as pointing to literal/static-const data which may then be accesses as desired in a target specific way. (which I believe is likely sufficient, see below) > Can tell me, who you would change the RTL and give an concrete example, > how to use your changes and what befit they have. I believe the following need to be supported: - all existing references to static const string literals need to be correctly wrapped in (mem string-cst-ptr) such that MEM_READONLY_P is true as is already the case with all other static-const-data references. (although admittedly I haven't been able to figure out where the root problem is yet.) - optionally enable the C/C++ parser to accept and enforce (static const)* as a function parameter and result type pointer type qualification, thereby all code within the body of the function will wrap all dereferences to it in a (mem ptr) such that MEM_READONLY_P is true. - thereby a target may simply if desired test rtl memory operands i.e. (define_insn "loadqi" [(set (match_operand:QI 0 "register_operand" "") (match_operand:QI 1 "memory_operand" ""))] "" "* return output_loadqi (insn, operands, NULL);" ) const char * output_loadqi (rtx insn, rtx operands[], int *l) { ... if (MEM_READONLY_P (operands[1])) return output_loadqi_rom (rtx insn, operands[0], operands[2]); else return output_loadqi_ram (rtx insn, operands[0], operands[2]); ... } - all code references should already be identifiable as label or function symbol static constant values. - all remaining references represent non-code/static-data-literal data references (which should likely correspondingly always be wrapped in a correctly attributed (mem ...) expression for consistency even when an effective address is computed and stored in a logical register i.e.: (mem (plus (symb ...) (intval ..))) => (mem (reg ...)) not (reg ...). --- (why I believe adding the ability to qualify/enforce static const qualified function parameter and result pointer types is likely sufficient to enable reasonably flexible multiple target architecture support, in addition to rigorously enforcing the wrapping of all pointer references in correspondingly correctly attributed mem references): My impression is that there are 3 fundamental types of memory references: - literal-code (call/goto code-label/ptr) - literal-data (mem static-const-symbol/ptr) - runtime-data (mem non-static-const-symbol/ptr) As such it seems likely sufficient to simply enable the memory reference to these data classes to be identifiable during target specific linking and code generation to enable a broad class of Harvard memory architecture machines to be supported in addition to unified memory Von-Newman machines. Thereby enabling the partitioning of code, static-constant, and runtime allocated data to be all allocated and accessed independently of each other in orthogonal address spaces as may be optimally desired, and/or required. Where although arbitrary target specific storage qualifiers could be enabled to be defined and utilized at the risk of introducing target specific key words into the source code; this seems typically unnecessary as the use of memories as a proxy for a true file system to preserve data beyond the duration of program execution is likely more properly modeled as a logical block, stream, or random accessed backing store accessed through explicit function interface, as typical of EEPROM or FLASH memory subsystems when used in this capacity.