>> +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

Reply via email to