//===-- LineTable.cpp -------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include <algorithm>

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// LineTable constructor
//----------------------------------------------------------------------
LineTable::LineTable(CompileUnit* comp_unit) :
    m_comp_unit(comp_unit),
    m_entries()
{
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
LineTable::~LineTable()
{
}

void
LineTable::InsertLineEntry
(
    lldb::addr_t file_addr,
    uint32_t line,
    uint16_t column,
    uint16_t file_idx,
    bool is_start_of_statement,
    bool is_start_of_basic_block,
    bool is_prologue_end,
    bool is_epilogue_begin,
    bool is_terminal_entry
)
{
    Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);

    entry_collection::iterator begin_pos = m_entries.begin();
    entry_collection::iterator end_pos = m_entries.end();
    LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
    entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp);

//  Stream s(stdout);
//  s << "\n\nBefore:\n";
//  Dump (&s, Address::DumpStyleFileAddress);
    m_entries.insert(pos, entry);
//  s << "After:\n";
//  Dump (&s, Address::DumpStyleFileAddress);
}

LineSequence::LineSequence()
{
}

void
LineTable::LineSequenceImpl::Clear()
{ 
    m_entries.clear();
}

LineSequence* LineTable::CreateLineSequenceContainer ()
{
    return new LineTable::LineSequenceImpl();
}

void
LineTable::AppendLineEntryToSequence
(
    LineSequence* sequence,
    lldb::addr_t file_addr,
    uint32_t line,
    uint16_t column,
    uint16_t file_idx,
    bool is_start_of_statement,
    bool is_start_of_basic_block,
    bool is_prologue_end,
    bool is_epilogue_begin,
    bool is_terminal_entry
)
{
    assert(sequence != nullptr);
    LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
    Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
    entry_collection &entries = seq->m_entries;
    // Replace the last entry if the address is the same, otherwise append it. If we have multiple
    // line entries at the same address, this indicates illegal DWARF so this "fixes" the line table
    // to be correct. If not fixed this can cause a line entry's address that when resolved back to
    // a symbol context, could resolve to a different line entry. We really want a 1 to 1 mapping
    // here to avoid these kinds of inconsistencies. We will need tor revisit this if the DWARF line
    // tables are updated to allow multiple entries at the same address legally.
    if (!entries.empty() && entries.back().file_addr == file_addr)
    {
        // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue.
        // Instead of it it is issueing a line table entry for the first instruction of the prologue
        // and one for the first instruction after the prologue. If the size of the prologue is 0
        // instruction then the 2 line entry will have the same file address. Removing it will remove
        // our ability to properly detect the location of the end of prologe so we set the prologue_end
        // flag to preserve this information (setting the prologue_end flag for an entry what is after
        // the prologue end don't have any effect)
        entry.is_prologue_end = entry.file_idx == entries.back().file_idx;
        entries.back() = entry;
    }
    else
        entries.push_back (entry);
}

void
LineTable::InsertSequence (LineSequence* sequence)
{
    assert(sequence != nullptr);
    LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
    if (seq->m_entries.empty())
        return;
    Entry& entry = seq->m_entries.front();
    
    // If the first entry address in this sequence is greater than or equal to
    // the address of the last item in our entry collection, just append.
    if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back()))
    {
        m_entries.insert(m_entries.end(),
                         seq->m_entries.begin(),
                         seq->m_entries.end());
        return;
    }

    // Otherwise, find where this belongs in the collection
    entry_collection::iterator begin_pos = m_entries.begin();
    entry_collection::iterator end_pos = m_entries.end();
    LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
    entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp);

    // We should never insert a sequence in the middle of another sequence
    if (pos != begin_pos) {
        while (pos < end_pos && !((pos - 1)->is_terminal_entry))
            pos++;
    }

#ifdef LLDB_CONFIGURATION_DEBUG
    // If we aren't inserting at the beginning, the previous entry should
    // terminate a sequence.
    if (pos != begin_pos)
    {
        entry_collection::iterator prev_pos = pos - 1;
        assert(prev_pos->is_terminal_entry);
    }
#endif
    m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end());
}

//----------------------------------------------------------------------
LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) :
    m_line_table (line_table)
{
}

bool
LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const
{
    #define LT_COMPARE(a,b) if (a != b) return a < b
    LT_COMPARE (a.file_addr, b.file_addr);
    // b and a reversed on purpose below.
    LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry);
    LT_COMPARE (a.line, b.line);
    LT_COMPARE (a.column, b.column);
    LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement);
    LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block);
    // b and a reversed on purpose below.
    LT_COMPARE (b.is_prologue_end, a.is_prologue_end);
    LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin);
    LT_COMPARE (a.file_idx, b.file_idx);
    return false;
    #undef LT_COMPARE
}



uint32_t
LineTable::GetSize() const
{
    return m_entries.size();
}

bool
LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry)
{
    if (idx < m_entries.size())
    {
        ConvertEntryAtIndexToLineEntry (idx, line_entry);
        return true;
    }
    line_entry.Clear();
    return false;
}

bool
LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr)
{
    if (index_ptr != nullptr )
        *index_ptr = UINT32_MAX;

    bool success = false;

    if (so_addr.GetModule().get() == m_comp_unit->GetModule().get())
    {
        Entry search_entry;
        search_entry.file_addr = so_addr.GetFileAddress();
        if (search_entry.file_addr != LLDB_INVALID_ADDRESS)
        {
            entry_collection::const_iterator begin_pos = m_entries.begin();
            entry_collection::const_iterator end_pos = m_entries.end();
            entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan);
            if (pos != end_pos)
            {
                if (pos != begin_pos)
                {
                    if (pos->file_addr != search_entry.file_addr)
                        --pos;
                    else if (pos->file_addr == search_entry.file_addr)
                    {
                        // If this is a termination entry, it shouldn't match since
                        // entries with the "is_terminal_entry" member set to true 
                        // are termination entries that define the range for the 
                        // previous entry.
                        if (pos->is_terminal_entry)
                        {
                            // The matching entry is a terminal entry, so we skip
                            // ahead to the next entry to see if there is another
                            // entry following this one whose section/offset matches.
                            ++pos;
                            if (pos != end_pos)
                            {
                                if (pos->file_addr != search_entry.file_addr)
                                    pos = end_pos;
                            }
                        }
                        
                        if (pos != end_pos)
                        {
                            // While in the same section/offset backup to find the first
                            // line entry that matches the address in case there are 
                            // multiple
                            while (pos != begin_pos)
                            {
                                entry_collection::const_iterator prev_pos = pos - 1;
                                if (prev_pos->file_addr == search_entry.file_addr &&
                                    prev_pos->is_terminal_entry == false)
                                    --pos;
                                else
                                    break;
                            }
                        }
                    }

                }
                
                // Make sure we have a valid match and that the match isn't a terminating
                // entry for a previous line...
                if (pos != end_pos && pos->is_terminal_entry == false)
                {
                    uint32_t match_idx = std::distance (begin_pos, pos);
                    success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
                    if (index_ptr != nullptr && success)
                        *index_ptr = match_idx;
                }
            }
        }
    }
    return success;
}


bool
LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry)
{
    if (idx < m_entries.size())
    {
        const Entry& entry = m_entries[idx];
        ModuleSP module_sp (m_comp_unit->GetModule());
        if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress()))
        {
            if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
                line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr);
            else
                line_entry.range.SetByteSize(0);

            line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx);
            line_entry.original_file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx);
            line_entry.line = entry.line;
            line_entry.column = entry.column;
            line_entry.is_start_of_statement = entry.is_start_of_statement;
            line_entry.is_start_of_basic_block = entry.is_start_of_basic_block;
            line_entry.is_prologue_end = entry.is_prologue_end;
            line_entry.is_epilogue_begin = entry.is_epilogue_begin;
            line_entry.is_terminal_entry = entry.is_terminal_entry;
            return true;
        }
    }
    return false;
}

uint32_t
LineTable::FindLineEntryIndexByFileIndex 
(
    uint32_t start_idx, 
    const std::vector<uint32_t> &file_indexes, 
    uint32_t line, 
    bool exact, 
    LineEntry* line_entry_ptr
)
{

    const size_t count = m_entries.size();
    std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin();
    std::vector<uint32_t>::const_iterator end_pos = file_indexes.end();
    size_t best_match = UINT32_MAX;

    for (size_t idx = start_idx; idx < count; ++idx)
    {
        // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
        if (m_entries[idx].is_terminal_entry)
            continue;

        if (find (begin_pos, end_pos, m_entries[idx].file_idx) == end_pos)
            continue;

        // Exact match always wins.  Otherwise try to find the closest line > the desired
        // line.
        // FIXME: Maybe want to find the line closest before and the line closest after and
        // if they're not in the same function, don't return a match.

        if (m_entries[idx].line < line)
        {
            continue;
        }
        else if (m_entries[idx].line == line)
        {
            if (line_entry_ptr)
                ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr);
            return idx;
        }
        else if (!exact)
        {
            if (best_match == UINT32_MAX)
                best_match = idx;
            else if (m_entries[idx].line < m_entries[best_match].line)
                best_match = idx;
        }
    }

    if (best_match != UINT32_MAX)
    {
        if (line_entry_ptr)
            ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr);
        return best_match;
    }
    return UINT32_MAX;
}

uint32_t
LineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr)
{
    const size_t count = m_entries.size();
    size_t best_match = UINT32_MAX;

    for (size_t idx = start_idx; idx < count; ++idx)
    {
        // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
        if (m_entries[idx].is_terminal_entry)
            continue;

        if (m_entries[idx].file_idx != file_idx)
            continue;

        // Exact match always wins.  Otherwise try to find the closest line > the desired
        // line.
        // FIXME: Maybe want to find the line closest before and the line closest after and
        // if they're not in the same function, don't return a match.

        if (m_entries[idx].line < line)
        {
            continue;
        }
        else if (m_entries[idx].line == line)
        {
            if (line_entry_ptr)
                ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr);
            return idx;
        }
        else if (!exact)
        {
            if (best_match == UINT32_MAX)
                best_match = idx;
            else if (m_entries[idx].line < m_entries[best_match].line)
                best_match = idx;
        }
    }

    if (best_match != UINT32_MAX)
    {
        if (line_entry_ptr)
            ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr);
        return best_match;
    }
    return UINT32_MAX;
}

size_t
LineTable::FineLineEntriesForFileIndex (uint32_t file_idx, 
                                        bool append,
                                        SymbolContextList &sc_list)
{
    
    if (!append)
        sc_list.Clear();

    size_t num_added = 0;
    const size_t count = m_entries.size();
    if (count > 0)
    {
        SymbolContext sc (m_comp_unit);

        for (size_t idx = 0; idx < count; ++idx)
        {
            // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
            if (m_entries[idx].is_terminal_entry)
                continue;
            
            if (m_entries[idx].file_idx == file_idx)
            {
                if (ConvertEntryAtIndexToLineEntry (idx, sc.line_entry))
                {
                    ++num_added;
                    sc_list.Append(sc);
                }
            }
        }
    }
    return num_added;
}


void
LineTable::Dump (Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges)
{
    const size_t count = m_entries.size();
    LineEntry line_entry;
    FileSpec prev_file;
    for (size_t idx = 0; idx < count; ++idx)
    {
        ConvertEntryAtIndexToLineEntry (idx, line_entry);
        line_entry.Dump (s, target, prev_file != line_entry.original_file, style, fallback_style, show_line_ranges);
        s->EOL();
        prev_file = line_entry.original_file;
    }
}


void
LineTable::GetDescription (Stream *s, Target *target, DescriptionLevel level)
{
    const size_t count = m_entries.size();
    LineEntry line_entry;
    for (size_t idx = 0; idx < count; ++idx)
    {
        ConvertEntryAtIndexToLineEntry (idx, line_entry);
        line_entry.GetDescription (s, level, m_comp_unit, target, true);
        s->EOL();
    }
}

size_t
LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append)
{
    if (!append)
        file_ranges.Clear();
    const size_t initial_count = file_ranges.GetSize();
    
    const size_t count = m_entries.size();
    LineEntry line_entry;
    FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0);
    for (size_t idx = 0; idx < count; ++idx)
    {
        const Entry& entry = m_entries[idx];

        if (entry.is_terminal_entry)
        {
            if (range.GetRangeBase() != LLDB_INVALID_ADDRESS)
            {
                range.SetRangeEnd(entry.file_addr);
                file_ranges.Append(range);
                range.Clear(LLDB_INVALID_ADDRESS);
            }
        }
        else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS)
        {
            range.SetRangeBase(entry.file_addr);
        }
    }
    return file_ranges.GetSize() - initial_count;
}

LineTable *
LineTable::LinkLineTable (const FileRangeMap &file_range_map)
{
    std::unique_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit));
    LineSequenceImpl sequence;
    const size_t count = m_entries.size();
    LineEntry line_entry;
    const FileRangeMap::Entry *file_range_entry = nullptr;
    const FileRangeMap::Entry *prev_file_range_entry = nullptr;
    lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS;
    bool prev_entry_was_linked = false;
    bool range_changed = false;
    for (size_t idx = 0; idx < count; ++idx)
    {
        const Entry& entry = m_entries[idx];
        
        const bool end_sequence = entry.is_terminal_entry;
        const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0);
        if (file_range_entry == nullptr || !file_range_entry->Contains(lookup_file_addr))
        {
            prev_file_range_entry = file_range_entry;
            file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr);
            range_changed = true;
        }

        lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS;
        lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS;

        bool terminate_previous_entry = false;
        if (file_range_entry)
        {
            entry_linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data;
            // Determine if we need to terminate the previous entry when the previous
            // entry was not contiguous with this one after being linked.
            if (range_changed && prev_file_range_entry)
            {
                prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr, prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
                if (prev_end_entry_linked_file_addr != entry_linked_file_addr)
                    terminate_previous_entry = prev_entry_was_linked;                
            }
        }
        else if (prev_entry_was_linked)
        {
            // This entry doesn't have a remapping and it needs to be removed.
            // Watch out in case we need to terminate a previous entry needs to
            // be terminated now that one line entry in a sequence is not longer valid.
            if (!sequence.m_entries.empty() &&
                !sequence.m_entries.back().is_terminal_entry)
            {
                terminate_previous_entry = true;
            }
        }
        
        if (terminate_previous_entry && !sequence.m_entries.empty())
        {
            assert (prev_file_addr != LLDB_INVALID_ADDRESS);
            sequence.m_entries.push_back(sequence.m_entries.back());
            if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS)
                prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr,prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
            sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr;
            sequence.m_entries.back().is_terminal_entry = true;

            // Append the sequence since we just terminated the previous one
            line_table_ap->InsertSequence (&sequence);
            sequence.Clear();
        }
        
        // Now link the current entry
        if (file_range_entry)
        {
            // This entry has an address remapping and it needs to have its address relinked
            sequence.m_entries.push_back(entry);
            sequence.m_entries.back().file_addr = entry_linked_file_addr;
        }

        // If we have items in the sequence and the last entry is a terminal entry,
        // insert this sequence into our new line table.
        if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry)
        {
            line_table_ap->InsertSequence (&sequence);
            sequence.Clear();
            prev_entry_was_linked = false;
        }
        else
        {
            prev_entry_was_linked = file_range_entry != nullptr;
        }
        prev_file_addr = entry.file_addr;
        range_changed = false;
    }
    if (line_table_ap->m_entries.empty())
        return nullptr;
    return line_table_ap.release();
}




