>> +static subprog_entry *
>> +add_subprog_entry (tree decl, bool is_inlined)
>> +{
>> + subprog_entry **slot;
>> + subprog_entry *entry;
>> +
>> + slot = subprog_table->find_slot_with_hash (decl, DECL_UID (decl), INSERT);
>> + if (*slot == HTAB_EMPTY_ENTRY)
>> + {
>> + entry = XCNEW (struct subprog_entry);
>> + entry->decl = decl;
>> + entry->is_inlined = is_inlined;
>> + entry->subprog_num = 0;
>> + *slot = entry;
>> + }
>> + else if (is_inlined)
>
> When will the logic go into else branch?
When we already have an entry for the given subprogram (e.g., the same
subroutine gets inlined in multiple places).
>> +/* For two-level line tables, a map from block number to an
>> + inlined call chain. */
>> +
>> +struct block_entry
>> +{
>> + unsigned int block_num;
>> + struct subprog_entry *subprog;
>> + struct block_entry *caller;
>> + location_t caller_loc;
>> +};
>> +
>> +struct block_hasher : typed_free_remove <block_entry>
>> +{
>> + typedef block_entry value_type;
>> + typedef unsigned int compare_type;
>> + static hashval_t hash (const value_type *);
>> + static bool equal (const value_type *, const compare_type *);
>> +};
>> +
>> +inline hashval_t
>> +block_hasher::hash (const value_type *p)
>> +{
>> + return (hashval_t) p->block_num;
>> +}
>> +
>> +inline bool
>> +block_hasher::equal (const value_type *p1, const compare_type *p2)
>> +{
>> + return p1->block_num == *p2;
>> +}
>> +
>> +static hash_table<block_hasher> *block_table;
>
> Not quite clear why we need block_table. This table is not gonna be
> emitted. And we can easily get subprog_entry through block->block_num
When final_scan_insn() calls dwarf2out_begin_block(), all it passes is
a block number. I don't know a way to get from block number to the
block, so I traverse all the blocks of a function when
dwarf2out_begin_function() is called, and build this table. Now in
dwarf2out_source_line, I can look at the current block number and tell
what the inline call stack is.
>> +#ifdef DEBUG_TWO_LEVEL
>> + static unsigned int level = 0;
>> +#endif
>> +
>> + if (block == NULL)
>> + return;
>> +
>> +#ifdef DEBUG_TWO_LEVEL
>
> Shall this be controlled by dump options with TDF_DETAILS dump_flag?
I don't see the need -- I'll rip this out before submitting for trunk.
I'd have ripped it out already, but thought it might be useful for a
little while longer.
>> + block_num = BLOCK_NUMBER (block);
>> + slot = block_table->find_slot_with_hash (&block_num, (hashval_t)
>> block_num, INSERT);
>> + if (*slot != HTAB_EMPTY_ENTRY)
>
> Instead of return, can you assert that the data stored in *slot is
> consistent with the new data? Or should *slot never be
> HTAB_EMPTY_ENTRY?
It should probably be consistent, but I wasn't absolutely sure, and I
didn't want to have the compiler crash when either version of the data
is probably good enough. It might not be empty, because I might have
already added the block number to the table in the loop over the
parent node's BLOCK_FRAGMENT_CHAIN. (I may not need to have that loop
at all, if it's always the case that the blocks in
BLOCK_FRAGMENT_CHAIN are also contained in the subtree under
BLOCK_SUBBLOCKS. I'm being conservative here.)
-cary