On 2/3/21 5:01 AM, Richard Biener wrote:
On Mon, Feb 1, 2021 at 5:20 PM Martin Sebor <mse...@gmail.com> wrote:
I have pushed the tree.h comments in g:6a2053773b8. I will wait
for an approval of the changes to the manual.
Sorry for not looking earlier.
Sorry, I thought you were fine with the text after your first review.
I'll adjust the tree.h comments when we're done, though I'd like to
think the example in the manual will do a lot more to help make it
clear than the comments in tree.h can.
+/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost"
+ function scope. Inlined functions are chained by this so that given
+ expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope
+ in which E has been made or into which E has been inlined. */
I can't really understand what you are trying to say with the second
sentence. There's
nothing really special about BLOCK_SUPERCONTEXT and inlines so I believe this
sentence only adds confusion.
The sentence explains how SUPERCONTEXT chains inlined blocks. In
the manual diff I show an example:
void f0 (char *p, int n) { memset (p, 1, n); }
void f1 (char *p, int n) { f0 (p + 1, n + 1); }
void f2 (char *p, int n) { f1 (p + 1, n + 1); }
int a[6];
void f3 (char *p, int n) { f2 (a, 3); }
The blocks for all calls inlined into f3 are chained like so:
CALL_EXPR: memset E
BLOCK #13 <--+ TREE_BLOCK (E)
+-- SUPERCONTEXT: BLOCK #12 |
| ABSTRACT_ORIGIN: BLOCK #0 --+
| | |
+-> BLOCK #12 (f1) <--|-+ |
+-- SUPERCONTEXT: BLOCK #10 | | |
| SUBBLOCKS: BLOCK #13 --|-| |
| ABSTRACT_ORIGIN: f0 ---+ | |
| | |
+-> BLOCK #10 (f2) <-+ | |
+--- SUPERCONTEXT: BLOCK #8 | | |
| SUBBLOCKS: BLOCK #12 ---|-| |
| ABSTRACT_ORIGIN: f1 ------+ |
| | |
+-> BLOCK #8 (f3) | |
+---- SUPERCONTEXT: BLOCK #0 | |
| SUBBLOCKS: BLOCK #10 --| |
| ABSTRACT_ORIGIN: f2 ---+ |
| |
+-> BLOCK #0 (f3) <---------------+
SUPERCONTEXT: f3
SUBBLOCKS: BLOCK #8
Does the following sound better? (Dropping the "in which E has been
made.")
Inlined functions are chained by this so that given expression E
and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope into
which E has been inlined.
#define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext)
+/* Points to the next scope at the same level of nesting as scope NODE. */
#define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain)
+/* A BLOCK, or FUNCTION_DECL of the function from which a block has been
+ inlined.
... from which a block has been ultimatively copied for example by inlining.
[clones also will have abstract origins]
In a scope immediately enclosing an inlined leaf expression,
+ points to the outermost scope into which it has been inlined (thus
+ bypassing all intermediate BLOCK_SUPERCONTEXTs). */
?
This describes the long arrow on the right, pointing Block #13's
ABSTRACT_ORIGIN down to Block #0. All the other AO's point down
to the next/enclosing block (arrows on the left). I didn't expect
this when I first worked with the blocks so it seemed like
an important detail to mention.
Maybe: An inlined function is represented by a scope with
BLOCK_ABSTRACT_ORIGIN being the FUNCTION_DECL of the inlined function
containing the inlined functions scope tree as children. All abstract origins
are ultimate, that is BLOCK_ABSTRACT_ORIGIN(NODE)
== BLOCK_ABSTRACT_ORIGIN(BLOCK_ABSTRACT_ORIGIN (NODE)).
The first sentence sounds good to me as far as it goes but it
doesn't capture the long arrow above. (By children I assume you
mean SUBBLOCKS, correct?)
I don't follow what you're trying to say in the second sentence.
The equality isn't true for Block #0 whose AO is null. It also
isn't true for Block #12 and the others whose AO is a DECL, not
a block.
What do you mean by "ultimate" in plain English?
FWIW, if I were to try to explain it using the example I'd say
only Block #13's AO is "ultimate:" it points down in the diagram
to the block of the function into which the expression has
ultimately been inlined. The AO's of all the other intervening
inlined blocks are the DECLs of the inlined callees (up-pointing
arrows); they don't look ultimate to me in this sense.
But however this is phrased I suspect it won't be perfectly clear
without an example or a picture.
Martin
#define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK
(NODE)->block.abstract_origin)
On 1/27/21 5:54 PM, Martin Sebor wrote:
Attached is an updated patch for both tree.h and the internals manual
documenting the most important BLOCK_ macros and what they represent.
On 1/21/21 2:52 PM, Martin Sebor wrote:
On 1/18/21 6:25 AM, Richard Biener wrote:
PS Here are my notes on the macros and the two related functions:
BLOCK: Denotes a lexical scope. Contains BLOCK_VARS of variables
declared in it, BLOCK_SUBBLOCKS of scopes nested in it, and
BLOCK_CHAIN pointing to the next BLOCK. Its BLOCK_SUPERCONTEXT
point to the BLOCK of the enclosing scope. May have
a BLOCK_ABSTRACT_ORIGIN and a BLOCK_SOURCE_LOCATION.
BLOCK_SUPERCONTEXT: The scope of the enclosing block, or FUNCTION_DECL
for the "outermost" function scope. Inlined functions are chained by
this so that given expression E and its TREE_BLOCK(E) B,
BLOCK_SUPERCONTEXT(B) is the scope (BLOCK) in which E has been made
or into which E has been inlined. In the latter case,
BLOCK_ORIGIN(B) evaluates either to the enclosing BLOCK or to
the enclosing function DECL. It's never null.
BLOCK_ABSTRACT_ORIGIN(B) is the FUNCTION_DECL of the function into
which it has been inlined, or null if B is not inlined.
It's the BLOCK or FUNCTION it was inlined _from_, not were it was
inlined to.
It's the "ultimate" source, thus the abstract copy of the block or
function decl
(for the outermost scope, aka inlined_function_outer_scope_p). It
corresponds
to what you'd expect for the DWARF abstract origin.
Thanks for the correction! It's just the "innermost" block that
points to the "ultimate" destination into which it's been inlined.
BLOCK_ABSTRACT_ORIGIN can be NULL (in case it isn't an inline instance).
BLOCK_ABSTRACT_ORIGIN: A BLOCK, or FUNCTION_DECL of the function
into which a block has been inlined. In a BLOCK immediately enclosing
an inlined leaf expression points to the outermost BLOCK into which it
has been inlined (thus bypassing all intermediate BLOCK_SUPERCONTEXTs).
BLOCK_FRAGMENT_ORIGIN: ???
BLOCK_FRAGMENT_CHAIN: ???
that's for scope blocks split by hot/cold partitioning and only
temporarily
populated.
Thanks, I now see these documented in detail in tree.h.
bool inlined_function_outer_scope_p(BLOCK) [tree.h]
Returns true if a BLOCK has a source location.
True for all but the innermost (no SUBBLOCKs?) and outermost blocks
into which an expression has been inlined. (Is this always true?)
tree block_ultimate_origin(BLOCK) [tree.c]
Returns BLOCK_ABSTRACT_ORIGIN(BLOCK), AO, after asserting that
(DECL_P(AO) && DECL_ORIGIN(AO) == AO) || BLOCK_ORIGIN(AO) == AO).
The attached diff adds the comments above to tree.h.
I looked for a good place in the manual to add the same text but I'm
not sure. Would the Blocks @subsection in generic.texi be appropriate?
Martin