From owner-sc22wg5@open-std.org Wed Dec 3 19:33:44 2008 Return-Path: X-Original-To: sc22wg5-dom7 Delivered-To: sc22wg5-dom7@www2.open-std.org Received: by www2.open-std.org (Postfix, from userid 521) id 530BFC56CF8; Wed, 3 Dec 2008 19:33:44 +0100 (CET) X-Original-To: sc22wg5@open-std.org Delivered-To: sc22wg5@open-std.org Received: from ppsw-5.csi.cam.ac.uk (ppsw-5.csi.cam.ac.uk [131.111.8.135]) by www2.open-std.org (Postfix) with ESMTP id 96175C178DC for ; Wed, 3 Dec 2008 19:33:43 +0100 (CET) X-Cam-AntiVirus: no malware found X-Cam-SpamDetails: not scanned X-Cam-ScannerInfo: http://www.cam.ac.uk/cs/email/scanner/ Received: from hermes-1.csi.cam.ac.uk ([131.111.8.51]:46206) by ppsw-5.csi.cam.ac.uk (smtp.hermes.cam.ac.uk [131.111.8.155]:25) with esmtpa (EXTERNAL:nmm1) id 1L7wXe-0003l4-Io (Exim 4.70) for sc22wg5@open-std.org (return-path ); Wed, 03 Dec 2008 18:33:42 +0000 Received: from prayer by hermes-1.csi.cam.ac.uk (hermes.cam.ac.uk) with local (PRAYER:nmm1) id 1L7wXe-0005cE-QP (Exim 4.67) for sc22wg5@open-std.org (return-path ); Wed, 03 Dec 2008 18:33:42 +0000 Received: from [83.67.89.123] by webmail.hermes.cam.ac.uk with HTTP (Prayer-1.3.1); 03 Dec 2008 18:33:42 +0000 Date: 03 Dec 2008 18:33:42 +0000 From: "N.M. Maclaren" To: WG5 Subject: Re: the interoperability TR - an alternative descriptor design Message-ID: In-Reply-To: <49360D4C.1020600@llnl.gov> References: <20081127193527.EF00DC178D9@www2.open-std.org> <20081202130345.82E16C178E1@www2.open-std.org> <49360D4C.1020600@llnl.gov> X-Mailer: Prayer v1.3.1 Mime-Version: 1.0 Content-Type: text/plain; format=flowed; charset=ISO-8859-1 Sender: owner-sc22wg5@open-std.org Precedence: bulk This has been written in haste, as I am away for a month from next Tuesday, and have other work to do! It isn't finished enough for a proposal, but may indicate how I think this should be done. Note that I have implemented something fairly similar (for Algol 68 and Fortran 77), and have seen a fair number of similar designs. C Interoperability - an Alternative Design ------------------------------------------- Note that this is NOT addressing the syntactic extensions proposed in N1761 (i.e. TYPE(*) or DIMENSION(..)), but the actual way that the procedure interface to C is specified. The main point of this is to decouple the implementation from the specification. In particular, it is negligibly more expensive to implement that the mechanism proposed on N1761 and supports all of omitted features I mentioned above. The intention is that it should be potentially extensible to supporting all procedure calls that could reasonably be defined to be interoperable. The only syntactic change is that, for procedures, we extend the BIND attribute: proc-language-binding-spec is BIND(C[,METHOD=binding_method][NAME=scalar-char-initialization-expr]) binding_method is DIRECT or DESCRIPTOR The default is DIRECT, and is what we have at present. For DESCRIPTOR, a procedure called from Fortran is invoked in a processor dependent fashion. If the calling sequences are compatible, it might be called directly; if not, it would be called via a thunking mechanism written in assembler. When the call reaches C, it has the following prototype: void function (const CFI_interface *arguments); Such a function (whether in Fortran or C) is called from C by a processor-provided macro which has a prototype: void CFI_invoke (void (*function)(const CFI_interface *), const CFI_interface *arguments); The arguments include both the result type and the arguments proper, because the C result mechanism is too limited for all of Fortran's features. CFI_interface is a recursive definition, exactly as in Fortran, and so allows any type that can be defined in Fortran. The next section contains a VERY rough draft of a possible specification, described entirely in terms of C; I regret that I do not have time to do better just now. A Possible Interface Type ------------------------- The header is defined as unitary, and all names beginning CFI_ are reserved. I describe it in terms of the structures that C will see when DESCRIPTOR is specified. Note that the actual header will need to use structure and union tags, because C does not support recursive definitions. Also, I have used simple names for fields, for clarity, but they would need prefixing by CFI_ to avoid namespace pollution. This proposal includes the field names in argument lists and derived types. C can't make use of them, though some other languages can, but the real point they are included is for debuggers as companion processors. Note that the attributes are flags - i.e. bits in a mask (with INTENT taking two), and would include flags other than attributes per se. I have allowed for 16 properties per procedure, and 32 'attributes'. Note that the totality of an interface descriptor is constant, and only the data are updatable. Simple uses do not need updatable descriptors, and they are inadequate for complicated ones (e.g. where subcomponents of an argument are copied and changed separately, or if it were extended to support CLASS). In particular, it can be compiled and placed in read-only memory for MODULEs and COMMON - and that is a useful facility. The uintptr_t fields are opaque, and are passed to the auxiliary procedures so that they can access Fortran's internal structures (as is needed for CFI_allocate, CFI_deallocate etc.) The 'pointer' field is zero for arguments that are not ALLOCATABLE or POINTER. typedef struct { uint_least16_t flags; /* PURE, RECURSIVE etc. */ const CFI_descriptor *result; /* NULL for a subroutine */ int arg_count; const CFI_descriptor[] arguments; } CFI_interface; typedef struct { const char *name; /* The name of the argument or field */ int_least16_t type; /* Which member of the union */ int_least16_t subtype; /* CFI_char, CFI_int etc. */ uint_least32_t attributes; /* The attributes */ uintptr_t pointer; /* Also used for ALLOCATABLE */ union { CFI_intrinsic; CFI_array; CFI_derived; CFI_opaque; /* I.e. Not interoperable */ CFI_procedure; CFI_class; /* Currently not proposed */ . . . } type; } CFI_descriptor; typedef struct { int size; /* The storage size in bytes */ void *location; size_t length; /* The length of CHARACTER */ } CFI_intrinsic; typedef struct { int dimensions; /* The number of dimensions */ void *location; /* As in N1761 */ const CFI_descriptor *element; /* Element type descriptor */ const ptrdiff_t bounds[][3]; /* The array bounds and stride */ } CFI_array; The bounds are triples of the lower bound, upper bound and stride, in units of the element size. The upper bound and stride are zero for an unspecified assumed-shape or deferred-shape array; a stride of zero is unambiguous. An assumed-size array could be specified in one of three ways: by an 'attribute' saying that the argument is assumed-size, by providing a last upper-bound derived from its storage size, or by adding an extra ptrdiff_t argument giving its storage size. typedef struct { int fields; /* The number of fields */ void *location; /* As in N1761 */ const CFI_descriptor elements[]; /* Element type descriptors */ } CFI_derived; typedef struct { uintptr_t token; /* Copyable, but nothing else */ } CFI_opaque; typedef CFI_interface CFI_procedure; All of the locations are NULL in the arguments of procedure arguments, of course, and the strides in arrays and length in character may be zero. More work is needed on the precise specification. Regards, Nick Maclaren, University of Cambridge Computing Service, New Museums Site, Pembroke Street, Cambridge CB2 3QH, England. Email: nmm1@cam.ac.uk Tel.: +44 1223 334761 Fax: +44 1223 334679