The TDF Token Register

  1. i. Introduction
    1. ii. Background
    2. iii. Token Register Objectives
  2. 1. Naming scheme
  3. 2. Target dependency tokens
    1. 2.1. Integer variety representations
    2. 2.2. Data model representations
    3. 2.3. Struct representations
    4. 2.4. Floating point representations
    5. 2.5. Sign
    6. 2.6. Alignment
  4. 3. Basic mapping tokens
    1. 3.1. C mapping tokens
    2. 3.2. Fortran mapping tokens
  5. 4. TDF Interface tokens
    1. 4.1. Exception handling
    2. 4.2. TDF Diagnostic Specification
    3. 4.3. Accessing variable parameter lists
  6. 5. Language Programming Interfaces
    1. 5.1. The DRA C LPI
    2. 5.2. The DRA C++ LPI
    3. 5.3. The Etnoteam Fortran LPI
  7. 6. Application Programming Interfaces
    1. 6.1. ANSI C standard functions
    2. 6.2. Common exceptional cases

First published .

Revision History

kate

Moved out andfutils to standalone tools.

kate

Moved out andfutils as a standalone package.

DERA

TenDRA 4.1.2 release.

i. Introduction

  1. ii. Background
  2. iii. Token Register Objectives

ii. Background

TDF is an interface used for architecture neutral and programming language neutral representation of program. It is used both within portable language specific compilation systems, and for architecture neutral distribution of compiled programs. For full details see TDF Specification.

TDF tokens offer a general encapsulation and expansion mechanism which allows any implementation detail to be delayed to the most appropriate stage of program translation. This provides a means for encapsulating any target dependencies in a neutral form, with specific implementations defined through standard TDF features. This raises a natural opportunity for well understood sets of TDF tokens to be included along with TDF itself as interface between TDF tools.

This first revision includes additional tokens for accessing variable parameter lists (see §4.3), and a C mapping token to support the optional type long long int.

iii. Token Register Objectives

As TDF tokens may be used to represent any piece of TDF, they may be used to supplement any TDF interface between software tools. However, that raises the issue of control authority for such an interface. In many cases, the interfaces may be considered to “belong” to a particular tool. In other cases, the names and specifications of tokens need to be recorded for common use.

This token register is used to record the names and specifications of tokens which may need to be assumed by more than one software tool. It also defines a naming scheme which should be used consistently to avoid ambiguity between tokens.

Five classes of tokens are identified:

Target dependency tokens

concerned with describing target architecture or translator detail;

Basic mapping tokens

relating general language features to architecture detail;

TDF interface tokens

These may be required to complete the specification of some TDF constructs;

Language Programming Interfaces (LPI)

These may be specific to a particular producer;

Application Programming Interfaces (API)

corresponding to libraries' interfaces.

These classes are discussed separately, in §2 to §6 below.

1. Naming scheme

A flat name space will suffice for TDF token names if producer writers adopt the simple constraints described here. TDF has separate provision for a hierarchic unique naming scheme, but that was intended for a specific purpose that has not yet been realised.

External names for program or application specific tokens should be confined to “simple names”, which we define to mean that they consist only of letters, digits and underscore, the characters allowed in C identifiers. Normally there will be very few such external names, as tokens internal to a single capsule do not require to be named. All other token names will consist of some controlled prefix followed by a simple name, with the prefix identifying the control authority.

For API tokens, the prefix will consist of a sequence of simple names, each followed by a dot, where the first simple name is the name of the API as listed or referred to in §6.

The prefix for producer specific and target dependency tokens will begin and end with characters that distinguish them from the above cases. However, common tools such as DISP, TNC and PL-TDF assume that token names contain only letters, digits, underscore, dot, and/or twiddle.

The following prefixes are currently reserved:

PrefixReservation
~TDF interface tokens as specified in §4 below, and also LPI tokens specific to DRA's C producer.
.~Registered target dependency tokens as specified in §2 below, and basic mapping tokens specified in section §3.
~c.LPI tokens specific to DRA's C++ producer, other than those it shares with the C producer.
.Et~LPI tokens specific to Etnoteam's Fortran77 producer.

2. Target dependency tokens

  1. 2.1. Integer variety representations
    1. 2.1.1. .~rep_var_width
    2. 2.1.2. .~rep_atomic_width
    3. 2.1.3. Floating variety representations
    4. 2.1.4. Non-numeric representations
    5. 2.1.5. Common conversion routines
    6. 2.1.6. .~ptr_to_ptr
    7. 2.1.7. .~ptr_to_int
    8. 2.1.8. .~int_to_ptr
    9. 2.1.9. .~f_to_ptr
    10. 2.1.10. .~ptr_to_f
  2. 2.2. Data model representations
    1. 2.2.1. .~abi_char_width,
      .~abi_short_width,
      .~abi_int_width,
      .~abi_long_width,
      .~abi_longlong_width,
      .~abi_ptr_width
  3. 2.3. Struct representations
    1. 2.3.1. .~abi_min_struct_rep
  4. 2.4. Floating point representations
    1. 2.4.1. .~abi_float_rep,
      .~abi_double_rep,
      .~abi_longdouble_rep
  5. 2.5. Sign
    1. 2.5.1. .~abi_char_is_signed,
      .~abi_bitfield_is_signed
  6. 2.6. Alignment
    1. 2.6.1. .~abi_pv_align

Target dependency tokens provide a common interface to simple constructs where the required detail for any specific architecture can be expressed within TDF, but the detail will be architecture specific. Every installer should have associated with it, a capsule containing the installer specific definitions of all the tokens specificed within §2.

Some of these tokens provide information about the integer and floating point variety representations supported by an installer, in a form that may be used by TDF analysis tools for architecture specific analysis, or by library generation tools when generating an architecture specific version of a library. Other target dependency tokens provide commonly required conversion routines.

It is recommended that these tokens should not be used directly within application programs. They are designed for use within LPI definitions, which can provide a more appropriate interface for applications.

2.1. Integer variety representations

Since TDF specifies integer representations to be twos-complement, the number of bits required to store an integer variety representation fully specifies that representation. The minimum or maximum signed or unsigned integer that can be represented within any variety representation can easily be determined from the number of bits.

2.1.1. .~rep_var_width

w:	NAT
	-> NAT

If w lies within the range of VARIETY sizes supported by the associated installer, rep_var_width(w) will be the number of bits required to store values of VARIETY var_width(b,w), for any BOOL b.

If w is outside the range of VARIETY sizes supported by the associated installer, rep_var_width(w) will be 0.

2.1.2. .~rep_atomic_width

-> NAT

.~rep_atomic_width will be the number of bits required to store values of some VARIETY v such that assign and assign_with_mode are atomic operations if the value assigned has SHAPE integer(v). The TDF specification guarantees existence of such a number.

2.1.3. Floating variety representations

Floating point representations are much more diverse than integers, but we may assume that each installer will support a finite set of distinct representations. For convenience in distinguishing between these representations within architecture specific TDF, the set of distinct representations supported by any specific installer are stated to be ordered into a sequence of non-decreasing memory size. An analysis tool can easily count through this sequence to determine the properties of all supported representations, starting at 1 and using .~rep_fv_width to test for the sequence end.

For all these tokens, unless indicated otherwise, n will lie within the sequence range of supported floating point representations.

2.1.3.1. .~rep_fv
n:	NAT
	-> FLOATING_VARIETY

.~rep_fv(n) will be the FLOATING_VARIETY whose representation is the nth of the sequence of supported floating point representations.

2.1.3.2. .~rep_fv_width
n:	NAT
	-> NAT

If n lies within the sequence range of supported floating point representations, .~rep_fv_width(n) will be the number of bits required to store values of FLOATING_VARIETY .~rep_fv(n).

If n is outside the sequence range of supported floating point representations, .~rep_fv_width(n) will be 0.

2.1.3.3. .~rep_fv_radix
n:	NAT
	-> NAT

.~rep_fv_radix(n) will be the radix used in the representation of values of FLOATING_VARIETY .~rep_fv(n).

2.1.3.4. .~rep_fv_mantissa
n:	NAT
	-> NAT

.~rep_fv_mantissa(n) will be the number of base .~rep_fv_radix(n) digits in the mantissa representation of values of FLOATING_VARIETY .~rep_fv(n).

2.1.3.5. .~rep_fv_min_exp
n:	NAT
	-> NAT

.~rep_fv_min_exp(n) will be the maximum integer m such that (.~rep_fv_radix(n))-m is exactly representable (though not necessarily normalised) by the FLOATING_VARIETY .~rep_fv(n).

2.1.3.6. .~rep_fv_max_exp
n:	NAT
	-> NAT

.~rep_fv_max_exp(n) will be the maximum integer m such that (.~rep_fv_radix(n))m is exactly representable by the FLOATING_VARIETY .~rep_fv( n).

2.1.3.7. .~rep_fv_epsilon
n:	NAT
	-> EXP FLOATING .~rep_fv(n)

.~rep_fv_epsilon(n) will be the smallest strictly positive real x such that (1.0 + x) is exactly representable by the FLOATING_VARIETY .~rep_fv(n).

2.1.3.8. .~rep_fv_min_val
n:	NAT
	-> EXP FLOATING .~rep_fv(n)

.~rep_fv_min_val(n) will be the smallest strictly positive real number that is exactly representable (though not necessarily normalised)) by the FLOATING_VARIETY .~rep_fv(n).

2.1.3.9. .~rep_fv_max_val
n:	NAT
	-> EXP FLOATING .~rep_fv(n)

.~rep_fv_max_val(n) will be the largest real number that is exactly representable by the FLOATING_VARIETY .~rep_fv(n).

2.1.3.10. .~rep_fv_dig
n:	NAT
	-> EXP

.~rep_fv_dig(n) is the number of decimal digits, q, such that any floating point number of FLOATING_VARIETY .~rep_fv(n) with q decimal digits can be rounded into a floating point number (of the same FLOATING_VARIETY) with radix .~rep_fv_radix(n) and back again without change to the q decimal digits.

2.1.3.11. .~rep_fv_max_10_exp
n:	NAT
	-> EXP

.~rep_fv_max_10_exp(n) is the maximum integer such that 10 raised to that power is in the range of representable finite floating-point numbers for the FLOATING_VARIETY .~rep_fv(n).

2.1.3.12. .~rep_fv_min_norm_val
n:	NAT
	-> EXP

.~rep_fv_min_norm_val(n) is the minimum negative integer such that .~rep_fv_radix(n) raised to that power is a normalized floating-point number for the FLOATING_VARIETY .~rep_fv(n). This is equivalent to .~rep_fv_min_val(n), but for a normalised value.

This is intended to correspond to C's FLT_MIN, DBL_MIN and LDBL_MIN values, but does not include the -1 offset present for those macros.

2.1.4. Non-numeric representations

2.1.4.1. .~ptr_width
-> NAT

.~ptr_width will be the minimum .~rep_var_width(w) for any w such that any pointer to any alignment may be converted to an integer of VARIETY var_width(b,w), for some BOOL b, and back again without loss of information, using the conversions .~ptr_to_int and .~int_to_ptr (q.v.).

2.1.4.2. .~best_div
-> NAT

.~best_div is 1 or 2 to indicate preference for class 1 or class 2 division and modulus (as defined in the TDF Specification). This token would be used in situations where either class is valid but must be used consistently.

2.1.4.3. .~little_endian
-> BOOL

.~little_endian is a property of the relationship between different variety representations and arrays. If an array of a smaller variety can be mapped onto a larger variety, and .~little_endian is true, then smaller indices of the smaller variety array map onto smaller ranges of the larger variety. If .~little_endian is false, no such assertion can be made.

2.1.5. Common conversion routines

This subsection contains a set of conversion routines between values of different shapes, that are not required to have any specific meaning apart from reversability. If the storage space requirements for the two shapes are identical, the conversion can usually be achieved without change of representation. When that is the case, and if the two shapes can be stored at a common alignment, the conversion can simply be achieved by assignment via a common union, which will ensure the required alignment consistency.

2.1.6. .~ptr_to_ptr

a1:	ALIGNMENT
a2:	ALIGNMENT
p:	EXP POINTER(a1)
	-> EXP POINTER(a2)

.~ptr_to_ptr converts pointers from one pointer shape to another.

If p is any pointer with alignment a1, then .~ptr_to_ptr (a2, a1, .~ptr_to_ptr(a1, a2, p)) shall result in the same pointer p, provided that the number of bits required to store a pointer with alignment a2 is not less than that required to store a pointer with alignment a1.

2.1.7. .~ptr_to_int

a:	ALIGNMENT
v:	VARIETY
p:	EXP POINTER(a)
	-> EXP INTEGER(v)

.~ptr_to_int converts a pointer to an integer. The result is undefined if the VARIETY v is insufficient to distinguish between all possible distinct pointers p of alignment a.

2.1.8. .~int_to_ptr

v:	VARIETY
a:	ALIGNMENT
i:	EXP INTEGER(v)
	-> EXP POINTER(a)

.~int_to_ptr converts an integer to a pointer. The result is undefined unless the integer i was obtained without modification from some pointer using .~ptr_to_int with the same variety and alignment arguments.

If p is any pointer with alignment a, and v is var_width(b, .~ptr_width) for some BOOL b, then .~int_to_ptr(v, a, .~ptr_to_int (a, v, p)) shall result in the same pointer p.

2.1.9. .~f_to_ptr

a:	ALIGNMENT
fn:	EXP PROC
	-> EXP POINTER(a)

.~f_to_ptr converts a procedure to a pointer. The result is undefined except as required for consistency with .~ptr_to_f.

2.1.10. .~ptr_to_f

a:	ALIGNMENT
p:	EXP POINTER(a)
	-> EXP PROC

.~ptr_to_f converts a pointer to a procedure. The result is undefined unless the pointer p was obtained without modification from some procedure f using .~f_to_ptr(a, f). The same procedure f is delivered.

2.2. Data model representations

2.2.1. .~abi_char_width,
.~abi_short_width,
.~abi_int_width,
.~abi_long_width,
.~abi_longlong_width,
.~abi_ptr_width

-> NAT

These represent the number of bits for the respectively named sizes belonging to the target machine's data model.

Note that these names (char, short etc.) are not C types; they are the names defined by a data model. These are provided as an abstraction, so that their respective C (and other LPI) tokens such as .~char_width may be mapped to the data model in such a way that the underlying data model may be easily substituted.

2.3. Struct representations

2.3.1. .~abi_min_struct_rep

Minimum struct representation size.

2.4. Floating point representations

2.4.1. .~abi_float_rep,
.~abi_double_rep,
.~abi_longdouble_rep

-> NAT

These represent the sequence number for the respectively named floating point tokens belonging to the target machine's floating point representations.

Note that these names (float, double etc.) are not C types; they are the names defined by a model of floating point representations. These are provided as an abstraction, so that their respective C (and other LPI) tokens such as .~char_width may be mapped to the data model in such a way that the underlying representation may be easily substituted.

The sequence numbers correspond to the values defined under §2.1.3.

2.5. Sign

2.5.1. .~abi_char_is_signed,
.~abi_bitfield_is_signed

-> BOOL

2.6. Alignment

2.6.1. .~abi_pv_align

-> ALIGNMENT

3. Basic mapping tokens

  1. 3.1. C mapping tokens
    1. 3.1.1. .~char_width
    2. 3.1.2. .~short_width
    3. 3.1.3. .~int_width
    4. 3.1.4. .~long_width
    5. 3.1.5. .~longlong_width
    6. 3.1.6. .~size_t_width
    7. 3.1.7. .~fl_rep
    8. 3.1.8. .~dbl_rep
    9. 3.1.9. .~ldbl_rep
    10. 3.1.10. .~pv_align
    11. 3.1.11. .~min_struct_rep
    12. 3.1.12. .~char_is_signed
    13. 3.1.13. .~bitfield_is_signed
  2. 3.2. Fortran mapping tokens
    1. 3.2.1. .~F_char_width
    2. 3.2.2. .~F_int_width
    3. 3.2.3. .~F_fl_rep
    4. 3.2.4. .~F_dbl_rep

Basic mapping tokens provide target specific detail for specific language features that are defined to be target dependent. This detail need not be fixed for a particular target architecture, but needs to provide compatibility with any external library with which an application program is to be linked.

Tokens specific to the C and Fortran language families are included. Like the target dependency tokens, it is again recommended that these tokens should not be used directly within application programs. They are designed for use within LPI definitions, which can provide a more appropriate interface for applications.

Every operating system variant of an installer should have associated with it, a capsule containing the definitions of all the tokens specificed within §3.

3.1. C mapping tokens

3.1.1. .~char_width

 -> NAT

.~char_width is the number of bits required to store values of the representation VARIETY that corresponds to the C type char.

3.1.2. .~short_width

 -> NAT

.~short_width is the number of bits required to store values of the representation VARIETY that corresponds to the C type short int.

3.1.3. .~int_width

 -> NAT

.~int_width is the number of bits required to store values of the representation VARIETY that corresponds to the C type int.

3.1.4. .~long_width

 -> NAT

.~long_width is the number of bits required to store values of the representation VARIETY that corresponds to the C type long int.

3.1.5. .~longlong_width

 -> NAT

.~longlong_width is the number of bits required to store values of the representation VARIETY that corresponds to the C type long long int.

3.1.6. .~size_t_width

 -> NAT

.~size_t_width is the number of bits required to store values of the representation VARIETY that corresponds to the C type size_t. It will be the same as one of .~short_width, .~int_width, or .~long_width.

3.1.7. .~fl_rep

 -> NAT

.~fl_rep is the sequence number (see §2.1.3) of the floating point representation to be used for values of C type float.

3.1.8. .~dbl_rep

 -> NAT

.~dbl_rep is the sequence number (see subsection 3.2) of the floating point representation to be used for values of C type double.

3.1.9. .~ldbl_rep

 -> NAT

.~ldbl_rep is the sequence number (see subsection 3.2) of the floating point representation to be used for values of C type long double.

3.1.10. .~pv_align

 -> ALIGNMENT

.~pv_align is the common alignment for all pointers that can be represented by the C generic pointer type void*. For architecture independence, this would have to be a union of several alignments, but for many installers it can be simplified to alignment(integer(var_width(false, .~char_width))).

3.1.11. .~min_struct_rep

 -> NAT

.~min_struct_rep is the number of bits required to store values of the smallest C integral type which share the same alignment properties as a structured value whose members are all of that same integral type. It will be the same as one of .~char_width, .~short_width, .~int_width, or .~long_width.

3.1.12. .~char_is_signed

 -> BOOL

.~char_is_signed is true if the C type char is treated as signed, or false if it is unsigned.

3.1.13. .~bitfield_is_signed

 -> BOOL

.~bitfield_is_signed is true if bitfield members of structures in C are treated as signed, or false if unsigned.

3.2. Fortran mapping tokens

3.2.1. .~F_char_width

 -> NAT

.~F_char_width is the number of bits required to store values of the representation VARIETY that corresponds to the Fortran77 type CHARACTER.

In most cases, .~F_char_width is the same as .~char_width.

3.2.2. .~F_int_width

 -> NAT

.~F_int_width is the number of bits required to store values of the representation VARIETY that corresponds to the Fortran77 type INTEGER.

In most cases, .~F_int_width is the same as .~int_width.

3.2.3. .~F_fl_rep

 -> NAT

.~F_fl_rep is the sequence number (see §2.1.3) of the floating point representation to be used for values of Fortran77 type REAL, with the constraint that .~rep_fv_width(.~F_fl_rep ) = .~F_int_width.

If this constraint cannot be met, .~F_fl_rep will be 0.

3.2.4. .~F_dbl_rep

 -> NAT

.~F_dbl_rep is the sequence number (see subsection 3.2) of the floating point representation to be used for values of Fortran77 type DOUBLE PRECISION, with the constraint that .~rep_fv_width( .~F_dbl_rep) = 2 * .~F_int_width.

If this constraint cannot be met, .~F_dbl_rep will be 0.

4. TDF Interface tokens

  1. 4.1. Exception handling
    1. 4.1.1. ~Throw
    2. 4.1.2. ~Set_signal_handler
    3. 4.1.3. ~Sync_handler
  2. 4.2. TDF Diagnostic Specification
    1. 4.2.1. ~exp_to_source, ~diag_id_scope, ~diag_type_scope, ~diag_tag_scope
  3. 4.3. Accessing variable parameter lists
    1. 4.3.1. ~va_list
    2. 4.3.2. ~__va_start
    3. 4.3.3. ~va_arg
    4. 4.3.4. ~va_end
    5. 4.3.5. ~next_caller_offset
    6. 4.3.6. ~next_callee_offset

A very few specifically named tokens are referred to within the TDF specification, which are required to complete the ability to use certain TDF constructs. Responsibility for providing appropriate definitions for these tokens is indicated with the specifications below.

Similarly, a few tokens are specified within the TDF Diagnostic Specification.

4.1. Exception handling

4.1.1. ~Throw

n:	NAT
	-> EXP BOTTOM

The EXP e defined as the body of this token will be evaluated on occurrence of any error whose ERROR_TREATMENT is trap. The type of error can be determined within e from the NAT n, which will be error_val(ec) for some ERROR_CODE ec. The token definition body e will typically consist of a long_jump to some previously set exception handler.

Exception handling using trap and ~Throw will usually be determined by producers for languages that specify their own exception handling semantics. Responsibility for the ~Throw token definition will therefore normally rest with producers, by including this token within the producer specific LPI.

4.1.2. ~Set_signal_handler

 -> EXP OFFSET (locals_alignment, locals_alignment)

~Set_signal_handler must be applied before any use of the ERROR_TREATMENT trap, to indicate the need for exception trapping. Responsibility for the ~Set_signal_handler token definition will rest with installers. Responsibility for applying it will normally rest with producers.

The resulting offset value will contain the amount of space beyond any stack limit, which must be reserved for use when handling a stack_overflow trap raised by exceeding that limit.

4.1.3. ~Sync_handler

 -> EXP TOP

~Sync_handler delays subsequent processing until any pending exceptions have been raised, as necessary to synchronise exception handler modification. It must be applied immediately prior to any action that modifies the effect of ~Throw, such as assignment to a variable holding an exception handler as long_jump destination Responsibility for the ~Sync_handler token definition will rest with installers. Responsibility for applying it will normally rest with producers.

4.2. TDF Diagnostic Specification

The TDF Diagnostic Specification is a separate document which describes an extension to TDF, optionally used to provide program diagnostic information that can be transformed by installers to the form required by popular platform-specific debuggers. This extension cannot be considered fully developed and is therefore not included as part of standard TDF. Its use for other than DRA's C producer has not been considered.

4.2.1. ~exp_to_source, ~diag_id_scope, ~diag_type_scope, ~diag_tag_scope

bdy:	EXP
... :	 ...
	-> EXP

Each of these four tokens has several arguments of which the first, bdy, is an EXP. In each case the default definition body, when no diagnostic information is required, is simply bdy. Note that this description is quite sufficient to enable installers to ignore any diagnostic information that may be included in produced TDF, without needing any further knowledge of the TDF Diagnostic Specification.

4.3. Accessing variable parameter lists

Installers should provide token definitions for the tokens listed in this section.

4.3.1. ~va_list

 -> SHAPE

This is the SHAPE of a variable capable of holding state information used for stepping through the anonymous parameters of a procedure created by make_proc.

4.3.2. ~__va_start

p:	EXP POINTER var_param_alignment
	-> EXP ~va_list

If t is the TAG introduced by var_intro OPTION(TAGACC) in make_proc, then the token application ~__va_start(obtain_tag(t)) will provide the initial value for a local variable to be used for stepping through the anonymous parameters of the procedure, starting with the first actual parameter (if any) that does not have a corresponding entry in the make_proc params_intro list.

4.3.3. ~va_arg

v:	EXP POINTER (alignment(~va_list))
s:	SHAPE
	-> EXP s

If v is the variable initialised by ~__va_start (see above), then successive token applications ~va_arg(v,s) will deliver the anonymous parameter values in turn. The successive SHAPEs s must be the appropriate SHAPEs for the successive parameters.

4.3.4. ~va_end

v:	EXP POINTER (alignment(~va_list))
	-> EXP TOP

If v is a variable initialised by ~__va_start, the token application ~va_end(v) indicates that no further use will be made of v.

4.3.5. ~next_caller_offset

o1:	EXP OFFSET (fa,parameter_alignment(s1))
s1:	SHAPE
s2:	SHAPE
	-> EXP OFFSET (fa,parameter_alignment(s2))

~next_caller_offset is used to provide access to successive elements of the caller_params of an apply_general_proc, by delivering successive OFFSETs of their positions relative to the environment pointer created by that procedure application. Both the apply_general_proc and associated make_general_proc will include PROCPROPS var_callers.

o1 will be the OFFSET for a caller_params element of SHAPE s1, and will be derived either from env_offset for a TAG introduced by caller_intro of the make_general_proc , or from a previous application of ~next_caller_offset. s2 will be the SHAPE of the subsequent caller_params element, whose OFFSET is delivered. fa will include the set union of ALIGNMENTs appropriate to the make_general_proc (as specified by current_env).

4.3.6. ~next_callee_offset

o1:	EXP OFFSET (fa,parameter_alignment(s1))
s1:	SHAPE
s2:	SHAPE
	-> EXP OFFSET (fa,parameter_alignment(s2))

~next_callee_offset is used to provide access to successive elements of the CALLEES of an apply_general_proc or tail_call, by delivering successive OFFSETs of their positions relative to the environment pointer created by that procedure application. Both the procedure application and associated make_general_proc will include PROCPROPS var_callees.

o1 will be the OFFSET for a CALLEES element of SHAPE s1, and will be derived either from env_offset for a TAG introduced by callee_intro of the make_general_proc, or from a previous application of ~next_callee_offset. s2 will be the SHAPE of the subsequent CALLEES element, whose OFFSET is delivered. fa will include the set union of ALIGNMENTs appropriate to the make_general_proc (as specified by current_env ).

5. Language Programming Interfaces

  1. 5.1. The DRA C LPI
  2. 5.2. The DRA C++ LPI
  3. 5.3. The Etnoteam Fortran LPI

A Language Programming Interface (LPI) is here defined to mean a set of tokens, usually specific to a particular producer, which will encapsulate language features at a higher level than basic TDF constructs, more convenient for the producer to produce.

Responsibility for the specification of individual LPIs lies with the appropriate producer itself. Before an application can be installed on some target platform, the appropriate LPI token definitions must have been built for that platform. In this sense, the LPI can be considered as a primitive API, which is discussed in §6.

The process by which the LPI token definition library or capsule is generated for any specific platform will vary according to the LPI, and responsibility for defining that process will also lie with the appropriate producer. Some LPIs, such as that associated with DRA's C producer, can be fully defined by architecture neutral TDF, using the tokens specified in §2 and §3 to encapsulate any target dependencies. When that is the case, the generation process can be fully automated. For other LPIs the process may be much less automated. In some cases where the source language implies a complex run-time system, this might even require a small amount of new code to be written for each platform.

Generally, the individual LPI tokens do not need to be specified in the token registry, provided they follow a registered naming scheme to ensure uniqueness (see §1). In exceptional circumstances it may be necessary for some TDF tool to recognise individual LPI tokens explicitly by name. This will be the case when experimenting with potential extensions to TDF, in the field of parallelism for example. In other cases a TDF installer or other tool may recognise an LPI token by name rather than its definition by choice, for some unspecified advantage. We make a pragmatic choice in such cases whether to include such token specifications in the token registry. For widely used producers, we can assume availability of the LPI token specifcations, or standard definitions, separately from the token register, but we should expect any such tokens to be specified within the register for all cases where significant advantage could be taken by an installer only if it recognises the token by name.

5.1. The DRA C LPI

DRA's C producer LPI is defined by an architecture neutral token definition capsule provided with the producer. Target specific detail is included only by use of the target dependency tokens and C mapping tokens specified in §2 and §3.1 respectively. Target specific versions of this capsule are obtained by transformation, using the preprocessing action of the TDF tool tnc, with definitions of the target dependency and C mapping tokens that are provided with the target installer. No special treatment is required for any of the C LPI tokens, though translation time can be slightly improved in a few cases if the names are recognised and standard token definition exercised explicitly within some installers.

The DRA C LPI does not include standard library features, for which the C language requires header files. The standard C library is one example of an API, discussed in §6.

5.2. The DRA C++ LPI

The DRA C++ LPI extends the DRA C LPI adding tokens for target specific C++ features not found in C. Again, standard library features are treated as an API.

5.3. The Etnoteam Fortran LPI

The details in this subsection are provisional, subject to confirmation of argument and result SORTs, and development of model token definitions.

The following tokens are named here in case any installers may be able to produce better code than could be achieved by normal token expansion. In particular, some installers may be able to inline standard function calls.

.Et~SQRTsquare root
.Et~EXPexponential (e ** x)
.Et~LOG(natural) logarithm
.Et~LOG_10base 10 logarithm
.Et~LOG_2base 2 logarithm
.Et~SINsine
.Et~COScosine
.Et~TANtangent
.Et~ASINinverse sine
.Et~ACOSinverse cosine
.Et~ATANinverse (one argument) tangent
.Et~ATAN2inverse (two arguments) tangent, excluding complex
.Et~SINHhyperbolic sine
.Et~COSHhyperbolic cosine
.Et~TANHhyperbolic tangent
.Et~ASINHinverse hyperbolic sine
.Et~ACOSHinverse hyperbolic cosine
.Et~ATANHinverse hyperbolic tangent
.Et~MODfloating point remainder, excluding complex

These tokens apply to any floating variety. This includes complex, unless otherwise stated.

6. Application Programming Interfaces

  1. 6.1. ANSI C standard functions
  2. 6.2. Common exceptional cases
    1. 6.2.1. c89.setjmp.setjmp
    2. 6.2.2. c89.setjmp.longjmp
    3. 6.2.3. ~alloca
    4. 6.2.4. c89.stdarg.va_list,
      c89.stdarg.__va_start,
      c89.stdarg.va_arg,
      c89.stdarg.va_end

Application Programming Interfaces are typically specified with a C mapping, which define the required contents for C header files which a portable C program must include by name to gain access to target specific implementations of an API library. The TDF approach to API specification includes using a #pragma token syntax within architecture neutral C header files, such that all implementation dependencies are encapsulated by API specific tokens. These API tokens are the TDF representation of the API. Both the API library and API token definitions are required before a TDF program using the API can be installed on any particular platform.

Platform specific definitions for API tokens are produced automatically, with few exceptions, for any platform with a conformant implementation of the API. This is achieved by a token library building process which analyses the architecture neutral header files for the API concerned, together with the platform specific header files that provide normal (non-TDF) C access to the API. The few exceptions occur where the platform specific header files have been written to make use of specific C compiler built-in features, typically recognised by identifiers with a prefix such as __builtin_. Such cases are very likely to require explicit recognition of the corresponding token name in TDF installers.

Generally, API token names and specifications are not detailed in this token register. The token specifications are clearly dependent on the associated API specifications. Authority for controlling the actual API token names, and the relationship between API tokens and the various API standardisation authorities, remain separate subjects of discussion.

Names and specifications are given or implied below for those API tokens which frequently require built-in support from installers, and for other cases where an installer may be able to produce better code than could be achieved by normal token expansion, for example by inlining standard function calls.

6.1. ANSI C standard functions

The set of tokens implied below all have the form:

c89.header.function

... :	 ...
	-> EXP

Tokens are defined for all cases where header is ctype or string or math or stdlib, and function is the name of a non-ellipsis function specified in the ANSI C standard library, declared within the corresponding header <header.h>. (Note that ellipsis functions, such as printf, cannot be represented as tokens since they may take a variable number of arguments.)

These tokens have arguments all of SORT EXP, whose number and shape, and token result shape, all correspond to the implementation shape of the named ANSI C standard library function parameters and result. For the few cases where the function is specified not to return (e.g. c89.stdlib.abort), the result shape may be either TOP or BOTTOM.

6.2. Common exceptional cases

6.2.1. c89.setjmp.setjmp

jb:	EXP
	-> EXP

c89.setjmp.setjmp is a token which has the semantics and argument and result implementation shapes corresponding to the ANSI C macro setjmp declared within <setjmp.h>.

6.2.2. c89.setjmp.longjmp

jb:	EXP
v:	EXP
	-> EXP

c89.setjmp.longjmp is a token which has the semantics and argument implementation shapes corresponding to the ANSI C macro longjmp declared within <setjmp.h>. The result shape may be either TOP or BOTTOM.

6.2.3. ~alloca

i:	EXP
	-> EXP

~alloca is a token which has the semantics and argument and result implementation shapes corresponding to the BSD specified function alloca.

6.2.4. c89.stdarg.va_list,
c89.stdarg.__va_start,
c89.stdarg.va_arg,
c89.stdarg.va_end

These four tokens are identical to the Interface Tokens ~va_list, ~__va_start, ~va_arg and ~va_end respectively.