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