Sign in Join
Wiki copytemporary

Debugging Compiler: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Debugging Compiler

OldNewLine
1+This page is about debugging the FPC compiler and thus it provides a tutorial and some hints that might be useful.
2+
3+## Step-by-step tutorial
4+
5+1. There is a FPC installation in `D:\Fcpupdeluxe\fpc`
6+2. The FPC repository is checked out (same revision as the FPC installation) in another folder `D:\fpcsrc` and used to work on the compiler, thus the .lpi file is opened from this folder.
7+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` on Windows 10 64-bit.
8+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.
9+5. In the menu bar go to *Run* and then click *Run parameters ...* to specify the *Command line parameters*.
10+
11+ An example of command line parameters could look like this:
12+
13+
14+ `-FuD:\Fcpupdeluxe\fpc\units\x86_64-win64* D:\Delphi\tests\test.pas`
15+
16+ Explanation of the command line parameters:
17+
18+ 1. `-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
19+ 2. `D:\Delphi\tests\test.pas` \<- program or unit that should be compiled
20+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).
21+7. Once you added e.g. a new intrinsic to the compiler you need to recompile the RTL:
22+ 1. open Windows CMD
23+ 2. switch to your FPC source folder, type `D:` and `cd D:\fpcsrc\`
24+ 3. compile the system units, type `make rtl PP=D:\fpcsrc\compiler\x86_64\pp`
25+ 4. change the *Command line parameters* in Lazarus to use the new system units in *D:\fpcsrc\rtl\units\x86_64-win64*
26+
27+ `-FuD:\fpcsrc\rtl\units\x86_64-win64`
28+
29+- Notes:
30+ - The FPC installation in `D:\Fcpupdeluxe\fpc` is needed to bootstrap the initial compiler executable
31+ - The system units from `D:\Fcpupdeluxe\fpc` can be used as long as nothing in the compiler is changed that is related to these units, otherwise you need to recompile the system units as well (see steps above)
32+ - If you change any of the compiler source files the *pp* executable will be overwritten to reflect the changes made
33+ - 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`
34+
35+## Debugging FPC Hints
36+
37+- There are some verbosity options (like gcc) to be specified for the command line to show internal representations like
38+ - *-vp*: Write tree.log with parse tree
39+ - *-vv*: Write fpcdebug.txt with lots of debugging info
40+
41+- Place a breakpoint at the `parser.compile` function in Lazarus as this is the entry point for parsing.
42+
43+- 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, ...).
44+
45+- Steps to investigate internal error codes:
46+
47+1. search for the error code in the source folder (e.g. *rgrep* on Linux or *grep -r* from the git bash on Windows)
48+2. open the related file and place a break point on the internal error call
49+3. look at the stack trace to see the call history leading up to this point
50+
51+- Analyse code that leads to an error or warning:
52+
53+1. search for the error/warning code or a short text snippet of the message in the *compiler/msg* folder
54+2. the English message will be in *errore.msg* file, e.g.:
55+
56+ `% The constants are out of their allowed range.`
57+
58+ `parser_e_double_caselabel=03037_E_Duplicate case label`
59+3. locate the constant name of the message (first part of the message before "="), e.g.:
60+
61+ `parser_e_double_caselabel`
62+4. search for this constant in the compiler source files, example output:
63+
64+ `nset.pas: Message(parser_e_double_caselabel);`
65+
66+ `nset.pas: Message(parser_e_double_caselabel);`
67+
68+- The subroutine `printnode(<node>)` allows to print a node and all it's children, this is often usefull when examining node trees at particular locations.
69+
70+- If code is generated that absolutely does not match with what should be generated, a good starting point is to compile with *-al -sr* as this generates the assembly file pre-register allocation. If that one looks alright, you know the issue is in the register allocator/spilling code.
71+
72+- The XML Node output feature can be enabled via `-dDEBUG_NODE_XML` during compiler compilation and it generates a *\<NAME\>-node-dump.xml* file for each unit, program or library compiled, containing a XML description of the nodes handled during compilation of the unit, program or library.
73+
74+---
75+*From the Free Pascal wiki, page "Debugging Compiler", as it stood on 2021-04-20 after a change by Bi0T1N, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
76+Category: Debugging
77+Category: FPC
78+Category: FPC development
79+Category: FPC internals

Back to history