> 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.



Reply via email to