Add "phantom let" support and provenance tracking to Flambda
Created by: mshinwell
This pull request deals with the addition of a new construction called "phantom let" to Flambda. Phantom lets behave like normal lets except that they do not generate any code at runtime. They are used as a way of encoding optimised-out parts of the program entirely within the language rather than using some kind of out-of-band mechanism.
This patch also adds support to Flambda for provenance tracking: identifying which variables in the Flambda code came from which variables (equipped with full module paths and locations of definitions) in the source program. The tracking back to original Ident.t
values is necessary so that their original stamps can be retrieved; these are used for lookup of types in .cmt
files in libmonda. The propagation of location information is required so that variables that do not have unique names can be properly disambiguated in the debugger. This location information keeps track of inlined-out frames.
In order for it to compile this pull request has a couple of stubs on the Lambda side and a version of Flambda_to_clambda
that does not deal with phantom lets. This will be added via a subsequent pull request that adds support for them in Clambda and beyond.
Code in this pull request scrapes Lambda expressions for location information. It would probably be better in future to equip Llet
with the necessary location information. There will be another pull request coming in due course in this area, so let's save any discussion on this point for later.
Phantom lets only permit certain kinds of defining expressions for simplicity. @lpw25 suggested this might be a mistake (we may still gain more information about an optimised-out piece of code if it were subsequently inlined), but I think this should stay as-is for the moment. It's probably actually good enough in any case.
When the simplifier determines that a let binding is no longer required it will become eligible for phantomisation. This uses both the structure of the redundant defining expression together with its approximation to try to construct a phantom let which will later be describable in DWARF. The backend support permits the description in DWARF (using "implicit pointers") of structured values that have been optimised out even in the case where such values may reference values that were not optimised out. For example, the structure of a pair may be described in the following manner: the pair was optimised out, but it had size 2 and tag 0, and its contents were the parameters x
and y
of the function, which may be found in some particular registers (also described). At runtime, the debugger will reconstitute the structured value in the address space of the debugger (not the address space of the target program), and the libmonda library's value printers will be able to move seamlessly through the value, unaware that in fact part of it doesn't exist in the target program.
Once case that is not currently supported in the backend is the description of projections from variables known to represent blocks where those variables may in turn be phantom. This problem, together with the fact that we end up generating aliases in the DWARF information between phantom lets (e.g phantom_let x = y
where y
is phantom), is planned to be solved in the future by making Inline_and_simplify
simplify the defining expressions of phantom lets using the techniques it uses for normal lets. This will eliminate aliases and enable us to avoid the case that is unsupported in the backend. (The reason it is unsupported is due to restrictions in the DWARF language.)
Along the way this patch introduces a new module Free_names
for tracking of the various free name sets that we now have. There are some other minor cleanups (e.g. a record type for Let_rec
).
@chambart is on the hook to review this one :)