Debugging flang¶
This guide aims at presenting different debugging tools and techniques available in flang.
Invocation and debuggers¶
flang
binary program actually calls flang1
and flang2
, so running gdb or lldb on flang
makes little sense unless you account for this for example by setting follow-fork-mode child
in gdb before starting the process.
It might be easier though to invoke gdb/lldb with flang1
and flang2
instead.
flang1
produces ILM, consumed by flang2
which translates from ILM to ILI and then to LLVM IR assemblies.
Note that you need to pass the -DCMAKE_BUILD_TYPE=Debug
flag to cmake to enable the debugging symbols in the binary.
Debugging output dumps¶
Both flang1
and flang2
are capable of providing a large number of diagnostic outputs. By default they are written into a file ending in .qdbg
in the current working directory. Alternatively you can use debug flag -q,0,1
to redirect the output to standard output.
The flags are enabled by passing -q
or -qq
parameters, always carrying a “flag,value” pair. On flang
invocation level the flags must be specified for either flang1
or flang2
, by specifying “H” or “M” respectively.
See Coding Practices for details of the flang2
flags meanings.
Example 1: print human-readable ILM representation as read by flang2 for further processing:
$ flang -c func.f90 -Mq,0,1 -Mq,4,1
Example 2: print human-readable ILI representation as used internally by flang2:
$ flang -c hello.f90 -Mq,0,1 -Mq,10,2 -Mq,10,1
In the source code these flags are represented by flg.dbg[i]
, where i
is the flag number.
The -qq
parameter causes debug routines to dump human-readable views of various internal data structures. The syntax is:
-qq,<phase_name>,<object_name>
E.g. to dump flang1 AST, one can pass -Hq,0,1 -Hqq,parser,ast
to the compiler, or to dump flang1 symtab, one can pass -Hq,0,1 -Hqq,parser,symtab
to the compiler.
The available phase names are: init, parser, bblock, vectorize, optimize, schedule, assemble, xref, unroll
The available object names are: ast, dtype, std, sstd, stdp, sym, syms, symtab, allsym, stats, area, olddtype, odtype, oldsym, osym, hsym, hsyms, common, commons, nast, stdtree, stdtrees, shape, aux
Note: In case you are passing arguments to flang1
or flang2
directly, you need to skip the “H” or “M” prefix and replace commas with whitespaces. For example, the two commands should give the same debugging output:
flang -Hq,0,1 -Hq,3,8 -Hq,47,1 -Hqq,parser,symtab example.f90
/usr/local/bin/flang1 -q 0 1 -q 3 8 -q 47 1 -qq parser symtab example.f90
flang1 and flang2 command line options¶
As mentioned in Invocation and debuggers, you may often need to run flang1
and flang2
separately in the debugger and thus provide them with all the parameters that a normal flang
invocation would. Unfortunately flang1
and flang2
do not have --help
option, so here is a list of possible options and their functionality. For flang1
:
Flang1 Option |
Explanation |
---|---|
|
source file name (method 1 of 2) |
|
source file name (method 2 of 2) |
|
output .ilm text file name (will contain STB + ILM) |
|
output .stb symbol table text file name (will contain STB only) |
|
output .cmod text file name, collective content of all modules exported by given Fortran source file (note that separate .mod files will be also generated by Flang1!) |
|
output .cmdx text file containing index of exported modules (including offsets in .cmod file where each of the modules begins) |
|
output debug .qdbg text file name, see |
|
optimization level |
|
same as clang’s |
|
same as clang’s |
|
same as clang’s |
|
same as flang’s |
|
magic |
|
magic |
|
magic debug parameter |
|
magic dump parameter |
|
process OpenMP pragmas |
|
process C preprocessor directives in Fortran code
same as clang’s |
|
local variables should have RECURSIVE semantics instead of SAVE semantics (same as recursive/norecursive below); also inhibit special treatment of terminus functions |
|
reduce verbosity of error messages (0 = don’t reduce) |
|
increase verbosity level of error messages |
|
handle HPF (High Performance Fortran) - off by default doesn’t seem to be fully implemented! |
|
enable IPA (inter-procedural analysis), doesn’t seem to do anything, always set to OFF |
|
quad align (round-up size) “unconstrained objects” if sizeof >= 16 |
|
allow free form code |
|
Intel-specific target architecture name |
|
‘:’-separated list of include directories |
|
vectorizer settings (bitmask), doesn’t seem to be examined anywhere in the frontend |
|
be strict about standard, e.g. disallow use of <> instead of /= or .ne. |
|
local variables should have SAVE semantics instead of RECURSIVE semantics (typically used for overriding OpenMP’s default using -Msave) |
|
allow lines up to 132 characters length (instead of 72 characters) |
|
local variables should have RECURSIVE semantics instead of SAVE semantics
(OpenMP’s default, can be forced by |
|
override command line used to invoke the compiler |
And for flang2
:
Flang2 Option |
Explanation |
---|---|
|
source .ilm file name |
|
(the original) Fortran source file name |
|
input .stb symbol table text file name |
|
output .ll LLVM IR text file name |
|
same as clang’s |
|
build host; doesn’t seem to have any use currently |
|
magic |
|
magic |
|
magic debug parameter |
|
magic dump parameter |
|
1 = |
|
increase verbosity level of error messages |
|
force endianness, 0 = little, 1 = big |
|
process OpenMP pragmas |
|
local variables should have RECURSIVE semantics instead of SAVE semantics (same as recursive/norecursive below); also inhibit special treatment of terminus functions |
|
reduce verbosity of error messages (0 = don’t reduce) |
|
quad align (round-up size) “unconstrained objects” if sizeof >= 16 |
|
Intel-specific target architecture name |
|
local variables should have SAVE semantics instead of RECURSIVE semantics (typically used for overriding OpenMP’s default using -Msave) |
|
assembler syntax: 0 = ELF, 1 = COFF |
|
vectorizer settings (bitmask), doesn’t seem to be examined anywhere in the frontend |
|
debug ON/OFF flag |
|
local variables should have RECURSIVE semantics instead of SAVE semantics
(OpenMP’s default, can be forced by |
|
override command line used to invoke the compiler |
xflags¶
Compilers have a number of supported and unsupported switches that are used internal to the compilers. These are referred to as “xflags”. See Other Compiler Switches for details on the available xflags and how to use them.
In the code these flags are represented by flg.x[n]
, where n
is the ID of the flag.