Difference between revisions of "Debugging Compiler"

From Free Pascal wiki
Jump to navigationJump to search
(Add simple step-by-step tutorial + extend provided information)
(Add more hints and extend the tutorial)
Line 5: Line 5:
 
# The FPC repository is checked out (same revision as the FPC installation) in another folder and used to work on the compiler, thus the .lpi file is opened from this folder.
 
# The FPC repository is checked out (same revision as the FPC installation) in another folder and used to work on the compiler, thus the .lpi file is opened from this folder.
 
# There are multiple .lpi files for different architectures in the compiler directory to be used with the Lazarus IDE. Open the one which fits your architecture. In this tutorial we're using the <code>ppcx64.lpi</code>.
 
# There are multiple .lpi files for different architectures in the compiler directory to be used with the Lazarus IDE. Open the one which fits your architecture. In this tutorial we're using the <code>ppcx64.lpi</code>.
 +
# Now, if you build the compiler an executable called ''pp'' will be created in the <code>compiler\x86_64</code> folder of your FPC source files (the folder where you opened the .lpi file from). This executable is your new built compiler that can be used to build any other program/unit/project while it is debugged from this Lazarus project.
 
# In the menu bar go to ''Run'' and then click ''Run parameters ...'' to specify the ''Command line parameters''.
 
# In the menu bar go to ''Run'' and then click ''Run parameters ...'' to specify the ''Command line parameters''.
 
#: An example of command line parameters could look like this:
 
#: An example of command line parameters could look like this:
Line 12: Line 13:
 
## <code>-FuD:\Fcpupdeluxe\fpc\units\x86_64-win64\*</code> <- path to the units provided by FPC, otherwise the error ''Fatal: Can't find unit system used by test'' will be shown and an ''ECompilerAbort'' exception in verbose.pas is raised
 
## <code>-FuD:\Fcpupdeluxe\fpc\units\x86_64-win64\*</code> <- path to the units provided by FPC, otherwise the error ''Fatal: Can't find unit system used by test'' will be shown and an ''ECompilerAbort'' exception in verbose.pas is raised
 
# Now you can set breakpoints in Lazarus, e.g. in the <code>parser.compile</code> function and follow the flow of compiling something by using the functionality of Step Over (F8) or Step Into (F7).
 
# Now you can set breakpoints in Lazarus, e.g. in the <code>parser.compile</code> function and follow the flow of compiling something by using the functionality of Step Over (F8) or Step Into (F7).
 +
* Notes:
 +
** If you change any of the compiler source files the ''pp'' executable will be overwritten to reflect the changes made
 +
** The compiled ''pp'' executable can also be used to recompile the RTL (or packages) if needed, e.g. <code>make rtl PP=compiler/x86_64/pp</code>
  
 
==Debugging FPC Hints==
 
==Debugging FPC Hints==
Line 22: Line 26:
  
 
* Another useful procedure in which to place a breakpoint is <code>GenerateError</code> in verbose.pas. It's called for any kind of compilation error (syntax error, type error, assembler reader error, internal error, ...).
 
* Another useful procedure in which to place a breakpoint is <code>GenerateError</code> in verbose.pas. It's called for any kind of compilation error (syntax error, type error, assembler reader error, internal error, ...).
 +
 +
* Steps to investigate internal error codes:
 +
# search for the error code in the source folder (e.g. ''rgrep'' on Linux or ''grep -r'' from the git bash on Windows)
 +
# open the related file and place a break point on the internal error call
 +
# look at the stack trace to see the call history leading up to this point
 +
 +
* Analyse code that leads to an error or warning:
 +
# search for the error/warning code or a short text snippet of the message in the ''compiler/msg'' folder
 +
# the English message will be in ''errore.msg'' file, e.g.:
 +
#: <code>% The constants are out of their allowed range.</code>
 +
#: <code>parser_e_double_caselabel=03037_E_Duplicate case label</code>
 +
# locate the constant name of the message (first part of the message before "="), e.g.:
 +
#: <code>parser_e_double_caselabel</code>
 +
# search for this constant in the compiler source files, example output:
 +
#: <code>nset.pas:                Message(parser_e_double_caselabel);</code>
 +
#: <code>nset.pas:              Message(parser_e_double_caselabel);</code>
  
 
[[Category:FPC]]
 
[[Category:FPC]]

Revision as of 12:48, 12 April 2021

This page is about debugging the FPC compiler and thus it provides a tutorial and some hints that might be useful.

Step-by-step tutorial

  1. There is a FPC installation in D:\Fcpupdeluxe\fpc
  2. The FPC repository is checked out (same revision as the FPC installation) in another folder and used to work on the compiler, thus the .lpi file is opened from this folder.
  3. There are multiple .lpi files for different architectures in the compiler directory to be used with the Lazarus IDE. Open the one which fits your architecture. In this tutorial we're using the ppcx64.lpi.
  4. Now, if you build the compiler an executable called pp will be created in the compiler\x86_64 folder of your FPC source files (the folder where you opened the .lpi file from). This executable is your new built compiler that can be used to build any other program/unit/project while it is debugged from this Lazarus project.
  5. In the menu bar go to Run and then click Run parameters ... to specify the Command line parameters.
    An example of command line parameters could look like this:
    D:\Delphi\tests\test.pas -FuD:\Fcpupdeluxe\fpc\units\x86_64-win64\*
    Explanation of the command line parameters:
    1. D:\Delphi\tests\test.pas <- program or unit that should be compiled
    2. -FuD:\Fcpupdeluxe\fpc\units\x86_64-win64\* <- path to the units provided by FPC, otherwise the error Fatal: Can't find unit system used by test will be shown and an ECompilerAbort exception in verbose.pas is raised
  6. Now you can set breakpoints in Lazarus, e.g. in the parser.compile function and follow the flow of compiling something by using the functionality of Step Over (F8) or Step Into (F7).
  • Notes:
    • If you change any of the compiler source files the pp executable will be overwritten to reflect the changes made
    • The compiled pp executable can also be used to recompile the RTL (or packages) if needed, e.g. make rtl PP=compiler/x86_64/pp

Debugging FPC Hints

  • There are some verbosity options (like gcc) to be specified for the command line to show internal representations like
    • -vp: Write tree.log with parse tree
    • -vv: Write fpcdebug.txt with lots of debugging info
  • Place a breakpoint at the parser.compile function in Lazarus as this is the entry point for parsing.
  • Another useful procedure in which to place a breakpoint is GenerateError in verbose.pas. It's called for any kind of compilation error (syntax error, type error, assembler reader error, internal error, ...).
  • Steps to investigate internal error codes:
  1. search for the error code in the source folder (e.g. rgrep on Linux or grep -r from the git bash on Windows)
  2. open the related file and place a break point on the internal error call
  3. look at the stack trace to see the call history leading up to this point
  • Analyse code that leads to an error or warning:
  1. search for the error/warning code or a short text snippet of the message in the compiler/msg folder
  2. the English message will be in errore.msg file, e.g.:
    % The constants are out of their allowed range.
    parser_e_double_caselabel=03037_E_Duplicate case label
  3. locate the constant name of the message (first part of the message before "="), e.g.:
    parser_e_double_caselabel
  4. search for this constant in the compiler source files, example output:
    nset.pas: Message(parser_e_double_caselabel);
    nset.pas: Message(parser_e_double_caselabel);