From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4398 invoked by alias); 14 Aug 2012 01:12:29 -0000 Received: (qmail 4382 invoked by uid 22791); 14 Aug 2012 01:12:27 -0000 X-SWARE-Spam-Status: No, hits=0.3 required=5.0 tests=AWL,BAYES_99,KHOP_THREADED,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from sentry-two.sandia.gov (HELO sentry-two.sandia.gov) (132.175.109.14) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 14 Aug 2012 01:12:12 +0000 X-M-MSG: Received: from interceptor1.sandia.gov (interceptor1.sandia.gov [132.175.109.5]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by sentry-two.sandia.gov (Postfix) with ESMTP id 1DF89D2C2B0; Mon, 13 Aug 2012 19:12:09 -0600 (MDT) Received: from sentry.sandia.gov (sentry.sandia.gov [132.175.109.20]) by interceptor1.sandia.gov (RSA Interceptor); Mon, 13 Aug 2012 19:11:50 -0600 Received: from [132.175.109.4] by sentry.sandia.gov with ESMTP (SMTP Relay 01 (Email Firewall v6.3.2)); Mon, 13 Aug 2012 19:11:44 -0600 X-Server-Uuid: 6BFC7783-7E22-49B4-B610-66D6BE496C0E Received: from mail.ca.sandia.gov (exch06.ran.sandia.gov [134.252.77.2]) by mailgate2.sandia.gov (8.14.4/8.14.4) with ESMTP id q7E1BhOS000606; Mon, 13 Aug 2012 19:11:43 -0600 Received: from EXMB09.srn.sandia.gov ([169.254.2.34]) by EXCH06.srn.sandia.gov ([134.252.77.2]) with mapi id 14.02.0309.002; Mon, 13 Aug 2012 18:11:42 -0700 From: "Rouson, Damian" To: "Tobias Burnus" , "gcc patches" , gfortran , "Alessandro Fanfarillo" cc: "Morris, Karla NMN" Subject: Re: [EXTERNAL] [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine Date: Tue, 14 Aug 2012 01:12:00 -0000 Message-ID: <8BD04F8FCECE2F43BE5F3D8C4EDB452D38CD6139@EXMB09.srn.sandia.gov> In-Reply-To: <50295E1A.5050108@net-b.de> user-agent: Microsoft-MacOutlook/14.13.0.110805 MIME-Version: 1.0 X-TMWD-Spam-Summary: TS=20120814011145; ID=1; SEV=2.3.1; DFV=B2012081401; IFV=NA; AIF=B2012081401; RPD=5.03.0010; ENG=NA; RPDID=7374723D303030312E30413031303230322E35303239413544312E303033383A534346535441543838363133332C73733D312C6667733D30; CAT=NONE; CON=NONE; SIG=AAAAAAAAAAAAAAAAAAAAAAAAfQ== X-MMS-Spam-Filter-ID: B2012081401_5.03.0010 Content-Type: text/plain; charset=iso-8859-1 Content-ID: Content-Transfer-Encoding: quoted-printable X-RSA-Inspected: yes X-RSA-Classifications: Healthcare Dictionaries, public X-RSA-Action: allow Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2012-08/txt/msg00837.txt.bz2 Hi Tobias, Thanks for your work on this. This is a big step. I would add to your list the following: (4) If the entity is of extended type and the parent type has a component that is finalizable, the parent component's component is finalized. In ForTrilnos, we need for this to happen even when the parent is abstract but has a finalizable component. So far, the IBM, NAG, and Cray compilers support this use case and we've had enough dialogue with committee members that I'm confident it's required by the standard, although I can't cite the specific part of the standard that requires it. Please copy my staff member Karla Morris on any replies. Thanks again! Damian On 8/13/12 1:05 PM, "Tobias Burnus" wrote: >Dear all, > >Attached is the first part of a patch which will implement finalization >support and polymorphic freeing in gfortran. > > >It addresses two needs: > >a) For polymorphic ("CLASS") variables, allocatable components have to >be freed; however, at compile time only the allocatable components of >the declared type are known =AD and the dynamic type might have more > >b) Fortran 2003 allows finalization subroutines ("FINAL", destructors), >which can be elemental, scalar or for a given rank (any array type is >allowed). Those should be called for DEALLOCATE, leaving the scope >(unless saved), intrinsic assignment and with intent(out). > > >The finalization is done as follows (F2008, "4.5.6.2 The finalization >process") > >"(1) If the dynamic type of the entity has a final subroutine whose >dummy argument has the same kind type parameters and rank as the entity >being finalized, it is called with the entity as an actual argument. >Otherwise, if there is an elemental final subroutine whose dummy >argument has the same kind type parameters as the entity being >finalized, it is called with the entity as an actual argument. >Otherwise, no subroutine is called at this point. > >"(2) All finalizable components that appear in the type definition are >finalized in a processor-dependent order. If the entity being finalized >is an array, each finalizable component of each element of that entity >is finalized separately. > >"(3) If the entity is of extended type and the parent type is >finalizable, the parent component is finalized." > > >The idea is to create a wrapper function which handles those steps - and >attach a reference to the dynamic type (i.e. add it via proc-pointer to >the vtable). Additionally, the wrapper can be directly called for TYPE. > > >The attached patch implements the generation of the wrapper subroutine; >it does not yet implement the actual calls. The wrapper is generated on >Fortran AST level and creates code similar to > >subroutine final_wrapper_for_type_t (array) >type(t), intent(inout) :: array(..) >integer, pointer :: ptr >integer(c_intptr_t) :: i, addr > >select case (rank (array)) >case (3) >call final_rank3 (array) >case default: >do i =3D 0, size (array)-1 >addr =3D transfer (c_loc (array), addr) + i * STORAGE_SIZE (array) >call c_f_pointer (transfer (addr, c_ptr), ptr) >call elemental_final (ptr) >end do >end select > >! For all noninherited allocatable components, call >! DEALLOCATE(array(:)%comp, stat=3Dignore) >! scalarized as above > >call final_wrapper_of_parent (array(...)%parent) >end subroutine final_wrapper_for_type_t > > >Note 1: The call to the parent type requires packing support for >assumed-rank arrays, which has not yet been implemented (also required >for TS29113, though not for this usage). That is, without further >patches, the wrapper will only work for scalars or if the parent has no >wrapper subroutine. > >Note 2: The next step will be to add the calls to the wrapper, starting >with an explicit DEALLOCATE. > > >I intent to commit the patch, when approved, without allowing FINAL at >resolution time; that way there is no false impression that finalization >actually works. > >Build and regtested on x86-64-gnu-linux. >OK for the trunk? > >* * * > >Note: The patch will break gfortran's OOP ABI. It does so by adding >"_final" to the virtual table (vtab). > >I think breaking the ABI for this functionality is unavoidable. The ABI >change only affects code which uses the CLASS (polymorphic variables) >and the issue only raises if one mixes old with new code for the same >derived type. However, if one does so (e.g. by incomplete >recompilation), segfaults and similar issues will occur. Hence, I am >considering to bump the .mod version; that will effectively force a >recompilation and thus avoid the issue. The down side is that it will >also break packages (e.g. of Linux distributions) which ship .mod files >(sorry!). What do you think? > >I think it could then be combined with Janus' proc-pointer patch, which >changes the assembler name of (non-Bind(C)) procedure pointers, declared >at module level. Again, by forcing recompilation, the .mod version bump >should ensure that users don't see the ABI breakage. His patch is at >http://gcc.gnu.org/ml/fortran/2012-04/msg00033.html (I think is okay, >but I believe it has not yet been reviewed.) > >Tobias > >PS: I used the following test case to test whether the wrapper >generation and scalarization works; it properly prints 11,22,33,44,55,66 >and also the dump looks okay for various versions. > >The scalarization code should work relatively well; there is only one >call to an external function: For SIZE gfortran - for what ever reason - >doesn't generate inline code, but calls libgfortran. > > >But now the test code: > >module m >type tt >end type tt > >type t >! type(tt), allocatable :: comp1 >integer :: val >contains >final bar1 >end type t > >type t1t >! type(tt), allocatable :: comp1 >integer :: val >!contains >! final bar1 >end type t1t > >type, extends(t) :: t2 >type(tt), allocatable :: comp2 >contains >final bar2 >end type t2 > >class(t), allocatable, save :: a >class(t2), allocatable, save :: b > >contains >impure elemental subroutine bar1(x) >! subroutine bar1(x) >type(t), intent(inout) :: x!(:) >print *, 'bar1, ....' >print *, '..........', x%val >end subroutine bar1 >subroutine bar2(y) >type(t2),intent(inout) :: y(:,:) >end subroutine bar2 >end > >use m >use iso_c_binding >type(t1t) ::x(3,2) > >interface >subroutine fini(x) bind(C,name=3D"__m_MOD___final_m_T") >type(*) :: x(..) >end subroutine >end interface > >x%val =3D reshape([11,22,33,44,55,66],shape(x)) >print *, storage_size(x) >call fini(x) >end > > >And one example for a dump: > >__final_m_T (struct array7_t & restrict array) >{ >integer(kind=3D8) idx; >integer(kind=3D8) nelem; >struct t * ptr; > >{ >struct array7_t * D.1977; > >D.1977 =3D (struct array7_t *) array; >nelem =3D (integer(kind=3D8)) (integer(kind=3D4)) _gfortran_size0 (D.1977)= + -1; >} >switch ((integer(kind=3D4)) array->dtype & 7) >{ >default:; >{ >integer(kind=3D8) D.1981; > >D.1981 =3D nelem; >idx =3D 0; >if (idx <=3D D.1981) >{ >while (1) >{ >{ >logical(kind=3D4) D.1991; > >{ >integer(kind=3D8) transfer.3; >integer(kind=3D8) D.1989; >integer(kind=3D8) D.1988; >static integer(kind=3D8) C.1987 =3D 0; >void * D.1986; >void * D.1985; >integer(kind=3D8) D.1984; > >D.1985 =3D (void *) array->data; >D.1986 =3D D.1985; >D.1984 =3D 8; >D.1988 =3D 8; >__builtin_memcpy ((void *) &transfer.3, (void *) &D.1986, MAX_EXPR >, 0>); >ptr =3D (struct t *) (idx * 4 + transfer.3); >} >bar1 (ptr); >L.11:; >D.1991 =3D idx =3D=3D D.1981; >idx =3D idx + 1; >if (D.1991) goto L.12; >} >} >} >L.12:; >} >goto L.9; >} >L.9:; >L.8:; >}