bool dwarf_cfa_state::set_register()

in Source/PLCrashAsyncDwarfCFAState.cpp [118:167]


bool dwarf_cfa_state<machine_ptr, machine_ptr_s>::set_register (dwarf_cfa_state_regnum_t regnum, plcrash_dwarf_cfa_reg_rule_t rule, machine_ptr value) {
    /* Check for an existing entry, or find the target entry off which we'll chain our entry */
    unsigned int bucket = regnum % (sizeof(_table_stack[0]) / sizeof(_table_stack[0][0]));
    
    dwarf_cfa_reg_entry_t *parent = NULL;
    for (uint8_t parent_idx = _table_stack[_table_depth][bucket]; parent_idx != DWARF_CFA_STATE_INVALID_ENTRY_IDX; parent_idx = parent->next) {
        parent = &_entries[parent_idx];
        
        /* If an existing entry is found, we can re-use it directly */
        if (parent->regnum == regnum) {
            parent->value = value;
            parent->rule = rule;
            return true;
        }
        
        /* Otherwise, make sure we terminate with parent == last element */
        if (parent->next == DWARF_CFA_STATE_INVALID_ENTRY_IDX)
            break;
    }
    
    /* 'parent' now either points to the end of the list, or is NULL (in which case the table
     * slot was empty */
    dwarf_cfa_reg_entry *entry = NULL;
    uint8_t entry_idx;
    
    /* Fetch a free entry */
    if (_free_list == DWARF_CFA_STATE_INVALID_ENTRY_IDX) {
        /* No free entries */
        return false;
    }
    entry_idx = _free_list;
    entry = &_entries[entry_idx];
    _free_list = entry->next;
    
    /* Intialize the entry */
    entry->regnum = regnum;
    entry->rule = rule;
    entry->value = value;
    entry->next = DWARF_CFA_STATE_INVALID_ENTRY_IDX;
    
    /* Either insert in the parent, or insert as the first table element */
    if (parent == NULL) {
        _table_stack[_table_depth][bucket] = entry_idx;
    } else {
        parent->next = entry - _entries;
    }
    
    _register_count[_table_depth]++;
    return true;
}