Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29407 Diskussionen

Possible execution after EXIT and ABORT function

foxtran
Neuer Beitragender III
691Aufrufe

Considering the following code:

subroutine test(stat)
  implicit none
  integer :: stat
  if (stat > 0) call abort()
  if (stat == 42) print *, 'unreachable'
end subroutine test


which is compiled as follows:

ifx test.f90 -O3 -S


In the resulting code (test.S) I see 'unreachable' string, which should not be there since abort() stops program execution.

Looks like https://llvm.org/docs/LangRef.html#unreachable-instruction is not generated after exit/abort calls. error-stop-stmt/stop-stmt do not have this problem. 

Tested with ifx 2025.2.1.

 

0 Kudos
1 Lösung
Steve_Lionel
Geehrter Beitragender III
429Aufrufe

EXIT is a non-standard intrinsic subroutine. Intrinsic means that the compiler knows about it, but there's no requirement that the code generator be aware that it never returns. If you care about such things, use ERROR STOP.

Lösung in ursprünglichem Beitrag anzeigen

8 Antworten
JohnNichols
Geschätzter Beitragender III
634Aufrufe

The compiler has the option that stat < 0 so the first if fails, the second if then checks , it is reached it just takes the false line and then proceeds on. 

Nothing strange. 

andrew_4619
Geehrter Beitragender III
596Aufrufe
You need to read that again John, if unreachable is written as is stated then istat is 42 which is definitely greater than zero.
Shrublet
Anfänger
546Aufrufe

It says the string "unreachable" can be found in the assembler, not that it is written to the screen. Of course the compiler can stick whatever it wants in the assembler so long as the program when executed behave as prescribed by the standard.

Steve_Lionel
Geehrter Beitragender III
514Aufrufe

The compiler has no idea what ABORT does - it's not part of the Fortran language. In this case it's just some procedure defined in a non-intrinsic module.

Steve_Lionel
Geehrter Beitragender III
569Aufrufe

There are a couple of issues here, not the least of which is that you did not provide a complete program. The other major issue is that your code is incorrect.

If I use the following program:

program foo
call test_quiet (42)
end
subroutine test_quiet(stat)
use ifport, only: abort
  implicit none
  integer :: stat
  if (stat > 0) call abort()
  if (stat == 42) print *, 'unreachable'
end subroutine test_quiet

It works as I would expect and delivers:

D:\Projects>t.exe
abort: Fortran Abort Called

and nothing else.  But without the USE IFPORT, as you had, you lose the explicit interface required for omitting an optional argument, and the results are unpredictable (I got an access violation in one scenario.)

foxtran
Neuer Beitragender III
503Aufrufe

> The compiler has no idea what ABORT does - it's not part of the Fortran language.

Yep, it is a compiler extension that requires explicit interface. However, once interface is known, compiler also knows what this routine do and then can insert unreachable after `call ABORT` to avoid generation of PRINT *, 'unreachable' code.

Probably, it is a good idea here to propose a FINAL keyword (or another name) for subroutines that never return control, so compilers will know more about execution of such routines without looking on their implementation.

EXIT is also a compiler extension, however looks like it does not require explicit interface: 
https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2023-2/exit-subroutine.html
which translates to `for_exit@PLT` call. So, it seems to me that `unreachable` may be put after for_exit call to avoid generation of PRINT *, 'unreachable' code. (42 is positive, but any positive number are not possible after non-returning  exit call)
If it had to be `call exit_@PLT`, user would be able to redefine exit routine and insertion of `unreachable` would be dangerous.

The ASM for call exit:

	.file	"test.f90"
	.text
	.globl	test_quiet_
	.p2align	4
	.type	test_quiet_,@function
test_quiet_:
	.cfi_startproc
	pushq	%rbx
	.cfi_def_cfa_offset 16
	subq	$96, %rsp
	.cfi_def_cfa_offset 112
	.cfi_offset %rbx, -16
	movl	(%rdi), %ebx
	testl	%ebx, %ebx
	jle	.LBB0_3
	movl	$__unnamed_1, %edi
	callq	for_exit@PLT            ; <- call exit
	cmpl	$42, %ebx
	jne	.LBB0_3
	movq	$0, 32(%rsp)
	movl	$66616, 12(%rsp)
	movq	$11, 16(%rsp)
	movq	$strlit, 24(%rsp)       ; <- loading of 'unreachable'
	leaq	32(%rsp), %rdi
	movabsq	$2253038970797824, %rdx
	leaq	12(%rsp), %rcx
	leaq	16(%rsp), %r8
	movl	$-1, %esi
	xorl	%eax, %eax
	callq	for_write_seq_lis@PLT
.LBB0_3:
	addq	$96, %rsp
	.cfi_def_cfa_offset 16
	popq	%rbx
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end0:
	.size	test_quiet_, .Lfunc_end0-test_quiet_
	.cfi_endproc

	.type	strlit,@object
	.section	.rodata,"a",@progbits
strlit:
	.ascii	"unreachable"
	.size	strlit, 11

	.type	__unnamed_1,@object
	.section	.rodata.cst4,"aM",@progbits,4
	.p2align	2, 0x0
__unnamed_1:
	.long	0
	.size	__unnamed_1, 4

	.section	".note.GNU-stack","",@progbits

 

Steve_Lionel
Geehrter Beitragender III
430Aufrufe

EXIT is a non-standard intrinsic subroutine. Intrinsic means that the compiler knows about it, but there's no requirement that the code generator be aware that it never returns. If you care about such things, use ERROR STOP.

DavidWhite
Geschätzter Beitragender II
384Aufrufe

It's worth remembering that all ASCII strings are stored in plain text within the executable code.  No good if you're trying to store a password to prevent unauthorised execution of the code!

Antworten