Arm Fortran Compiler Language Reference

This topic describes the compatibility of Arm Fortran Compiler (armflang) with the Fortran 77, 90, 95, 2003 and 2008 language standards. It also connects you to information describing the language features, statements, instrinsics, and compiler options supported within Arm Fortran Compiler.

Download as a PDF

This information in this page is available as part of the Arm Fortran Compiler reference guide.

The reference guide is also available in PDF format.

The Arm Fortran Compiler reference guide contains information on the adherence of the Arm Fortran Compiler with the various Fortran standards. It also describes the compatibility with various Fortran language features, statements and intrinsics. In addition, it describes the available compiler options, includes some 'Getting started ' content, and provides information and examples on using some of the compiler features.


Compiler options

Refer to the Compiler options topic for details on the command-line options you can pass to armflang.

You can also view them within the man pages built into the compiler. To view them, use:

man armflang

Fortran data types and file extensions

This topic describes, the data types and file extensions supported by Arm Fortran Compiler.

Data types

Arm Fortran Compiler provides the following intrinsic data types:

 Data Type
 Specified as
 Size (bytes)
 INTEGER  INTEGER
 INTEGER*1 or INTEGER([KIND=]1)
 INTEGER*2 or INTEGER([KIND=]2)
 INTEGER*4 or INTEGER([KIND=]4)
 INTEGER*8 or INTEGER([KIND=]8)
4
1
2
4
8
 REAL  REAL
 REAL*4 or REAL([KIND=]4)
 REAL*8 or REAL([KIND=]8)
4
4
8
DOUBLE PRECISION
 DOUBLE PRECISION
 (same as  REAL*8, no KIND parameter is permitted )
16
 COMPLEX  COMPLEX
 COMPLEX*8 or COMPLEX([KIND=]4)
 COMPLEX*16 or COMPLEX([KIND=]8)
4
8
16
 DOUBLE COMPLEX
 DOUBLE COMPLEX
 (same as COMPLEX*8, no KIND parameter is permitted)
8
 LOGICAL  LOGICAL
 LOGICAL*1 or LOGICAL([KIND=]1)
 LOGICAL*2 or LOGICAL([KIND=]2)
 LOGICAL*4 or LOGICAL([KIND=]4)
 LOGICAL*8 or LOGICAL([KIND=]8)
4
1
2
4
8
 CHARACTER  CHARACTER
 CHARACTER([KIND=]1)
1
1
 BYTE  BYTE
 (same as INTEGER([KIND=]1))
1

Note: The default entries are the first entries for each intrinsic data type.

To determine the kind type parameter of a representation method, use the intrinsic function KIND.

For more portable programs, define a PARAMETER constant using the appropriate SELECTED_INT_KIND or SELECTED_REAL_KIND functions, as appropriate.

For example, this code defines a PARAMETER constant for an INTEGER kind that has 9 digits.:

INTEGER, PARAMETER :: MY_INT_KIND = SELECTED_INT_KIND(9)
...
INTEGER(MY_INT_KIND) :: J
...

File extensions

The extensions .f90, .f95, .f03 and .f08 are used for modern, free-form source code conforming to the Fortran 90, Fortran 95, Fortran 2003, and Fortran 2008 standards.

The .f and .for extensions are typically used for older, fixed-form code such as FORTRAN77.

The extensions .F90, .F95, .F03 and .F08 are used for modern, free-form source code that require preprocessing, and conform to the Fortran 90, Fortran 95, Fortran 2003, and Fortran 2008 standards.

The file extensions that are compatible with Arm Fortran Compiler are listed below:

File Extension

Interpretation

a.out  Executable output file
file.a  Library of object files
file.f
file.for
 Fixed-format Fortran source file
file.fpp
file.F
 Free-format Fortran source file that requires preprocessing
file.f90
file.f95
file.f03
file.f08
 Free-format Fortran source file
file.F90
file.F95
file.F03
file.F08
 Free-format Fortran source file that requires preprocessing
file.o  Compiled object file
file.s  Assembler source file

 

Logical variables and constants

A LOGICAL constant is either true or false. The Fortran standard does not specify how variables of LOGICAL type are represented. However, it does require LOGICAL variables of default kind to have the same storage size as default INTEGER and REAL variables.

For Arm Fortran Compiler:

  • .TRUE. corresponds to -1 and has a default storage size of 4-bytes.

  • .FALSE. corresponds to 0 and has a default storage size of 4-bytes.

Some compilers represent .TRUE. and .FALSE. as 1 and 0, respectively.

C/Fortran inter-language calling

This section provides some useful troubleshooting information when handling argument passing and return values for Fortran functions or subroutines called from C/C++ code.

In Fortran, arguments are passed by reference. Here, reference means the address of the argument is passed, rather than the argument itself. In C/C++, arguments are passed by value, except for strings and arrays, which are passed by reference.

C/C++ provides some flexibility when solving passing difference with Fortran. Usually, intelligent use of the & and * operators in argument passing enables you to call Fortran from C/C++, and in argument declarations when Fortran is calling C/C++.

Fortran functions which return CHARACTER or COMPLEX data types require special consideration when called from C/C++ code.

Character

Fortran functions that return a character require the calling C/C++ function to have two arguments to describe the result:

  1. The first argument provides the address of the returned character.

  2. The second argument provides the length of the returned character.

For example, the Fortran function:

CHARACTER*(*) FUNCTION CHF( C1, I) CHARACTER*(*) C1 INTEGER I END

when called in C/C++, has an extra declaration:

extern void chf_(); char tmp[10]; char c1[9]; int i; chf_(tmp, 10, c1, &i, 9);

The argument, tmp, provides the address, and the length is defined with the second argument, 10.

Notes:

  • Fortran functions declared with a character return length, for example CHARACTER*4 FUNCTION CHF(), still require the second parameter to be supplied to the calling C/C++ code.
  • The value of the character function is not automatically NULL-terminated.

Complex

Fortran functions that return a COMPLEX data type cannot be directly called from C/C++. Instead, a workaround is possible by passing a C/C++ function a pointer to a memory area. This memory area can then be calling the COMPLEX function and storing the returned value.

For example, the Fortran function:

SUBROUTINE INTER_CF(C, I) COMPLEX C COMPLEX CF C = CF(I) RETURN END
COMPLEX FUNCTION CF(I) . . . END

when called in C/C++ is completed using a memory pointer:

extern void inter_cf_(); typedef struct {float real, imag;} cplx; cplx c1; int i; inter_cf_(&c1, &i);

Arm Fortran Compiler implementation notes

Additional information specific to the Arm Fortran Compiler:

  • Arm Fortran Compiler does not initialize arrays or variables with zeros.

    Note: This behavior varies from compiler to compiler and is not defined within Fortran standards. It is best practice to not assume arrays are filled with zeros when created.

 

Fortran statements

The language statements supported by Arm Fortran Compiler are described in our Fortran statement support topic.


Fortran intrinsics

The Fortran instrinsics supported by Arm Fortran Compiler are described in our Fortran intrinsics reference topic.

Directives

Directives are used to provide additional information to the compiler, and to control the compilation of specific code blocks, for example, loops.

For general-purpose directives, you do not need to specify a specific compiler option to enable the directive.

Arm Fortran Compiler supports the general-purpose ivdep directive, and the OpenMP-specific omp simd directive.

For more information on supported OpenMP directives, see the OpenMP support topic.

ivdep

Apply this general-purpose directive to a loop to force the vectorizer to ignore memory dependencies of iterative loops, and proceed with the vectorization.

Syntax

Command-line option:

None

Code:

!dir$ ivdep
<loops>

Parameters

None

Example: Using ivdep

Example usage of the ivdep directive.

Code example:

subroutine sum(myarr1,myarr2,ub)
integer, pointer :: myarr1(:)
integer, pointer :: myarr2(:)
integer :: ub
!dir$ ivdep
do i=1,ub
myarr1(i) = myarr1(i)+myarr2(i)
end do
end subroutine

Command-line invocation:

armflang -O3 <test>.f90 -S -Rpass-missed=loop-vectorize -Rpass=loop-vectorize

Outputs:

  1. With the pragma, the loop given below says the following:

    remark vectorized loop (vectorization width: 2, interleaved count: 1) [-Rpass=loop-vectorize]
  2. Without the pragma, the loop given below says the following:

    remark: loop not vectorized [-Rpass-missed=loop-vectorize]

omp simd

Apply this OpenMP directive to a loop to indicate that the loop can be transformed into a SIMD loop.

Syntax

Command-line option:

-fopenmp

Code:

!$omp simd
<do-loops>

Parameters

None

Example: Using omp simd

Example usage of the omp simd directive.

Code example:

subroutine sum(myarr1,myarr2,myarr3,myarr4,myarr5,ub)
integer, pointer :: myarr1(:)
integer, pointer :: myarr2(:)
integer, pointer :: myarr3(:)
integer, pointer :: myarr4(:)
integer, pointer :: myarr5(:)
integer :: ub

!$omp simd
do i=1,ub
myarr1(i) = myarr2(myarr4(i))+myarr3(myarr5(i))
end do
end subroutine

Command-line invocation:

armflang -O3 -fopenmp <test>.f90 -S -Rpass-missed=loop-vectorize -Rpass=loop-vectorize

Outputs:

  1. With the pragma, the loop given below says the following:

    remark vectorized loop (vectorization width: 2, interleaved count: 1) [-Rpass=loop-vectorize]
  2. Without the pragma, the loop given below says the following:

    remark: loop not vectorized [-Rpass-missed=loop-vectorize]

vector always

Apply this directive to force vectorization of a loop. The directive tells the vectorizer to ignore any potential cost-based implications.

The loop needs to be able to be vectorized.

Syntax

Command-line option:
None

Code:

!dir$ vector always
<loops>

Parameters

None

Example: Using vector always

Example usage of the vector always directive.

Code example:

subroutine add(a,b,c,d,e,ub)
implicit none
integer :: i, ub
integer, dimension(:) :: a, b, c, d, e
!dir$ vector always
do i=1, ub
e(i) = a(c(i)) + b(d(i))
end do
end subroutine add

Command-line invocation:

armflang -O3 <test>.f90 -S -Rpass-missed=loop-vectorize -Rpass=loop-vectorize

Outputs
With the pragma, the output for the example is:

remark: vectorized loop (vectorization width: 4, interleaved count: 1) [-Rpass=loop-vectorize]

Without the pragma, the output for the example is:

remark: the cost-model indicates that vectorization is not beneficial [-Rpass-missed=loop-vectorize]

 

novector

Apply this directive to disable vectorization of a loop.

Use this directive when vectorization would cause a regression instead of an improvement.

Syntax

Command-line option:

None

Code:

!dir$ novector
<loops>

Parameters

None

Example: Using novector

Example usage of the novector directive.

Code example:

subroutine add(arr1,arr2,,arr3,ub)
integer :: arr1(ub), arr2(ub), arr3(ub)
integer :: i
!dir$ novector
do i=1,ub
arr1(i) = arr1(i) + arr2(i)
end do
end subroutine add

Command-line invocation:

armflang -O3 <test>.f90 -S -Rpass-missed=loop-vectorize -Rpass=loop-vectorize

Outputs

With the pragma, the output for the example is:

remark: loop not vectorized [-Rpass-missed=loop-vectorize]

Without the pragma, the output for the example is:

remark: vectorized loop (vectorization width: 4, interleaved count:2)
[-Rpass=loop-vectorize]

 

Standards support

The support status of Arm Fortran Compiler with the Fortran and OpenMP standards.


Related information