- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can not findany codingproblem, so I decide to create a smaller test case, see if I canreproduce the error. I followed the exact logic in myworking code, but I can not get the error in the test.
For your info, I attached my test here:
file1:
------------
program testproc
use test
call testmesh
stop
end program testproc
file2:
-----------
module mesh
integer, parameter :: ikd = 4
contains
subroutine visit_two_mesh(proc1)
INTERFACE
SUBROUTINE proc1(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
!< [in] subroutine to be called a new element start on either mesh
integer, parameter :: ikd = 4
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER, INTENT(IN) :: lvl
INTEGER, INTENT(IN) :: lvl_dest
INTEGER , INTENT(IN) :: history(:)
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
END SUBROUTINE proc1
END INTERFACE
integer(IKD) :: iel, iel_dest
integer :: lvl, lvl_dest
integer :: hp, hc, ha
logical :: inc
integer :: history(1)
iel = 1
iel_dest = 1
lvl = 0
lvl_dest = 0
hp = 1
hc = 1
ha = 1
inc = .true.
history = 0
call proc1(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
end subroutine visit_two_mesh
end module
file3:
-------------------
module test
use mesh
contains
subroutine testmesh
call visit_two_mesh(myproc)
contains
subroutine myproc(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER, INTENT(IN) :: lvl
INTEGER, INTENT(IN) :: lvl_dest
INTEGER , INTENT(IN) :: history(:)
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
print *, iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history
end subroutine myproc
end subroutine testmesh
end module test
==============
The real error in my larger codehappenswhen visit_two_meshis calling proc1. The debugger says 'history' has Undefined address. Starting from 'lvl_dest', all arguments are wrong. But everything is fine in the test. The compilor options:
/nologo /debug:full /Od /fpp /I"C:\\Program Files\\MPICH2\\include" /I"C:\\works\\Phisics\\INSTANT\\lib\\instant2d\\\\..\\..\\src" /I"C:\\works\\Phisics\\INSTANT\\lib\\instant2d\\\\..\\..\\src\\mesh" /Ddim=2 /warn:all /module:"x64\\Debug\\\\" /object:"x64\\Debug\\\\" /Fd"x64\\Debug\\vc90.pdb" /traceback /check:all /libs:static /threads /dbglibs /c
The options used for the test:
/nologo /debug:full /Od /warn:interfaces /module:"x64\\Debug\\\\" /object:"x64\\Debug\\\\" /Fd"x64\\Debug\\vc90.pdb" /traceback /check:bounds /libs:static /threads /dbglibs /c
In my working code, 'visit_two_mesh' accepts more arguments, but I think it should be irrelavent.
When I set a breakpoint at the print line in the third file in the test, I see the disassembly:
subroutine myproc(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
00000001400011F6 push rbp
00000001400011F7 sub rsp,150h
00000001400011FE lea rbp,[rsp+30h]
0000000140001203 mov qword ptr [rbp+110h],rsi
000000014000120A mov qword ptr [rbp+108h],rbx
0000000140001211 mov qword ptr [rbp+130h],rcx
0000000140001218 mov qword ptr [rbp+138h],rdx
000000014000121F mov qword ptr [rbp+140h],r8
0000000140001226 mov qword ptr [rbp+148h],r9
000000014000122D mov eax,40h
0000000140001232 add rax,qword ptr [rbp+170h]
0000000140001239 mov edx,30h
000000014000123E add rdx,qword ptr [rbp+170h]
0000000140001245 mov rdx,qword ptr [rdx]
0000000140001248 add rdx,qword ptr [rax]
000000014000124B dec rdx
000000014000124E mov qword ptr [rbp+58h],rdx
0000000140001252 mov rax,qword ptr [rbp+58h]
0000000140001256 mov qword ptr [rbp+60h],rax
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER, INTENT(IN) :: lvl
INTEGER, INTENT(IN) :: lvl_dest
INTEGER , INTENT(IN) :: history(:)
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
print *, iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history
The disassembly in my working code however:
SUBROUTINE proc11(iell,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
000000014096A022 push rbp
000000014096A023 sub rsp,0F0h
000000014096A02A lea rbp,[rsp+30h]
000000014096A02F mov qword ptr [rbp+0B0h],rsi
000000014096A036 mov qword ptr [rbp+0A8h],rbx
000000014096A03D mov qword ptr [rbp+0D0h],r10
000000014096A044 mov qword ptr [rbp+0D8h],rcx
000000014096A04B mov qword ptr [rbp+0E0h],rdx
000000014096A052 mov qword ptr [rbp+0E8h],r8
000000014096A059 mov rax,qword ptr [rbp+0D0h]
000000014096A060 mov qword ptr [rbp+70h],rax
000000014096A064 mov eax,40h
000000014096A069 add rax,qword ptr [rbp+118h]
000000014096A070 mov edx,30h
000000014096A075 add rdx,qword ptr [rbp+118h]
000000014096A07C mov rdx,qword ptr [rdx]
000000014096A07F add rdx,qword ptr [rax]
000000014096A082 dec rdx
000000014096A085 mov qword ptr [rbp+78h],rdx
000000014096A089 mov rax,qword ptr [rbp+78h]
000000014096A08D mov qword ptr [rbp+80h],rax
IMPLICIT NONE
INTEGER(IKD), INTENT(IN) :: iell
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER , INTENT(IN) :: lvl
INTEGER , INTENT(IN) :: lvl_dest
INTEGER , INTENT(IN) :: history(:)
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
print *, history
, which is different from the one of the test. Is this normal? Any suggestions for me to remove this run-time error?
Many thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I noticed the following assembly lines are messed up:
000000014096A03D mov qword ptr [rbp+0D0h],r10
000000014096A044 mov qword ptr [rbp+0D8h],rcx
000000014096A04B mov qword ptr [rbp+0E0h],rdx
000000014096A052 mov qword ptr [rbp+0E8h],r8
rcx, rdx, r8 and r9 are storing the addresses of iel, iel_dest, lvl, lvl_dest, but the subroutine is using r8 and r10. What can be the reason for this?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I finally reproduce the error. Change the previous file 2 with the following:
----------------------------
module test
use mesh
implicit none
contains
subroutine testmesh
real(8) :: a(10,10)
call visit_two_mesh(myproc, myproc1)
contains
SUBROUTINE proc0()
IMPLICIT NONE
a = 0.0_8
RETURN
END SUBROUTINE proc0
subroutine myproc(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER, INTENT(IN) :: lvl
INTEGER, INTENT(IN) :: lvl_dest
INTEGER , INTENT(IN) :: history(:)
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
print *, iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history
end subroutine myproc
subroutine myproc1(iel,iel_dest, hp, hc, ha, inc)
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
print *, iel,iel_dest,hp, hc, ha, inc
end subroutine myproc1
end subroutine testmesh
end module test
=============
You will see the error with 12.0.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Essentially, the allocated array in stack caused the error. If I use /Qsave, then the error is gone. I am not sure if this is considered a compiler bug or not.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Would you please ZIP a folder containing the test sources and the solution/project files, or whatever tells me how you build the sources, and attach it to a reply? That way I can be certain of seeing what you are seeing.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
file 1:
===
program testproc
use test
call testmesh
stop
end program testproc
file 2:
====
module mesh
integer, parameter :: ikd = 4
contains
subroutine visit_two_mesh(proc1, proc2)
INTERFACE
SUBROUTINE proc1(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
!< [in] subroutine to be called a new element start on either mesh
integer, parameter :: ikd = 4
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER, INTENT(IN) :: lvl
INTEGER, INTENT(IN) :: lvl_dest
INTEGER , INTENT(IN) :: history(:)
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
END SUBROUTINE proc1
SUBROUTINE proc2(iel,iel_dest, hp, hc, ha, inc)
!< [in] subroutine to be called a new element start on either mesh
integer, parameter :: ikd = 4
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
END SUBROUTINE proc2
END INTERFACE
integer(IKD) :: iel, iel_dest
integer :: lvl, lvl_dest
integer :: hp, hc, ha
logical :: inc
integer :: history(1)
iel = 1
iel_dest = 1
lvl = 0
lvl_dest = 0
hp = 1
hc = 1
ha = 1
inc = .true.
history = 0
call proc2(iel,iel_dest, hp, hc, ha, inc)
call proc1(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
end subroutine visit_two_mesh
end module
file 3:
====
module test
use mesh
implicit none
contains
subroutine testmesh
real(8) :: a(10,10)
!real(8), save :: a(10,10)
call visit_two_mesh(myproc, myproc1)
contains
SUBROUTINE proc0()
IMPLICIT NONE
a = 0.0_8
RETURN
END SUBROUTINE proc0
subroutine myproc(iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history)
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER, INTENT(IN) :: lvl
INTEGER, INTENT(IN) :: lvl_dest
INTEGER , INTENT(IN) :: history(:)
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
print *, iel,iel_dest,lvl,lvl_dest, hp, hc, ha, inc,history
end subroutine myproc
subroutine myproc1(iel,iel_dest, hp, hc, ha, inc)
INTEGER(IKD), INTENT(IN) :: iel
INTEGER(IKD), INTENT(IN) :: iel_dest
INTEGER , INTENT(IN) :: hp
INTEGER , INTENT(IN) :: hc
INTEGER , INTENT(IN) :: ha !
LOGICAL , INTENT(IN) :: inc ! true to indicate a new element on the first mesh starts
print *, iel,iel_dest,hp, hc, ha, inc
end subroutine myproc1
end subroutine testmesh
end module test
If I put save attribute on the auto array a, then the error is fixed. But this does not work for my big code. I also tried to allocate a dynamically, it does not work.
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is an interesting case - it may take me a while to unravel. Changing the declaration of the array simply changes the layout of memory causing random other data to be used for the address which may or may not result in an error. It does not fail on IA-32.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When "proc1" is called back, "proc1" need to be able to see the local varialbes declared in its containing subroutine. I guess the error happens whilethecompiler handles this.
In my working code, when I comment out all statements in "proc1" and use save attribute for a, I can see the arguments are passed correctly with debugger (r8 and r9 are used). Once I add one statement accessing the local data in the containing subroutine, arguments are no longer passed correctly (in this cass, r9 and r10 are used in the assembly).I am desparately wanting a fix of this.
I remembered the code works longbefore, I was using Win32 anyway. I may had a bad memory. I will try Win32 and Linux tomorrow see what will happen.
Best.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I found that there was no problem accessing the host-associated variable. The problem is solely in how the actual arguments are passed to the subroutine, where the first three arguments are passed correctly but after that, positions are offset by one so that the last one picks up garbage. I'm pretty sure that this is related to the way the argument list is "split" on x64 with the first few arguments passed in registers and the rest on the stack. I have escalated this as issue DPD200168169.
I verified that it also fails with the 11.1 compiler on Windows - I haven't tried Linux. It works fine on IA-32 - it's only Intel 64 where the problem appears.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am assigned to work on something else. Please do let me know when you have a fix.
-Yaqi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Has this issue been fixed in update 5 of Composer XE 2011?
Best,
Yaqi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Description
Internal procedures are the same as external procedures, except for the following:
Only the host program unit can use an internal procedure.
An internal procedure has access to host entities by host association; that is, names declared in the host program unit are useable within the internal procedure.
In Fortran 95/90, the name of an internal procedure must not be passed as an argument to another procedure. However, Intel Fortran allows an internal procedure name to be passed as an actual argument to another procedure. (J.D. I assume this means the procedure address can be saved/restored but not called)
An internal procedure must not contain an ENTRY statement.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your interpretation is not correct. Intel Fortran supports passing an internal proxedure as an actual argument and calling the procedure via the argument. For some background on how we do that, see my Doctor Fortran post Think, Thank, Thunk.
I will note that this feature is now standard in Fortran 2008 - we were just ahead of the curve this time...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is loosly reminicient of a C++0x lambda function.
Can you clarify in the IVF documentation the requirement of the host context to persist through the duration of any subsequent use of a contains procedure. Also clarify when (if) a contains procedure recursively calls the host (new context or same context).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It seems to me that it will be tough to document the requirements and limitations as described in Jim's last paragraph, since Fortran is supposed to be agnostic to concepts such as registers, thunks and stacks, and so the documentation will have to avoid using these concepts.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page